zinfer 0.0.1 → 0.1.2

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.
Files changed (79) hide show
  1. package/README.md +477 -28
  2. package/bin/zinfer +2 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +486 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/brand-detector.d.ts +32 -0
  8. package/dist/core/brand-detector.d.ts.map +1 -0
  9. package/dist/core/brand-detector.js +121 -0
  10. package/dist/core/brand-detector.js.map +1 -0
  11. package/dist/core/config-loader.d.ts +87 -0
  12. package/dist/core/config-loader.d.ts.map +1 -0
  13. package/dist/core/config-loader.js +105 -0
  14. package/dist/core/config-loader.js.map +1 -0
  15. package/dist/core/description-extractor.d.ts +54 -0
  16. package/dist/core/description-extractor.d.ts.map +1 -0
  17. package/dist/core/description-extractor.js +180 -0
  18. package/dist/core/description-extractor.js.map +1 -0
  19. package/dist/core/errors.d.ts +35 -0
  20. package/dist/core/errors.d.ts.map +1 -0
  21. package/dist/core/errors.js +96 -0
  22. package/dist/core/errors.js.map +1 -0
  23. package/dist/core/extractor.d.ts +121 -0
  24. package/dist/core/extractor.d.ts.map +1 -0
  25. package/dist/core/extractor.js +504 -0
  26. package/dist/core/extractor.js.map +1 -0
  27. package/dist/core/file-resolver.d.ts +41 -0
  28. package/dist/core/file-resolver.d.ts.map +1 -0
  29. package/dist/core/file-resolver.js +95 -0
  30. package/dist/core/file-resolver.js.map +1 -0
  31. package/dist/core/getter-resolver.d.ts +67 -0
  32. package/dist/core/getter-resolver.d.ts.map +1 -0
  33. package/dist/core/getter-resolver.js +234 -0
  34. package/dist/core/getter-resolver.js.map +1 -0
  35. package/dist/core/import-resolver.d.ts +51 -0
  36. package/dist/core/import-resolver.d.ts.map +1 -0
  37. package/dist/core/import-resolver.js +158 -0
  38. package/dist/core/import-resolver.js.map +1 -0
  39. package/dist/core/index.d.ts +14 -0
  40. package/dist/core/index.d.ts.map +1 -0
  41. package/dist/core/index.js +13 -0
  42. package/dist/core/index.js.map +1 -0
  43. package/dist/core/logger.d.ts +20 -0
  44. package/dist/core/logger.d.ts.map +1 -0
  45. package/dist/core/logger.js +36 -0
  46. package/dist/core/logger.js.map +1 -0
  47. package/dist/core/name-mapper.d.ts +45 -0
  48. package/dist/core/name-mapper.d.ts.map +1 -0
  49. package/dist/core/name-mapper.js +82 -0
  50. package/dist/core/name-mapper.js.map +1 -0
  51. package/dist/core/normalizer.d.ts +24 -0
  52. package/dist/core/normalizer.d.ts.map +1 -0
  53. package/dist/core/normalizer.js +50 -0
  54. package/dist/core/normalizer.js.map +1 -0
  55. package/dist/core/schema-detector.d.ts +49 -0
  56. package/dist/core/schema-detector.d.ts.map +1 -0
  57. package/dist/core/schema-detector.js +272 -0
  58. package/dist/core/schema-detector.js.map +1 -0
  59. package/dist/core/schema-reference-analyzer.d.ts +77 -0
  60. package/dist/core/schema-reference-analyzer.d.ts.map +1 -0
  61. package/dist/core/schema-reference-analyzer.js +269 -0
  62. package/dist/core/schema-reference-analyzer.js.map +1 -0
  63. package/dist/core/test-generator.d.ts +97 -0
  64. package/dist/core/test-generator.d.ts.map +1 -0
  65. package/dist/core/test-generator.js +177 -0
  66. package/dist/core/test-generator.js.map +1 -0
  67. package/dist/core/type-printer.d.ts +46 -0
  68. package/dist/core/type-printer.d.ts.map +1 -0
  69. package/dist/core/type-printer.js +519 -0
  70. package/dist/core/type-printer.js.map +1 -0
  71. package/dist/core/types.d.ts +124 -0
  72. package/dist/core/types.d.ts.map +1 -0
  73. package/dist/core/types.js +5 -0
  74. package/dist/core/types.js.map +1 -0
  75. package/dist/index.d.ts +66 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +79 -0
  78. package/dist/index.js.map +1 -0
  79. package/package.json +63 -7
