UNPKG

typescript-scaffolder

Version:

![npm version](https://img.shields.io/npm/v/typescript-scaffolder) ### Unit Test Coverage: 97.12%

142 lines (141 loc) 6.7 kB
"use strict"; 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"); async function generateIncomingWebhook(webhook, interfaceInputDir, outputDir) { const funcName = 'generateIncomingWebhook'; const { name, requestSchema, handlerName, testHeaders } = 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_1.addClientRequiredImports)(sourceFile, outputFilePath, interfaceInputDir, requestSchema, '', true, false); const parameters = [ { name: 'payload', type: requestSchema, } ]; if (testHeaders && Object.keys(testHeaders).length > 0) { parameters.push({ name: 'headers', type: 'Record<string, string>', hasQuestionToken: true, }); } sourceFile.addFunction({ name: `handle${(0, object_helpers_1.toPascalCase)(handlerName)}Webhook`, isExported: true, isAsync: true, parameters, 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_1.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.assertDirectoryContainingAllSchemas)(requiredSchemas, interfaceNameToDirs, configPath); 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.'); }