@apistudio/apim-cli
Version:
CLI for API Management Products
185 lines (155 loc) • 5.81 kB
text/typescript
import * as path from 'path';
import * as fs from 'fs/promises';
import { AbstractInventoryBuilder } from '../src/core/design/AbstractInventoryBuilder.js';
import * as yaml from 'js-yaml';
// Define the categories for organizing schemas
const COMMON_SCHEMAS = ['api', 'urischemes', 'cors', 'properties', 'scope', 'product', 'plan', 'quota'];
interface SchemaInfo {
name: string;
version: string;
content: string;
category: 'common' | 'policies';
fileType: 'ts' | 'yaml';
}
class InventoryGenerator extends AbstractInventoryBuilder {
async generateInventoryModule(outputPath: string): Promise<void> {
try {
// Ensure the output directory exists
await fs.mkdir(path.join(outputPath, 'generated/source/assets/common'), { recursive: true });
await fs.mkdir(path.join(outputPath, 'generated/source/assets/policies'), { recursive: true });
// Process each source path from the config
for (const sourcePath of this.config.source) {
if (sourcePath) {
await this.processSourcePath(sourcePath, outputPath);
}
}
console.log(`Inventory generation completed at ${outputPath}`);
} catch (error) {
console.error('Error generating inventory:', error);
throw error;
}
}
private async processSourcePath(sourcePath: string, outputBasePath: string): Promise<void> {
try {
// Resolve the full path
const fullPath = path.resolve(process.cwd(), sourcePath.startsWith('/') ? `.${sourcePath}` : sourcePath);
// const fullPath = '/Users/sowbarnigaa/Documents/pocs/Smith/smith/packages/schema-specification/V12_openAPI_specification.yaml';
console.log(`Processing source path: ${fullPath}`);
// Check if the file exists
try {
await fs.access(fullPath);
} catch (error) {
console.warn(`Source file not found: ${fullPath}`);
return;
}
// Read the file content
const content = await fs.readFile(fullPath, 'utf8');
// Determine file type and parse accordingly
const isYaml = fullPath.endsWith('.yaml') || fullPath.endsWith('.yml');
let schemas;
if (isYaml) {
const parsed = yaml.load(content) as any;
schemas = parsed.components?.schemas;
} else {
// Assume JSON
const parsed = JSON.parse(content);
schemas = parsed.components?.schemas || parsed.schemas;
}
if (!schemas) {
console.warn(`No schemas found in ${fullPath}`);
return;
}
// Process each schema
for (const [schemaName, schema] of Object.entries<any>(schemas)) {
await this.processSchema(schemaName, schema, outputBasePath, isYaml ? 'yaml' : 'ts');
}
} catch (error) {
console.error(`Error processing source path ${sourcePath}:`, error);
throw error;
}
}
private async processSchema(
schemaName: string,
schema: any,
outputBasePath: string,
fileType: 'ts' | 'yaml'
): Promise<void> {
try {
// Extract schema information
const schemaInfo = this.extractSchemaInfo(schemaName, schema, fileType);
if (!schemaInfo) {
console.warn(`Could not extract information for schema: ${schemaName}`);
return;
}
// Determine the output directory
const baseDir = path.join(
outputBasePath,
'generated/source/assets',
schemaInfo.category,
schemaInfo.name.toLowerCase()
);
// Create the directory if it doesn't exist
await fs.mkdir(baseDir, { recursive: true });
// Create the output file
const fileName = `${schemaInfo.version.replace('\\', '-').replace('/', '-')}_${schemaInfo.name.toLowerCase()}.json`;
const filePath = path.join(baseDir, fileName);
await fs.writeFile(filePath, schemaInfo.content, 'utf8');
console.log(`Generated: ${filePath}`);
} catch (error) {
console.error(`Error processing schema ${schemaName}:`, error);
throw error;
}
}
private extractSchemaInfo(
schemaName: string,
schema: any,
fileType: 'ts' | 'yaml'
): SchemaInfo | null {
try {
// Determine the category (common or policies)
const category = this.getCategory(schemaName);
// Extract the version from the schema
const version = this.extractVersion(schema) || 'api.ibm.com-v1';
// Convert schema to string content
const content = typeof schema === 'string' ? schema : JSON.stringify(schema, null, 2);
return {
name: schemaName,
version,
content,
category,
fileType: fileType
};
} catch (error) {
console.error(`Error extracting schema info for ${schemaName}:`, error);
return null;
}
}
private getCategory(schemaName: string): 'common' | 'policies' {
const lowerName = schemaName.toLowerCase();
return COMMON_SCHEMAS.some(common => lowerName === common.toLowerCase()) ? 'common' : 'policies';
}
private extractVersion(schema: any): string | null {
// Try to extract version from different possible locations
if (schema.apiVersion?.default) {
return schema.apiVersion.default;
}
if (schema.properties?.apiVersion?.default) {
return schema.properties.apiVersion.default;
}
// If no version found, return null
return null;
}
}
async function run() {
const configPath = path.join(process.cwd(), 'generator/inventory_config.json');
const outputPath = process.cwd();
const generator = new InventoryGenerator();
await generator.runGeneration(configPath, outputPath);
console.log(`Inventory generation completed at ${outputPath}`);
}
// Run the generator
run().catch(err => {
console.error('Inventory generation failed:', err);
process.exit(1);
});
// Made with Bob