import { type CollectedApisMap, type CollectedEventsMap, type Entry, } from './types'; export const determineEntry = (path: string): Entry => { if (path.includes('src/entries/helper')) return 'helper'; return 'main'; }; /** * Generates the API type definitions file content */ export function generateApiTypesFile(collectedApis: CollectedApisMap): string { let content = `// AUTO-GENERATED FILE. DO NOT EDIT MANUALLY.\n// Generated by: packages/frontend/apps/electron/scripts/generate-types.ts\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n`; content += `// Utility type: remove trailing IpcMainInvokeEvent param and ensure Promise return\n`; content += `type EnsurePromise = T extends Promise ? T : Promise;\n`; content += `export type ApiMethod = T extends (...args: infer P) => infer R ? (...args: P) => EnsurePromise : never;\n\n`; content += `export interface ElectronApis {\n`; for (const [scope, methods] of collectedApis) { content += ` ${scope}: {\n`; for (const method of methods) { if (method.description && method.description.trim().length > 0) { const lines = method.description.split('\n').map(l => ` * ${l}`); content += ' /**\n'; content += lines.join('\n') + '\n'; content += ' */\n'; } content += ` ${method.apiMethodName}: ApiMethod;\n`; } content += ` };\n`; } content += `}\n`; return content; } /** * Generates the event type definitions file content */ export function generateEventTypesFile( collectedEvents: CollectedEventsMap ): string { let out = `// AUTO-GENERATED FILE. DO NOT EDIT MANUALLY.\n// Generated by: packages/frontend/apps/electron/scripts/generate-types.ts\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Observable } from 'rxjs';\n\n`; out += `type ToSubscribe> = T extends Observable ? (callback: (payload: P) => void) => () => void : never;\n\n`; out += `export interface ElectronEvents {\n`; for (const [scope, events] of collectedEvents) { out += ` ${scope}: {\n`; for (const evt of events) { const capName = evt.eventName.charAt(0).toUpperCase() + evt.eventName.slice(1); if (evt.description && evt.description.trim().length > 0) { const lines = evt.description.split('\n').map(l => ` * ${l}`); out += ' /**\n'; out += lines.join('\n') + '\n'; out += ' */\n'; } out += ` on${capName}: ToSubscribe;\n`; } out += ` };\n`; } out += `}\n`; return out; } /** * Generates a combined metadata file for both IPC handlers and events */ export function generateCombinedMetaFile( apiHandlers: CollectedApisMap, events: CollectedEventsMap ): string { let content = `// AUTO-GENERATED FILE. DO NOT EDIT MANUALLY.\n// Generated by: packages/frontend/apps/electron/scripts/generate-types.ts\n/* eslint-disable @typescript-eslint/no-explicit-any */\n`; // Build nested structure: entry -> scope -> names[] const handlersMeta: Record> = {}; apiHandlers.forEach((methods, scope) => { methods.forEach(m => { const ent = m.entry; if (!handlersMeta[ent]) handlersMeta[ent] = {}; if (!handlersMeta[ent][scope]) handlersMeta[ent][scope] = []; handlersMeta[ent][scope].push(m.apiMethodName); }); }); const eventsMeta: Record> = {}; events.forEach((evtList, scope) => { evtList.forEach(e => { const ent = e.entry; if (!eventsMeta[ent]) eventsMeta[ent] = {}; if (!eventsMeta[ent][scope]) eventsMeta[ent][scope] = []; eventsMeta[ent][scope].push(e.eventName); }); }); // Serialize handlersMeta & eventsMeta content += `export const handlersMeta = ${JSON.stringify( handlersMeta, null, 2 )} as const;\n\n`; content += `export const eventsMeta = ${JSON.stringify(eventsMeta, null, 2)} as const;\n`; return content; }