import { execFileSync } from "node:child_process"; import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { format } from "prettier"; const __dirname = dirname(fileURLToPath(import.meta.url)); const repoRoot = resolve(__dirname, "../.."); const defaultsPath = resolve(repoRoot, "config/tutti.defaults.json"); const goOutputPath = resolve( repoRoot, "services/tuttid/types/defaults_generated.go" ); const cliGoOutputPath = resolve( repoRoot, "apps/cli/internal/defaults/defaults_generated.go" ); const tsOutputPath = resolve( repoRoot, "apps/desktop/src/main/generated/defaults.ts" ); const prettierConfigPath = resolve( repoRoot, "packages/configs/prettier/base.mjs" ); const checkOnly = process.argv.includes("--check"); const { default: prettierConfig } = await import( pathToFileURL(prettierConfigPath).href ); if (isMainModule()) { const spec = JSON.parse(readFileSync(defaultsPath, "utf8")); writeGeneratedFile(goOutputPath, renderGoDefaults(spec)); writeGeneratedFile(cliGoOutputPath, renderCliGoDefaults(spec)); writeGeneratedFile(tsOutputPath, await renderTSDefaults(spec)); } function isMainModule() { return Boolean( process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url) ); } function writeGeneratedFile(targetPath, content) { mkdirSync(dirname(targetPath), { recursive: true }); if (checkOnly) { const existing = readFileSync(targetPath, "utf8"); if (existing !== content) { throw new Error(`Generated defaults are out of date: ${targetPath}`); } return; } writeFileSync(targetPath, content, "utf8"); } export function renderGoDefaults(specification) { return formatGo(`package types // Code generated by tools/scripts/generate-defaults.mjs. DO NOT EDIT. var generatedDefaults = generatedDefaultsSpec{ \tState: generatedStateDefaults{ \t\tProductionDirName: ${goString(specification.state.productionDirName)}, \t\tDevelopmentDirName: ${goString(specification.state.developmentDirName)}, \t\tRunDirName: ${goString(specification.state.runDirName)}, \t\tLogsDirName: ${goString(specification.state.logsDirName)}, \t\tDBFileName: ${goString(specification.state.dbFileName)}, \t\tDaemonLogFileName: ${goString(specification.state.daemonLogFileName)}, \t\tDesktopLogFileName: ${goString(specification.state.desktopLogFileName)}, \t\tListenerInfoFileName: ${goString(specification.state.listenerInfoFileName)}, \t\tPIDFileName: ${goString(specification.state.pidFileName)}, \t}, \tTransport: generatedTransportDefaults{ \t\tDefaultTCPAddr: ${goString(specification.transport.defaultTCPAddr)}, \t}, \tLogging: generatedLoggingDefaults{ \t\tDefaultLevel: ${goString(specification.logging.defaultLevel)}, \t\tDefaultOutput: ${goString(specification.logging.defaultOutput)}, \t\tMaxSizeMB: ${specification.logging.maxSizeMB}, \t\tMaxBackups: ${specification.logging.maxBackups}, \t\tMaxAgeDays: ${specification.logging.maxAgeDays}, \t\tMaxTotalMB: ${specification.logging.maxTotalMB}, \t}, \tAnalytics: generatedAnalyticsDefaults{ \t\tAppID: ${specification.analytics.appId}, \t\tAppKey: ${goString(specification.analytics.appKey)}, \t\tChannel: ${goString(specification.analytics.channel)}, \t\tChannelDomain: ${goString(specification.analytics.channelDomain)}, \t\tAppVersion: ${goString(specification.analytics.appVersion)}, \t}, \tAgentExtensions: generatedAgentExtensionDefaults{ \t\tSources: []generatedAgentExtensionSourceDefaults{ ${(specification.agentExtensions?.sources ?? []) .map( (source) => `\t\t\t{ \t\t\t\tKey: ${goString(source.key)}, \t\t\t\tPinnedVersion: ${goString(source.pinnedVersion)}, \t\t\t\tReleaseIndexURL: ${goString(source.releaseIndexUrl)}, \t\t\t\tFallbackReleaseIndexURLs: ${goStringSlice(source.fallbackReleaseIndexUrls)}, \t\t\t\tSigningKeyID: ${goString(source.signingKeyId)}, \t\t\t\tSigningPublicKey: ${goString(source.signingPublicKey)}, \t\t\t\tEnabled: ${source.enabled}, \t\t\t},` ) .join("\n")} \t\t}, \t}, \tAgentRuntimeTools: generatedAgentRuntimeToolDefaults{ \t\tUV: generatedUVToolDefaults{ \t\t\tVersion: ${goString(specification.agentRuntimeTools?.uv?.version ?? "")}, \t\t\tArtifacts: []generatedUVToolArtifactDefaults{ ${(specification.agentRuntimeTools?.uv?.artifacts ?? []) .map( (artifact) => `\t\t\t\t{ \t\t\t\t\tPlatform: ${goString(artifact.platform)}, \t\t\t\t\tURL: ${goString(artifact.url)}, \t\t\t\t\tSHA256: ${goString(artifact.sha256)}, \t\t\t\t\tSizeBytes: ${artifact.sizeBytes}, \t\t\t\t\tArchive: ${goString(artifact.archive)}, \t\t\t\t\tArchiveExecutable: ${goString(artifact.archiveExecutable)}, \t\t\t\t},` ) .join("\n")} \t\t\t}, \t\t}, \t}, } `); } export function renderCliGoDefaults(specification) { return formatGo(`package defaults // Code generated by tools/scripts/generate-defaults.mjs. DO NOT EDIT. var generatedDefaults = generatedDefaultsSpec{ \tState: generatedStateDefaults{ \t\tProductionDirName: ${goString(specification.state.productionDirName)}, \t\tDevelopmentDirName: ${goString(specification.state.developmentDirName)}, \t\tRunDirName: ${goString(specification.state.runDirName)}, \t\tListenerInfoFileName: ${goString(specification.state.listenerInfoFileName)}, \t}, } `); } export async function renderTSDefaults(specification) { return await format( `export const generatedDefaults = ${JSON.stringify(specification, null, 2)} as const;\n`, { ...prettierConfig, parser: "typescript" } ); } function goString(value) { return JSON.stringify(value); } function goStringSlice(values = []) { return `[]string{${values.map(goString).join(", ")}}`; } function formatGo(content) { return execFileSync("gofmt", { input: content, encoding: "utf8" }); }