typescript-runtime-schemas
Version:
A TypeScript schema generation tool that extracts Zod schemas from TypeScript source files with runtime validation support. Generate validation schemas directly from your existing TypeScript types with support for computed types and constraint-based valid
174 lines ⢠8.81 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.statsCommand = void 0;
const commander_1 = require("commander");
const schema_extractor_1 = require("../../core/schema-extractor");
const config_1 = require("../config");
const utils_1 = require("../utils");
exports.statsCommand = new commander_1.Command('stats')
.description('Show processing statistics and type analysis')
.argument('<input>', 'Input file or directory')
.option('--glob <pattern>', 'File pattern to match')
.option('--exclude <pattern>', 'File pattern to exclude')
.option('--config <file>', 'Configuration file path')
.option('--detailed', 'Show detailed per-file statistics')
.action(async (input, options) => {
const progress = new utils_1.ProgressIndicator();
try {
progress.start('Loading configuration...');
// Load configuration
const config = options.config
? await Promise.resolve().then(() => __importStar(require('../config'))).then((m) => m.loadConfig(options.config))
: await (0, config_1.findAndLoadConfig)();
const mergedOptions = (0, config_1.mergeConfig)(config, {
...options,
input,
});
progress.stop('Configuration loaded');
progress.start('Analyzing project...');
// Get extraction results with metadata
const result = await schema_extractor_1.SchemaExtractor.extract(input, {
includeSourceInfo: true,
glob: mergedOptions.glob,
exclude: mergedOptions.exclude,
});
progress.stop('Analysis completed');
// Display overall statistics
(0, utils_1.logInfo)(`\nš Schema Generation Statistics`);
(0, utils_1.logInfo)(`${'='.repeat(50)}`);
(0, utils_1.logInfo)(`š Input: ${input}`);
(0, utils_1.logInfo)(`ā” Processing time: ${result.processingTime}ms`);
(0, utils_1.logInfo)(`š Total types found: ${result.totalTypesFound}`);
(0, utils_1.logInfo)(`šÆ Types with validation: ${result.typesWithSupportsRuntimeValidation}`);
(0, utils_1.logInfo)(`š¦ Schemas extracted: ${result.schemas.length}`);
if (result.totalTypesFound > 0) {
const coverage = ((result.typesWithSupportsRuntimeValidation / result.totalTypesFound) *
100).toFixed(1);
(0, utils_1.logInfo)(`š Validation coverage: ${coverage}%`);
}
// Show efficiency metrics
const skippedTypes = result.totalTypesFound - result.typesWithSupportsRuntimeValidation;
if (skippedTypes > 0) {
const efficiency = ((skippedTypes / result.totalTypesFound) *
100).toFixed(1);
(0, utils_1.logInfo)(`ā” Processing efficiency: ${efficiency}% of types skipped (no validation needed)`);
}
// Show schema breakdown
if (result.schemas.length > 0) {
(0, utils_1.logInfo)(`\nš Schema Breakdown:`);
// Group by source file
const schemasByFile = {};
result.schemas.forEach((schema) => {
if (schema.sourceInfo?.filePath) {
const file = schema.sourceInfo.filePath;
schemasByFile[file] = (schemasByFile[file] || 0) + 1;
}
});
Object.entries(schemasByFile).forEach(([file, count]) => {
(0, utils_1.logInfo)(` š ${file}: ${count} schemas`);
});
// Show individual schemas if not too many
if (result.schemas.length <= 20) {
(0, utils_1.logInfo)(`\nš Generated Schemas:`);
result.schemas.forEach((schema, index) => {
const sourceInfo = schema.sourceInfo
? ` (${schema.sourceInfo.filePath}:${schema.sourceInfo.line})`
: '';
const propCount = Object.keys(schema.schema).length;
(0, utils_1.logInfo)(` ${(index + 1).toString().padStart(2)}. ${schema.typeName} (${propCount} properties)${sourceInfo}`);
});
}
else {
(0, utils_1.logInfo)(`\nš Schema Types (showing first 20 of ${result.schemas.length}):`);
result.schemas.slice(0, 20).forEach((schema, index) => {
const propCount = Object.keys(schema.schema).length;
(0, utils_1.logInfo)(` ${(index + 1).toString().padStart(2)}. ${schema.typeName} (${propCount} properties)`);
});
(0, utils_1.logInfo)(` ... and ${result.schemas.length - 20} more`);
}
}
// Show detailed statistics if requested
if (options.detailed) {
progress.start('Gathering detailed statistics...');
try {
// Create a temporary extractor to get detailed statistics
const { project, sourceFiles } = await Promise.resolve().then(() => __importStar(require('../../core/utils/source-loader'))).then((m) => m.SourceLoader.createProject(input, {
glob: mergedOptions.glob,
exclude: mergedOptions.exclude,
}));
const extractor = new schema_extractor_1.SchemaExtractor(project, sourceFiles);
const detailedStats = await extractor.getTypeStatistics();
progress.stop('Detailed statistics gathered');
(0, utils_1.logInfo)(`\nš Detailed File Statistics:`);
(0, utils_1.logInfo)(`${'='.repeat(50)}`);
Object.entries(detailedStats.typesByFile).forEach(([file, totalCount]) => {
const totalCountNum = totalCount;
const validationCount = detailedStats.validationTypesByFile[file] || 0;
const coverage = totalCountNum > 0
? ((validationCount / totalCountNum) * 100).toFixed(1)
: '0.0';
(0, utils_1.logInfo)(`\nš ${file}:`);
(0, utils_1.logInfo)(` Total types: ${totalCountNum}`);
(0, utils_1.logInfo)(` With validation: ${validationCount}`);
(0, utils_1.logInfo)(` Coverage: ${coverage}%`);
});
}
catch (statsError) {
progress.stop();
console.warn('Warning: Could not gather detailed statistics:', statsError);
}
}
// Performance insights
(0, utils_1.logInfo)(`\nš” Performance Insights:`);
if (result.processingTime < 1000) {
(0, utils_1.logInfo)(` ā” Fast processing (${result.processingTime}ms)`);
}
else if (result.processingTime < 5000) {
(0, utils_1.logInfo)(` ā±ļø Moderate processing time (${result.processingTime}ms)`);
}
else {
(0, utils_1.logInfo)(` š Slow processing (${result.processingTime}ms) - consider using glob patterns to filter files`);
}
if (result.totalTypesFound > 100) {
(0, utils_1.logInfo)(` š Large project detected (${result.totalTypesFound} types) - good validation coverage helps maintainability`);
}
}
catch (error) {
progress.stop();
(0, utils_1.handleError)(error, 'Failed to generate statistics');
}
});
//# sourceMappingURL=stats.js.map