mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
* Add type checking for protobus RPC handlers.
Add type parameters to the wrapper function when generating the server-setup file.
So that the parameters of the RPC handler will be type checked against types defined in the service.
The generated code looks like this:
```
server.addService(proto.cline.CheckpointsService.service, {
checkpointDiff: wrapper<cline.Int64Request,cline.Empty>(checkpointDiff, controller),
checkpointRestore: wrapper<cline.CheckpointRestoreRequest,cline.Empty>(checkpointRestore, controller),
});
```
Add an index.ts file to the proto directory so all the proto types can be imported without having to know which proto message is defined in which file (the proto descriptor set doesn't have this information).
* Generate index.ts with protoc instead of doing it ourselves.
Turn on the option 'dontExportCommonSymbols' in protoc, so that each generated proto file is not trying to export the same utility functions.
Generate all the protos with the same protoc command.
* cleanup
82 lines
2.8 KiB
JavaScript
82 lines
2.8 KiB
JavaScript
import * as fs from "fs"
|
|
import * as grpc from "@grpc/grpc-js"
|
|
import * as protoLoader from "@grpc/proto-loader"
|
|
import * as health from "grpc-health-check"
|
|
import { fileURLToPath } from "url"
|
|
import path from "path"
|
|
|
|
const OUT_FILE = path.resolve("src/standalone/server-setup.ts")
|
|
const DESCRIPTOR_SET = path.resolve("dist-standalone/proto/descriptor_set.pb")
|
|
|
|
// Load service definitions.
|
|
const clineDef = protoLoader.loadFileDescriptorSetFromBuffer(fs.readFileSync(DESCRIPTOR_SET))
|
|
const healthDef = protoLoader.loadSync(health.protoPath)
|
|
const packageDefinition = { ...clineDef, ...healthDef }
|
|
const proto = grpc.loadPackageDefinition(packageDefinition)
|
|
|
|
/**
|
|
* Generate imports and function to add all the handlers to the server for all services defined in the proto files.
|
|
*/
|
|
function generateHandlersAndExports() {
|
|
let imports = []
|
|
let handlerSetup = []
|
|
|
|
for (const [name, def] of Object.entries(proto.cline)) {
|
|
if (!def || !("service" in def)) {
|
|
continue
|
|
}
|
|
const domain = name.replace(/Service$/, "")
|
|
const dir = domain.charAt(0).toLowerCase() + domain.slice(1)
|
|
imports.push(`// ${domain} Service`)
|
|
handlerSetup.push(` // ${domain} Service`)
|
|
handlerSetup.push(` server.addService(proto.cline.${name}.service, {`)
|
|
for (const [rpcName, rpc] of Object.entries(def.service)) {
|
|
imports.push(`import { ${rpcName} } from "../core/controller/${dir}/${rpcName}"`)
|
|
const requestType = "proto.cline." + rpc.requestType.type.name
|
|
if (rpc.requestStream) {
|
|
throw new Error("Request streaming is not supported")
|
|
}
|
|
if (rpc.responseStream) {
|
|
handlerSetup.push(` ${rpcName}: wrapStreamingResponse<${requestType},void>(${rpcName}, controller),`)
|
|
} else {
|
|
const responseType = "proto.cline." + rpc.responseType.type.name
|
|
handlerSetup.push(` ${rpcName}: wrapper<${requestType},${responseType}>(${rpcName}, controller),`)
|
|
}
|
|
}
|
|
handlerSetup.push(` });`)
|
|
imports.push("")
|
|
handlerSetup.push("")
|
|
}
|
|
return {
|
|
imports: imports.join("\n"),
|
|
handlerSetup: handlerSetup.join("\n"),
|
|
}
|
|
}
|
|
|
|
const { imports, handlerSetup } = generateHandlersAndExports()
|
|
const scriptName = path.basename(fileURLToPath(import.meta.url))
|
|
|
|
// Create output file
|
|
let output = `// GENERATED CODE -- DO NOT EDIT!
|
|
// Generated by ${scriptName}
|
|
import * as grpc from "@grpc/grpc-js"
|
|
import * as proto from "@/shared/proto"
|
|
import { Controller } from "../core/controller"
|
|
import { GrpcHandlerWrapper, GrpcStreamingResponseHandlerWrapper } from "./grpc-types"
|
|
|
|
${imports}
|
|
export function addServices(
|
|
server: grpc.Server,
|
|
proto: any,
|
|
controller: Controller,
|
|
wrapper: GrpcHandlerWrapper,
|
|
wrapStreamingResponse: GrpcStreamingResponseHandlerWrapper,
|
|
): void {
|
|
${handlerSetup}
|
|
}
|
|
`
|
|
// Write output file
|
|
fs.writeFileSync(OUT_FILE, output)
|
|
|
|
console.log(`Generated service handlers in ${OUT_FILE}.`)
|