import { execFileSync } from 'node:child_process' import { existsSync, mkdirSync, readdirSync, rmSync, statSync, } from 'node:fs' import { delimiter, join, relative } from 'node:path' const rootDir = process.cwd() const protoRoot = 'proto' const genRoot = 'gen' const isWindows = process.platform === 'win32' const tsProtoBinDir = join(rootDir, 'node_modules', '.bin') const tsProtoPlugin = isWindows ? join(tsProtoBinDir, 'protoc-gen-ts_proto.cmd') : join(tsProtoBinDir, 'protoc-gen-ts_proto') function toUnixPath(path) { return path.replaceAll('\\', '/') } function collectProtoFiles(dir) { const files = [] for (const entry of readdirSync(dir)) { const fullPath = join(dir, entry) const stat = statSync(fullPath) if (stat.isDirectory()) { files.push(...collectProtoFiles(fullPath)) continue } if (entry.endsWith('.proto')) { files.push(toUnixPath(relative(rootDir, fullPath))) } } return files } if (!existsSync(protoRoot)) { console.error(`Proto directory not found: ${protoRoot}`) process.exit(1) } if (!existsSync(tsProtoPlugin)) { console.error(`ts-proto plugin not found: ${tsProtoPlugin}`) console.error('Run: yarn add -D ts-proto') process.exit(1) } const protoFiles = collectProtoFiles(protoRoot) if (protoFiles.length === 0) { console.error('No .proto files found.') process.exit(1) } rmSync(genRoot, { recursive: true, force: true, }) mkdirSync(genRoot, { recursive: true, }) const env = { ...process.env, PATH: `${tsProtoBinDir}${delimiter}${process.env.PATH ?? ''}`, Path: `${tsProtoBinDir}${delimiter}${process.env.Path ?? ''}`, } execFileSync( 'protoc', [ '-I', protoRoot, '--ts_proto_out', genRoot, '--ts_proto_opt', 'nestJs=true,package=omit', ...protoFiles, ], { cwd: rootDir, stdio: 'inherit', env, }, )