(lines: string[], node: Record<string, unknown>, isSession: boolean, resolveType: (name: string) => string, fields: Map<string, Map<string, GoExtractedField>>, unionInfos: Map<string, GoDiscriminatedUnionInfo>, classPrefix: string = "")
| 4049 | } |
| 4050 | |
| 4051 | function emitRpcWrapper(lines: string[], node: Record<string, unknown>, isSession: boolean, resolveType: (name: string) => string, fields: Map<string, Map<string, GoExtractedField>>, unionInfos: Map<string, GoDiscriminatedUnionInfo>, classPrefix: string = ""): void { |
| 4052 | const groups = sortByPascalName(Object.entries(node).filter(([, v]) => typeof v === "object" && v !== null && !isRpcMethod(v))); |
| 4053 | const topLevelMethods = sortByPascalName(Object.entries(node).filter(([, v]) => isRpcMethod(v))); |
| 4054 | |
| 4055 | const wrapperName = classPrefix + (isSession ? "SessionRPC" : "ServerRPC"); |
| 4056 | const apiSuffix = "API"; |
| 4057 | // Lowercase the prefix so the unexported service struct stays unexported in Go. |
| 4058 | const prefixLower = classPrefix ? classPrefix.charAt(0).toLowerCase() + classPrefix.slice(1) : ""; |
| 4059 | const serviceName = prefixLower |
| 4060 | ? prefixLower + (isSession ? "SessionAPI" : "ServerAPI") |
| 4061 | : (isSession ? "sessionAPI" : "serverAPI"); |
| 4062 | |
| 4063 | // Emit the common service struct (unexported, shared by all API groups via type cast) |
| 4064 | lines.push(`type ${serviceName} struct {`); |
| 4065 | lines.push(`\tclient *jsonrpc2.Client`); |
| 4066 | if (isSession) lines.push(`\tsessionID string`); |
| 4067 | lines.push(`}`); |
| 4068 | lines.push(``); |
| 4069 | |
| 4070 | // Emit API types for groups |
| 4071 | for (const [groupName, groupNode] of groups) { |
| 4072 | const prefix = classPrefix + (isSession ? "" : "Server"); |
| 4073 | const apiName = prefix + toGoFieldName(groupName) + apiSuffix; |
| 4074 | const groupExperimental = isNodeFullyExperimental(groupNode as Record<string, unknown>); |
| 4075 | const groupDeprecated = isNodeFullyDeprecated(groupNode as Record<string, unknown>); |
| 4076 | emitApiGroup(lines, apiName, groupNode as Record<string, unknown>, isSession, serviceName, resolveType, fields, unionInfos, groupExperimental, groupDeprecated); |
| 4077 | } |
| 4078 | |
| 4079 | // Compute field name lengths for gofmt-compatible column alignment |
| 4080 | const groupPascalNames = groups.map(([g]) => toGoFieldName(g)); |
| 4081 | const allFieldNames = ["common", ...groupPascalNames]; |
| 4082 | const maxFieldLen = Math.max(...allFieldNames.map((n) => n.length)); |
| 4083 | const pad = (name: string) => name.padEnd(maxFieldLen); |
| 4084 | |
| 4085 | // Emit wrapper struct |
| 4086 | pushGoComment( |
| 4087 | lines, |
| 4088 | classPrefix === "Internal" |
| 4089 | ? `${wrapperName} provides internal SDK ${isSession ? "session" : "server"}-scoped RPC methods (handshake helpers etc.). Not part of the public API.` |
| 4090 | : `${wrapperName} provides typed ${isSession ? "session" : "server"}-scoped RPC methods.` |
| 4091 | ); |
| 4092 | lines.push(`type ${wrapperName} struct {`); |
| 4093 | pushGoComment(lines, `Reuse a single struct instead of allocating one for each service on the heap.`, "\t"); |
| 4094 | lines.push(`\t${pad("common")} ${serviceName}`); |
| 4095 | lines.push(``); |
| 4096 | for (const [groupName] of groups) { |
| 4097 | const prefix = classPrefix + (isSession ? "" : "Server"); |
| 4098 | lines.push(`\t${pad(toGoFieldName(groupName))} *${prefix}${toGoFieldName(groupName)}${apiSuffix}`); |
| 4099 | } |
| 4100 | lines.push(`}`); |
| 4101 | lines.push(``); |
| 4102 | |
| 4103 | // Top-level methods on the wrapper use the common service fields |
| 4104 | for (const [key, value] of topLevelMethods) { |
| 4105 | if (!isRpcMethod(value)) continue; |
| 4106 | emitMethod(lines, wrapperName, key, value, isSession, resolveType, fields, unionInfos, false, true); |
| 4107 | } |
| 4108 |
no test coverage detected
searching dependent graphs…