typescript-scaffolder
Version:
 ### Unit Test Coverage: 97.53%
147 lines (146 loc) • 6.72 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.generateWebhookRoute = generateWebhookRoute;
exports.generateWebhookRoutesFromFile = generateWebhookRoutesFromFile;
exports.generateWebhookRoutesFromPath = generateWebhookRoutesFromPath;
const path = __importStar(require("path"));
const ts_morph_1 = require("ts-morph");
const file_system_1 = require("../utils/file-system");
const object_helpers_1 = require("../utils/object-helpers");
const client_constructors_1 = require("../utils/client-constructors");
const logger_1 = require("../utils/logger");
/**
* Generates an Express router file for a single incoming webhook.
*
* @param webhook - The webhook definition to generate a route for.
* @param interfaceInputDir - Root path for interface .ts files.
* @param outputDir - Base output directory (e.g., src/codegen/routes/webhooks).
*/
async function generateWebhookRoute(webhook, interfaceInputDir, outputDir) {
const { handlerName, path: webhookPath, requestSchema } = webhook;
const funcName = `generateWebhookRoute`;
logger_1.Logger.debug(funcName, 'Starting webhook route generation...');
const pascalHandlerName = (0, object_helpers_1.toPascalCase)(handlerName);
const routeFile = path.join(outputDir, 'router.ts');
(0, file_system_1.ensureDir)(outputDir);
const interfaceImportPath = path.relative(outputDir, path.join(interfaceInputDir, requestSchema)).replace(/\\/g, '/');
// Handler files are now generated in the same routes/ directory, so use a relative local import.
const handlerImportPath = `./handle_${handlerName}`;
const project = new ts_morph_1.Project();
const sourceFile = project.createSourceFile(routeFile, '', { overwrite: true });
sourceFile.addImportDeclaration({
defaultImport: 'express',
moduleSpecifier: 'express',
});
sourceFile.addImportDeclaration({
isTypeOnly: true,
namedImports: [requestSchema],
moduleSpecifier: interfaceImportPath.startsWith('.') ? interfaceImportPath : `./${interfaceImportPath}`,
});
sourceFile.addImportDeclaration({
namedImports: [`handle${pascalHandlerName}Webhook`],
moduleSpecifier: handlerImportPath.startsWith('.') ? handlerImportPath : `./${handlerImportPath}`,
});
sourceFile.addStatements([
'const router = express.Router();',
'router.use(express.json());'
]);
sourceFile.addStatements([
`router.post('${webhookPath}', async (req, res) => {
try {
const payload = req.body as ${requestSchema};
await handle${pascalHandlerName}Webhook(payload);
res.status(200).json({ ok: true });
} catch (error) {
console.error('Webhook error:', error);
res.status(500).json({ ok: false });
}
});`
]);
sourceFile.addStatements(['export default router;']);
logger_1.Logger.debug(funcName, 'Webhook route generation complete');
await sourceFile.save();
}
/**
* Reads a WebhookConfigFile and generates Express routes for each incoming webhook.
*
* @param configPath - Path to the webhook config file.
* @param interfaceInputDir - Directory containing interface .ts files.
* @param outputDir - Output directory for generated routes.
*/
async function generateWebhookRoutesFromFile(configPath, interfaceInputDir, outputDir) {
const config = (0, file_system_1.readWebhookConfigFile)(configPath);
if (!config)
return;
for (const webhook of config.webhooks) {
if (webhook.direction !== 'incoming')
continue;
await generateWebhookRoute(webhook, interfaceInputDir, outputDir);
}
}
/**
* Generate Express webhook route files from all config files in a directory.
* @param configDir - Path to the webhook config file.
* @param interfacesRootDir - Directory containing interface .ts files.
* @param outputRootDir - Output directory for generated routes.
*/
async function generateWebhookRoutesFromPath(configDir, interfacesRootDir, outputRootDir) {
const funcName = 'generateWebhookRoutesFromPath';
logger_1.Logger.debug(funcName, 'Starting webhook route generation from config and interface directories...');
const { configFiles, interfaceNameToDirs } = (0, file_system_1.extractInterfaces)(configDir, interfacesRootDir);
for (const configPath of configFiles) {
const config = (0, file_system_1.readWebhookConfigFile)(configPath);
if (!config) {
continue;
}
const requiredSchemas = new Set();
for (const webhook of config.webhooks) {
if (webhook.direction === 'incoming') {
requiredSchemas.add(webhook.requestSchema);
}
}
const foundDir = (0, client_constructors_1.findDirectoryContainingAllSchemas)(requiredSchemas, interfaceNameToDirs, configPath, funcName);
if (!foundDir) {
logger_1.Logger.warn(funcName, `Could not find a directory containing all schemas for config: ${configPath}`);
continue;
}
const relativeInterfaceDir = path.relative(interfacesRootDir, foundDir);
const outputDir = path.join(outputRootDir, relativeInterfaceDir);
(0, file_system_1.ensureDir)(outputDir);
await generateWebhookRoutesFromFile(configPath, foundDir, outputDir);
}
logger_1.Logger.info(funcName, 'Webhook route generation completed.');
}