typescript-scaffolder
Version:
 ### Unit Test Coverage: 97.12%
135 lines (134 loc) • 6.53 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateIncomingWebhook = generateIncomingWebhook;
exports.generateOutgoingWebhook = generateOutgoingWebhook;
exports.generateWebhooksFromFile = generateWebhooksFromFile;
exports.generateWebhooksFromPath = generateWebhooksFromPath;
const client_constructors_1 = require("../utils/client-constructors");
const file_system_1 = require("../utils/file-system");
const logger_1 = require("../utils/logger");
const ts_morph_1 = require("ts-morph");
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const object_helpers_1 = require("../utils/object-helpers");
const client_constructors_2 = require("../utils/client-constructors");
async function generateIncomingWebhook(webhook, interfaceInputDir, outputDir) {
const funcName = 'generateIncomingWebhook';
const { name, requestSchema, handlerName } = webhook;
logger_1.Logger.debug(funcName, `Generating incoming webhook handler for "${name}"...`);
const fileName = `handle_${handlerName}.ts`;
const outputFilePath = path_1.default.join(outputDir, fileName);
fs_1.default.mkdirSync(path_1.default.dirname(outputFilePath), { recursive: true });
const project = new ts_morph_1.Project();
const sourceFile = project.createSourceFile(outputFilePath, '', { overwrite: true });
// Include axios, responseSchema to avoid manual editing later
(0, client_constructors_2.addClientRequiredImports)(sourceFile, outputFilePath, interfaceInputDir, requestSchema, '', true, false);
sourceFile.addFunction({
name: `handle${(0, object_helpers_1.toPascalCase)(handlerName)}Webhook`,
isExported: true,
isAsync: true,
parameters: [
{
name: 'payload',
type: requestSchema,
},
],
returnType: 'Promise<void>',
statements: [
'// TODO: Implement webhook handler logic here',
'console.log("Received webhook payload:", payload);',
],
});
await sourceFile.save();
}
async function generateOutgoingWebhook(webhook, interfaceInputDir, outputDir) {
const funcName = 'generateOutgoingWebhook';
const { name, requestSchema, responseSchema, targetUrl } = webhook;
logger_1.Logger.debug(funcName, `Generating outgoing webhook sender for "${name}"...`);
const fileName = `send_${name}_webhook.ts`;
const outputFilePath = path_1.default.join(outputDir, fileName);
fs_1.default.mkdirSync(path_1.default.dirname(outputFilePath), { recursive: true });
const project = new ts_morph_1.Project();
const sourceFile = project.createSourceFile(outputFilePath, '', { overwrite: true });
(0, client_constructors_2.addClientRequiredImports)(sourceFile, outputFilePath, interfaceInputDir, requestSchema, responseSchema || '', true);
sourceFile.addFunction({
name: `send${(0, object_helpers_1.toPascalCase)(name)}Webhook`,
isExported: true,
isAsync: true,
parameters: [
{
name: 'body',
type: requestSchema,
},
{
name: 'headers',
type: 'Record<string, string>',
hasQuestionToken: true,
}
],
returnType: `Promise<${responseSchema || 'any'}>`,
statements: [
`const response = await axios.post(\`${targetUrl}\`, body, { headers });`,
'return response.data;',
],
});
await sourceFile.save();
}
async function generateWebhooksFromFile(configPath, interfaceInputDir, outputDir) {
const funcName = 'generateWebhooksFromFile';
logger_1.Logger.debug(funcName, 'Starting webhook handler generation...');
const config = (0, file_system_1.readWebhookConfigFile)(configPath);
if (!config) {
logger_1.Logger.warn(funcName, `Skipping invalid config file at: ${configPath}`);
return;
}
for (const webhook of config.webhooks) {
if (webhook.direction === 'incoming') {
await generateIncomingWebhook(webhook, interfaceInputDir, outputDir);
}
else if (webhook.direction === 'outgoing') {
await generateOutgoingWebhook(webhook, interfaceInputDir, outputDir);
}
else {
logger_1.Logger.warn(funcName, `Skipping unknown webhook direction for: ${webhook.name}`);
}
}
logger_1.Logger.debug(funcName, 'Finished generating all webhook handlers.');
}
/**
* Generate webhook handlers/senders from all config files in a directory, mapping to interface directories.
* @param configDir - Path to the webhook config file.
* @param interfacesRootDir - Directory containing interface .ts files.
* @param outputRootDir - Output directory for generated routes.
*/
async function generateWebhooksFromPath(configDir, interfacesRootDir, outputRootDir) {
const funcName = 'generateWebhooksFromPath';
logger_1.Logger.debug(funcName, 'Starting webhook 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) {
requiredSchemas.add(webhook.requestSchema);
if (webhook.direction === 'outgoing' && webhook.responseSchema) {
requiredSchemas.add(webhook.responseSchema);
}
}
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_1.default.relative(interfacesRootDir, foundDir);
const outputDir = path_1.default.join(outputRootDir, relativeInterfaceDir);
(0, file_system_1.ensureDir)(outputDir);
await generateWebhooksFromFile(configPath, foundDir, outputDir);
}
logger_1.Logger.info(funcName, 'Webhook generation completed.');
}
;