package/dist/cli.js ADDED
@@ -0,0 +1,486 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { resolve, dirname, basename, relative, parse as parsePath } from "pathe";
4
+ import { existsSync, writeFileSync, mkdirSync } from "fs";
5
+ import { ZodTypeExtractor, generateDeclarationFile, NameMapper, FileResolver, DescriptionExtractor, ConfigLoader, formatError, NoFilesMatchedError, NoSchemasFoundError, InvalidOptionError, generateTypeTests, generateImportPrefix, setVerbose, logVerbose, logProgress, } from "./core/index.js";
6
+ const program = new Command();
7
+ program.name("zinfer").description("Extract input/output types from Zod schemas").version("0.1.0");
8
+ program
9
+ .argument("[files...]", "File paths or glob patterns")
10
+ .option("-c, --config <path>", "Path to config file")
11
+ .option("-p, --project <path>", "Path to tsconfig.json")
12
+ .option("--schemas <names>", "Comma-separated schema names to extract")
13
+ .option("--input-only", "Output only input types")
14
+ .option("--output-only", "Output only output types")
15
+ .option("--merge-same", "Single type if input===output")
16
+ .option("--suffix <suffix>", "Remove suffix from schema names (e.g., 'Schema')")
17
+ .option("--input-suffix <suffix>", "Suffix for input type names (default: 'Input')")
18
+ .option("--output-suffix <suffix>", "Suffix for output type names (default: 'Output')")
19
+ .option("--map <mappings>", "Custom name mappings (e.g., 'UserSchema:User')")
20
+ .option("--outDir <dir>", "Output directory for generated files")
21
+ .option("--outFile <file>", "Single output file for all types")
22
+ .option("--outPattern <pattern>", "Output file naming pattern (e.g., '[name].types.ts')")
23
+ .option("-d, --declaration", "Generate .d.ts files")
24
+ .option("--dry-run", "Preview without writing files")
25
+ .option("--with-descriptions", "Include Zod .describe() as TSDoc comments")
26
+ .option("--generate-tests", "Generate vitest type equality tests alongside type files")
27
+ .option("-v, --verbose", "Enable verbose output")
28
+ .action(async (files, options) => {
29
+ try {
30
+ await runCLI(files, options);
31
+ }
32
+ catch (error) {
33
+ console.error(formatError(error));
34
+ process.exit(1);
35
+ }
36
+ });
37
+ program.parse();
38
+ /**
39
+ * Main CLI execution logic.
40
+ */
41
+ async function runCLI(files, options) {
42
+ const cwd = process.cwd();
43
+ // Enable verbose mode if requested
44
+ if (options.verbose) {
45
+ setVerbose(true);
46
+ logVerbose("Verbose mode enabled");
47
+ }
48
+ // Load config file
49
+ logVerbose("Loading configuration...");
50
+ const configLoader = new ConfigLoader();
51
+ const { config: fileConfig } = await configLoader.load(cwd);
52
+ // Merge CLI options with config file (CLI takes precedence)
53
+ const config = mergeCliWithConfig(options, fileConfig);
54
+ // Validate options
55
+ validateOptions(config);
56
+ logVerbose("Configuration validated");
57
+ // Use files from CLI args, or from config, or fail
58
+ const inputFiles = files.length > 0 ? files : config.include || [];
59
+ if (inputFiles.length === 0) {
60
+ throw new NoFilesMatchedError(["(no files specified)"]);
61
+ }
62
+ // Resolve file paths (support glob patterns)
63
+ logVerbose("Resolving input files...");
64
+ const fileResolver = new FileResolver();
65
+ const resolvedFiles = await fileResolver.resolveInputFiles(inputFiles, cwd);
66
+ if (resolvedFiles.length === 0) {
67
+ throw new NoFilesMatchedError(inputFiles);
68
+ }
69
+ logVerbose(`Found ${resolvedFiles.length} file(s) to process`);
70
+ // Find tsconfig
71
+ const tsconfigPath = config.project ? resolve(cwd, config.project) : findTsConfig(cwd);
72
+ logVerbose(`Using tsconfig: ${tsconfigPath || "(none)"}`);
73
+ // Validate --generate-tests requires file output
74
+ if (config.generateTests && !config.outDir && !config.outFile) {
75
+ throw new Error("--generate-tests requires --outDir or --outFile");
76
+ }
77
+ // Create extractor and name mapper
78
+ const extractor = new ZodTypeExtractor(tsconfigPath);
79
+ const nameMapper = createNameMapper(config);
80
+ const descriptionExtractor = config.withDescriptions ? new DescriptionExtractor() : null;
81
+ // Parse schema names if specified
82
+ const schemaFilter = config.schemas;
83
+ // Output options
84
+ const outputOptions = {
85
+ outDir: config.outDir,
86
+ outFile: config.outFile,
87
+ outPattern: config.outPattern,
88
+ declaration: config.declaration,
89
+ };
90
+ // Declaration options
91
+ const declOptions = {
92
+ inputOnly: config.inputOnly,
93
+ outputOnly: config.outputOnly,
94
+ mergeSame: config.mergeSame,
95
+ };
96
+ // Single output file mode
97
+ if (config.outFile) {
98
+ logVerbose("Processing files for single output...");
99
+ const allResults = [];
100
+ const fileResultsMap = new Map();
101
+ for (let i = 0; i < resolvedFiles.length; i++) {
102
+ const filePath = resolvedFiles[i];
103
+ logProgress(i + 1, resolvedFiles.length, `Processing ${basename(filePath)}`);
104
+ let results = getFilteredResults(extractor, filePath, schemaFilter);
105
+ // Add descriptions if enabled
106
+ if (descriptionExtractor) {
107
+ results = await addDescriptionsToResults(descriptionExtractor, filePath, results);
108
+ }
109
+ if (results.length > 0) {
110
+ allResults.push(...results);
111
+ fileResultsMap.set(filePath, results);
112
+ }
113
+ }
114
+ if (allResults.length === 0) {
115
+ throw new NoSchemasFoundError(resolvedFiles, schemaFilter);
116
+ }
117
+ const content = generateDeclarationFile(allResults, nameMapper.createMapFunction(), declOptions);
118
+ const outputPath = resolve(cwd, config.outFile);
119
+ if (options.dryRun) {
120
+ console.log(`Would write to: ${outputPath}`);
121
+ console.log("---");
122
+ console.log(content);
123
+ }
124
+ else {
125
+ ensureDir(dirname(outputPath));
126
+ writeFile(outputPath, content);
127
+ console.log(`Generated: ${outputPath} (${allResults.length} types)`);
128
+ }
129
+ // Generate test file if requested
130
+ if (config.generateTests) {
131
+ const testPath = outputPath.replace(/\.ts$/, ".test.ts");
132
+ const testContent = generateTestFileForSingleOutput(fileResultsMap, outputPath, testPath, nameMapper);
133
+ if (options.dryRun) {
134
+ console.log(`Would write to: ${testPath}`);
135
+ console.log("---");
136
+ console.log(testContent);
137
+ }
138
+ else {
139
+ writeFile(testPath, testContent);
140
+ console.log(`Generated: ${testPath} (${allResults.length * 2} test cases)`);
141
+ }
142
+ }
143
+ return;
144
+ }
145
+ // Per-file output mode or console output
146
+ logVerbose("Processing files...");
147
+ let totalResults = 0;
148
+ for (let i = 0; i < resolvedFiles.length; i++) {
149
+ const filePath = resolvedFiles[i];
150
+ logProgress(i + 1, resolvedFiles.length, `Processing ${basename(filePath)}`);
151
+ let results = getFilteredResults(extractor, filePath, schemaFilter);
152
+ if (results.length === 0) {
153
+ logVerbose(` No schemas found in ${basename(filePath)}`);
154
+ continue;
155
+ }
156
+ totalResults += results.length;
157
+ // Add descriptions if enabled
158
+ if (descriptionExtractor) {
159
+ results = await addDescriptionsToResults(descriptionExtractor, filePath, results);
160
+ }
161
+ // File output mode
162
+ if (config.outDir || config.outPattern) {
163
+ const content = generateDeclarationFile(results, nameMapper.createMapFunction(), declOptions);
164
+ const outputPath = fileResolver.resolveOutputPath(filePath, outputOptions, cwd);
165
+ if (options.dryRun) {
166
+ console.log(`Would write to: ${outputPath}`);
167
+ console.log("---");
168
+ console.log(content);
169
+ console.log("");
170
+ }
171
+ else {
172
+ ensureDir(dirname(outputPath));
173
+ writeFile(outputPath, content);
174
+ console.log(`Generated: ${outputPath} (${results.length} types)`);
175
+ }
176
+ // Generate test file if requested
177
+ if (config.generateTests) {
178
+ const testPath = outputPath.replace(/\.ts$/, ".test.ts");
179
+ const testContent = generateTestFileForPerFile(filePath, outputPath, testPath, results, nameMapper);
180
+ if (options.dryRun) {
181
+ console.log(`Would write to: ${testPath}`);
182
+ console.log("---");
183
+ console.log(testContent);
184
+ console.log("");
185
+ }
186
+ else {
187
+ writeFile(testPath, testContent);
188
+ console.log(`Generated: ${testPath} (${results.length * 2} test cases)`);
189
+ }
190
+ }
191
+ }
192
+ else {
193
+ // Console output mode
194
+ if (resolvedFiles.length > 1) {
195
+ console.log(`// File: ${filePath}`);
196
+ }
197
+ const content = generateDeclarationFile(results, nameMapper.createMapFunction(), declOptions);
198
+ console.log(content);
199
+ }
200
+ }
201
+ // Error if no schemas were found
202
+ if (totalResults === 0) {
203
+ throw new NoSchemasFoundError(resolvedFiles, schemaFilter);
204
+ }
205
+ }
206
+ /**
207
+ * Adds descriptions from Zod schemas to extraction results.
208
+ */
209
+ async function addDescriptionsToResults(descriptionExtractor, filePath, results) {
210
+ const schemaNames = results.map((r) => r.schemaName);
211
+ const descriptions = await descriptionExtractor.extractDescriptions(filePath, schemaNames);
212
+ return results.map((result) => {
213
+ const desc = descriptions.get(result.schemaName);
214
+ if (!desc) {
215
+ return result;
216
+ }
217
+ return {
218
+ ...result,
219
+ description: desc.description,
220
+ fieldDescriptions: desc.fields,
221
+ };
222
+ });
223
+ }
224
+ /**
225
+ * Gets extraction results, filtering by schema names if specified.
226
+ * Only extracts schemas that actually exist in the file.
227
+ */
228
+ function getFilteredResults(extractor, filePath, schemaFilter) {
229
+ if (!schemaFilter) {
230
+ return extractor.extractAll(filePath);
231
+ }
232
+ const existingSchemas = extractor.getSchemaNames(filePath);
233
+ const schemasToExtract = schemaFilter.filter((name) => existingSchemas.includes(name));
234
+ if (schemasToExtract.length === 0) {
235
+ return [];
236
+ }
237
+ return extractor.extractMultiple(filePath, schemasToExtract);
238
+ }
239
+ /**
240
+ * Merges CLI options with config file options.
241
+ * CLI options take precedence.
242
+ */
243
+ function mergeCliWithConfig(cliOptions, fileConfig) {
244
+ const merged = { ...fileConfig };
245
+ // Merge CLI options (only non-undefined values)
246
+ if (cliOptions.project !== undefined)
247
+ merged.project = cliOptions.project;
248
+ if (cliOptions.schemas !== undefined) {
249
+ merged.schemas = parseSchemaNames(cliOptions.schemas);
250
+ }
251
+ if (cliOptions.inputOnly !== undefined)
252
+ merged.inputOnly = cliOptions.inputOnly;
253
+ if (cliOptions.outputOnly !== undefined)
254
+ merged.outputOnly = cliOptions.outputOnly;
255
+ if (cliOptions.mergeSame !== undefined)
256
+ merged.mergeSame = cliOptions.mergeSame;
257
+ if (cliOptions.suffix !== undefined)
258
+ merged.suffix = cliOptions.suffix;
259
+ if (cliOptions.inputSuffix !== undefined)
260
+ merged.inputSuffix = cliOptions.inputSuffix;
261
+ if (cliOptions.outputSuffix !== undefined)
262
+ merged.outputSuffix = cliOptions.outputSuffix;
263
+ if (cliOptions.map !== undefined) {
264
+ merged.map = parseCustomMap(cliOptions.map);
265
+ }
266
+ if (cliOptions.outDir !== undefined)
267
+ merged.outDir = cliOptions.outDir;
268
+ if (cliOptions.outFile !== undefined)
269
+ merged.outFile = cliOptions.outFile;
270
+ if (cliOptions.outPattern !== undefined)
271
+ merged.outPattern = cliOptions.outPattern;
272
+ if (cliOptions.declaration !== undefined)
273
+ merged.declaration = cliOptions.declaration;
274
+ if (cliOptions.withDescriptions !== undefined)
275
+ merged.withDescriptions = cliOptions.withDescriptions;
276
+ if (cliOptions.generateTests !== undefined)
277
+ merged.generateTests = cliOptions.generateTests;
278
+ return merged;
279
+ }
280
+ /**
281
+ * Validates CLI options for conflicts and invalid values.
282
+ * @throws InvalidOptionError if any validation fails
283
+ */
284
+ function validateOptions(config) {
285
+ // Check mutually exclusive options
286
+ if (config.inputOnly && config.outputOnly) {
287
+ throw new InvalidOptionError("--input-only / --output-only", "Cannot use both options together", "Use only one of --input-only or --output-only");
288
+ }
289
+ // Check conflicting output options
290
+ if (config.outFile && (config.outDir || config.outPattern)) {
291
+ throw new InvalidOptionError("--outFile", "Cannot use with --outDir or --outPattern", "Use --outFile for single output, or --outDir/--outPattern for multiple outputs");
292
+ }
293
+ // Check empty suffix
294
+ if (config.suffix === "") {
295
+ throw new InvalidOptionError("--suffix", "Empty suffix is not allowed", "Provide a non-empty suffix value or omit the option");
296
+ }
297
+ }
298
+ /**
299
+ * Creates a NameMapper from config.
300
+ */
301
+ function createNameMapper(config) {
302
+ const mappingOptions = {};
303
+ if (config.suffix) {
304
+ mappingOptions.removeSuffix = config.suffix;
305
+ }
306
+ if (config.inputSuffix != null) {
307
+ mappingOptions.inputSuffix = config.inputSuffix;
308
+ }
309
+ if (config.outputSuffix != null) {
310
+ mappingOptions.outputSuffix = config.outputSuffix;
311
+ }
312
+ if (config.map) {
313
+ mappingOptions.customMap = config.map;
314
+ }
315
+ return new NameMapper(mappingOptions);
316
+ }
317
+ /**
318
+ * Parses schema names from a comma-separated string.
319
+ * Filters out empty strings and validates identifier format.
320
+ *
321
+ * @param schemasStr - Comma-separated schema names
322
+ * @returns Array of valid schema names
323
+ * @throws Error if any schema name is invalid
324
+ */
325
+ function parseSchemaNames(schemasStr) {
326
+ const schemas = schemasStr
327
+ .split(",")
328
+ .map((s) => s.trim())
329
+ .filter((s) => s.length > 0);
330
+ // Validate that each schema name is a valid identifier
331
+ const identifierPattern = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
332
+ for (const schema of schemas) {
333
+ if (!identifierPattern.test(schema)) {
334
+ throw new Error(`Invalid schema name: "${schema}". Schema names must be valid TypeScript identifiers.`);
335
+ }
336
+ }
337
+ return schemas;
338
+ }
339
+ /**
340
+ * Parses custom mapping string: "Schema1:Type1,Schema2:Type2"
341
+ * Validates both schema names and type names.
342
+ *
343
+ * @param mapStr - Custom mapping string
344
+ * @returns Map of schema names to type names
345
+ * @throws Error if any mapping is invalid
346
+ */
347
+ function parseCustomMap(mapStr) {
348
+ const result = {};
349
+ const identifierPattern = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
350
+ for (const pair of mapStr.split(",")) {
351
+ const trimmedPair = pair.trim();
352
+ if (!trimmedPair)
353
+ continue;
354
+ const colonIndex = trimmedPair.indexOf(":");
355
+ if (colonIndex === -1) {
356
+ throw new Error(`Invalid mapping format: "${trimmedPair}". Expected "SchemaName:TypeName".`);
357
+ }
358
+ const from = trimmedPair.substring(0, colonIndex).trim();
359
+ const to = trimmedPair.substring(colonIndex + 1).trim();
360
+ if (!from || !to) {
361
+ throw new Error(`Invalid mapping: "${trimmedPair}". Both schema name and type name are required.`);
362
+ }
363
+ if (!identifierPattern.test(from)) {
364
+ throw new Error(`Invalid schema name in mapping: "${from}". Must be a valid TypeScript identifier.`);
365
+ }
366
+ if (!identifierPattern.test(to)) {
367
+ throw new Error(`Invalid type name in mapping: "${to}". Must be a valid TypeScript identifier.`);
368
+ }
369
+ if (result[from] !== undefined) {
370
+ console.warn(`Warning: Duplicate mapping for "${from}". Using "${to}" (overwriting "${result[from]}").`);
371
+ }
372
+ result[from] = to;
373
+ }
374
+ return result;
375
+ }
376
+ /**
377
+ * Finds tsconfig.json starting from the given directory.
378
+ */
379
+ function findTsConfig(startDir) {
380
+ let currentDir = startDir;
381
+ // Get the root directory in a cross-platform way (e.g., "/" on Unix, "C:\" on Windows)
382
+ const root = parsePath(resolve(startDir)).root;
383
+ while (currentDir !== root) {
384
+ const tsconfigPath = resolve(currentDir, "tsconfig.json");
385
+ if (existsSync(tsconfigPath)) {
386
+ return tsconfigPath;
387
+ }
388
+ const parentDir = resolve(currentDir, "..");
389
+ // Prevent infinite loop at root
390
+ if (parentDir === currentDir) {
391
+ break;
392
+ }
393
+ currentDir = parentDir;
394
+ }
395
+ // Check root directory as well
396
+ const rootTsconfig = resolve(root, "tsconfig.json");
397
+ if (existsSync(rootTsconfig)) {
398
+ return rootTsconfig;
399
+ }
400
+ return undefined;
401
+ }
402
+ /**
403
+ * Ensures a directory exists.
404
+ * @throws Error if the directory cannot be created
405
+ */
406
+ function ensureDir(dirPath) {
407
+ if (!existsSync(dirPath)) {
408
+ try {
409
+ mkdirSync(dirPath, { recursive: true });
410
+ }
411
+ catch (error) {
412
+ const err = error;
413
+ throw new Error(`Failed to create directory "${dirPath}": ${err.message}`);
414
+ }
415
+ }
416
+ }
417
+ /**
418
+ * Writes content to a file with proper error handling.
419
+ * @throws Error if the file cannot be written
420
+ */
421
+ function writeFile(filePath, content) {
422
+ try {
423
+ writeFileSync(filePath, content, "utf-8");
424
+ }
425
+ catch (error) {
426
+ const err = error;
427
+ throw new Error(`Failed to write file "${filePath}": ${err.message}`);
428
+ }
429
+ }
430
+ /**
431
+ * Creates test schema info from extraction results.
432
+ */
433
+ function createTestSchemas(results, nameMapper) {
434
+ return results
435
+ .filter((r) => r.isExported)
436
+ .map((result) => ({
437
+ schemaName: result.schemaName,
438
+ inputTypeName: nameMapper.map(result.schemaName).inputName,
439
+ outputTypeName: nameMapper.map(result.schemaName).outputName,
440
+ }));
441
+ }
442
+ /**
443
+ * Generates test file content for single output mode (--outFile).
444
+ */
445
+ function generateTestFileForSingleOutput(fileResultsMap, typesPath, testPath, nameMapper) {
446
+ const testFiles = [];
447
+ const testDir = dirname(testPath);
448
+ for (const [schemaFile, results] of fileResultsMap) {
449
+ const schemas = createTestSchemas(results, nameMapper);
450
+ if (schemas.length === 0)
451
+ continue;
452
+ testFiles.push({
453
+ schemaFilePath: getRelativePath(testDir, schemaFile),
454
+ typesFilePath: getRelativePath(testDir, typesPath),
455
+ importPrefix: generateImportPrefix(basename(schemaFile, ".ts")),
456
+ schemas,
457
+ });
458
+ }
459
+ return generateTypeTests(testFiles);
460
+ }
461
+ /**
462
+ * Generates test file content for per-file output mode (--outDir).
463
+ */
464
+ function generateTestFileForPerFile(schemaFile, typesPath, testPath, results, nameMapper) {
465
+ const schemas = createTestSchemas(results, nameMapper);
466
+ if (schemas.length === 0) {
467
+ return "";
468
+ }
469
+ const testDir = dirname(testPath);
470
+ return generateTypeTests([
471
+ {
472
+ schemaFilePath: getRelativePath(testDir, schemaFile),
473
+ typesFilePath: getRelativePath(testDir, typesPath),
474
+ importPrefix: generateImportPrefix(basename(schemaFile, ".ts")),
475
+ schemas,
476
+ },
477
+ ]);
478
+ }
479
+ /**
480
+ * Gets relative path from one file to another, ensuring it starts with ./
481
+ */
482
+ function getRelativePath(from, to) {
483
+ const rel = relative(from, to);
484
+ return rel.startsWith(".") ? rel : "./" + rel;
485
+ }
486
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { SourceFile } from "ts-morph";
2
+ import type { BrandInfo } from "./types.js";
3
+ /**
4
+ * Map of schema name to its brand information.
5
+ */
6
+ export type SchemaBrandMap = Map<string, BrandInfo[]>;
7
+ /**
8
+ * Detects .brand<...>() calls in Zod schemas.
9
+ */
10
+ export declare class BrandDetector {
11
+ /**
12
+ * Analyzes a source file to find all branded types in schemas.
13
+ *
14
+ * @param sourceFile - The source file to analyze
15
+ * @param schemaNames - Set of schema names to analyze
16
+ * @returns Map of schema name to brand information
17
+ */
18
+ detectBrands(sourceFile: SourceFile, schemaNames: Set<string>): SchemaBrandMap;
19
+ /**
20
+ * Recursively finds brand calls in a node.
21
+ */
22
+ private findBrandsInNode;
23
+ /**
24
+ * Extracts brand information from a .brand<...>() call.
25
+ */
26
+ private extractBrandFromCall;
27
+ /**
28
+ * Extracts the brand name from a type argument.
29
+ */
30
+ private extractBrandName;
31
+ }
32
+ //# sourceMappingURL=brand-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand-detector.d.ts","sourceRoot":"","sources":["../../src/core/brand-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAwB,MAAM,UAAU,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAEtD;;GAEG;AACH,qBAAa,aAAa;IACxB;;;;;;OAMG;IACH,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,cAAc;IAsB9E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA8CxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA6B5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAkBzB"}
@@ -0,0 +1,121 @@
1
+ import { Node } from "ts-morph";
2
+ /**
3
+ * Detects .brand<...>() calls in Zod schemas.
4
+ */
5
+ export class BrandDetector {
6
+ /**
7
+ * Analyzes a source file to find all branded types in schemas.
8
+ *
9
+ * @param sourceFile - The source file to analyze
10
+ * @param schemaNames - Set of schema names to analyze
11
+ * @returns Map of schema name to brand information
12
+ */
13
+ detectBrands(sourceFile, schemaNames) {
14
+ const result = new Map();
15
+ const statements = sourceFile.getVariableStatements();
16
+ for (const stmt of statements) {
17
+ for (const decl of stmt.getDeclarations()) {
18
+ const schemaName = decl.getName();
19
+ if (!schemaNames.has(schemaName))
20
+ continue;
21
+ const init = decl.getInitializer();
22
+ if (!init)
23
+ continue;
24
+ const brands = this.findBrandsInNode(init, "");
25
+ if (brands.length > 0) {
26
+ result.set(schemaName, brands);
27
+ }
28
+ }
29
+ }
30
+ return result;
31
+ }
32
+ /**
33
+ * Recursively finds brand calls in a node.
34
+ */
35
+ findBrandsInNode(node, currentPath) {
36
+ const brands = [];
37
+ // Check if this node is a .brand<...>() call
38
+ if (Node.isCallExpression(node)) {
39
+ const brandInfo = this.extractBrandFromCall(node, currentPath);
40
+ if (brandInfo) {
41
+ brands.push(brandInfo);
42
+ }
43
+ // Check the expression being called (for method chains)
44
+ const expr = node.getExpression();
45
+ if (Node.isPropertyAccessExpression(expr)) {
46
+ const base = expr.getExpression();
47
+ brands.push(...this.findBrandsInNode(base, currentPath));
48
+ }
49
+ // Check arguments (for z.object({ field: schema }))
50
+ for (const arg of node.getArguments()) {
51
+ brands.push(...this.findBrandsInNode(arg, currentPath));
52
+ }
53
+ }
54
+ // Check object literals for field definitions
55
+ if (Node.isObjectLiteralExpression(node)) {
56
+ for (const prop of node.getProperties()) {
57
+ if (Node.isPropertyAssignment(prop)) {
58
+ const fieldName = prop.getName();
59
+ const fieldPath = currentPath ? `${currentPath}.${fieldName}` : fieldName;
60
+ const initializer = prop.getInitializer();
61
+ if (initializer) {
62
+ brands.push(...this.findBrandsInNode(initializer, fieldPath));
63
+ }
64
+ }
65
+ }
66
+ }
67
+ // Check property access expressions (method chains)
68
+ if (Node.isPropertyAccessExpression(node)) {
69
+ const base = node.getExpression();
70
+ brands.push(...this.findBrandsInNode(base, currentPath));
71
+ }
72
+ return brands;
73
+ }
74
+ /**
75
+ * Extracts brand information from a .brand<...>() call.
76
+ */
77
+ extractBrandFromCall(node, fieldPath) {
78
+ const expr = node.getExpression();
79
+ if (!Node.isPropertyAccessExpression(expr)) {
80
+ return null;
81
+ }
82
+ const methodName = expr.getName();
83
+ if (methodName !== "brand") {
84
+ return null;
85
+ }
86
+ // Get the type argument: .brand<"UserId">()
87
+ const typeArgs = node.getTypeArguments();
88
+ if (typeArgs.length === 0) {
89
+ return null;
90
+ }
91
+ const typeArg = typeArgs[0];
92
+ const brandName = this.extractBrandName(typeArg);
93
+ if (!brandName) {
94
+ return null;
95
+ }
96
+ return {
97
+ brandName,
98
+ fieldPath,
99
+ };
100
+ }
101
+ /**
102
+ * Extracts the brand name from a type argument.
103
+ */
104
+ extractBrandName(node) {
105
+ // Handle string literal type: "UserId"
106
+ if (Node.isLiteralTypeNode(node)) {
107
+ const literal = node.getLiteral();
108
+ if (Node.isStringLiteral(literal)) {
109
+ return literal.getLiteralText();
110
+ }
111
+ }
112
+ // Handle direct string literal (some TS versions)
113
+ const text = node.getText();
114
+ const match = text.match(/^["'](.+)["']$/);
115
+ if (match) {
116
+ return match[1];
117
+ }
118
+ return null;
119
+ }
120
+ }
121
+ //# sourceMappingURL=brand-detector.js.map