Created
May 25, 2025 17:56
-
-
Save Dasc3er/feb81a7049f083bbe92742dc4769cff8 to your computer and use it in GitHub Desktop.
Simple TS script to generate enums of available AWS Lambda entrypoints for CDK from Java code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as fs from 'fs'; | |
import * as path from 'path'; | |
// Ensure the generated folder exists | |
const GENERATED_FOLDER = path.resolve('./generated'); | |
if (!fs.existsSync(GENERATED_FOLDER)) { | |
fs.mkdirSync(GENERATED_FOLDER); | |
} | |
// Function to recursively find Java files in a directory | |
function findJavaFiles(dir: string): string[] { | |
let results: string[] = []; | |
const list = fs.readdirSync(dir); | |
list.forEach(file => { | |
const filePath = path.join(dir, file); | |
const stat = fs.statSync(filePath); | |
if (stat && stat.isDirectory()) { | |
results = results.concat(findJavaFiles(filePath)); | |
} else if (file.endsWith('.java')) { | |
results.push(filePath); | |
} | |
}); | |
return results; | |
} | |
// Function to extract package name and Lambda class implementations from Java files | |
function extractLambdaFunctions(filePath: string): { packageName: string, functions: {[key:string]: string} } { | |
const content = fs.readFileSync(filePath, 'utf-8'); | |
const lambdaFunctions: {[key:string]: string}= {}; | |
// Extract package name | |
const packageMatch = content.match(/package\s+([\w.]+);/); | |
const packageName = packageMatch ? packageMatch[1] : 'default'; | |
// Identify classes implementing Lambda interfaces | |
const classRegex = /class\s+(\w+)\s+.*implements\s+([\w.,\s]+)/g; | |
let match; | |
while ((match = classRegex.exec(content)) !== null) { | |
const className = match[1]; | |
const implementedInterfaces = match[2]; | |
if (implementedInterfaces.includes('RequestHandler') || implementedInterfaces.includes('RequestStreamHandler')) { | |
lambdaFunctions[className] = `${packageName}.${className}::handleRequest`; | |
} | |
} | |
return { packageName, functions: lambdaFunctions }; | |
} | |
// Function to determine Java version from multiple sources | |
function getJavaVersion(javaPath: string): string | null { | |
// 1. Check the standard Java 'release' file | |
const releaseFile = path.join(javaPath, 'release'); | |
if (fs.existsSync(releaseFile)) { | |
const content = fs.readFileSync(releaseFile, 'utf-8'); | |
const match = content.match(/JAVA_VERSION="([\d.]+)"/); | |
if (match) return match[1]; | |
} | |
// 2. Check Maven `pom.xml` | |
const pomFile = path.join(javaPath, 'pom.xml'); | |
if (fs.existsSync(pomFile)) { | |
const content = fs.readFileSync(pomFile, 'utf-8'); | |
const match = content.match(/<java.version>([\d.]+)<\/java.version>/) || | |
content.match(/<maven.compiler.source>([\d.]+)<\/maven.compiler.source>/); | |
if (match) return match[1]; | |
} | |
// 3. Check Ant `build.xml` | |
const buildFile = path.join(javaPath, 'build.xml'); | |
if (fs.existsSync(buildFile)) { | |
const content = fs.readFileSync(buildFile, 'utf-8'); | |
const match = content.match(/<javac[^>]+target="([\d.]+)"/); | |
if (match) return match[1]; | |
} | |
// 4. Check Java environment variable `JAVA_HOME` | |
const javaHome = process.env.JAVA_HOME; | |
if (javaHome) { | |
const javaVersionMatch = javaHome.match(/\d+/); | |
if (javaVersionMatch) return javaVersionMatch[0]; | |
} | |
return null; | |
} | |
// Generate TypeScript interface for each package | |
function generateCdkInterfaces(javaPaths: string[]) { | |
const packageMap: Record<string, {[key:string]: string}> = {}; | |
let javaVersion: string | null = null; | |
javaPaths.forEach(javaPath => { | |
console.log(`Processing Java path: ${javaPath}`); | |
const packageName = path.resolve(javaPath).split(path.sep).pop() || 'default'; | |
const version = getJavaVersion(javaPath); | |
if (!javaVersion && version) { | |
javaVersion = version; | |
} | |
console.log(`${javaPath}/src`) | |
const javaFiles = findJavaFiles(`${javaPath}/src`); | |
javaFiles.forEach(file => { | |
const { functions } = extractLambdaFunctions(file); | |
// Generate TypeScript interfaces for each package | |
if (Object.keys(functions).length > 0) { | |
let output = `// Auto-generated Lambda function interface\n`; | |
output += `// Java Version: ${javaVersion || 'Unknown'}\n\n`; | |
output += `export enum ${packageName.replace(/\./g, '_')} {\n`; | |
Object.entries(functions).forEach(([name, func]) => { | |
output += ` ${name} = '${func}',\n`; | |
}); | |
output += `}\n`; | |
fs.writeFileSync(`${GENERATED_FOLDER}/${packageName.replace(/\./g, '_')}.ts`, output); | |
console.log(`Generated: ${GENERATED_FOLDER}/${packageName.replace(/\./g, '_')}.ts`); | |
} | |
}); | |
}); | |
const INDEX_FILE_PATH = path.join(GENERATED_FOLDER, 'index.ts'); | |
// Read all TypeScript files in the generated folder | |
const files = fs.readdirSync(GENERATED_FOLDER) | |
.filter(file => file.endsWith('.ts') && file !== 'index.ts'); | |
// Generate the index.ts content | |
let indexContent = `// Auto-generated index file for Lambda functions\n\n`; | |
files.forEach(file => { | |
const moduleName = file.replace('.ts', ''); | |
indexContent += `export * from './${moduleName}';\n`; | |
}); | |
// Write the index.ts file | |
fs.writeFileSync(INDEX_FILE_PATH, indexContent); | |
console.log(`Generated: ${INDEX_FILE_PATH}`); | |
} | |
// Example usage | |
generateCdkInterfaces(['./TestPackage']); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment