Skip to content

Commit 22ac0f7

Browse files
stephentoubCopilot
andcommitted
Fix Go session event union decoding
Register shared API union decoders when generating Go session event payload unmarshalling so event data can decode attachments and approvals referenced from the API schema. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 756bf47 commit 22ac0f7

2 files changed

Lines changed: 165 additions & 4 deletions

File tree

go/rpc/zsession_encoding.go

Lines changed: 98 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/codegen/go.ts

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,57 @@ function pushGoEncodingBlock(blockLines: string[], ctx: GoCodegenCtx): void {
10341034
ctx.encoding.push(block);
10351035
}
10361036

1037+
function registerGoExternalUnionUnmarshalers(
1038+
schema: JSONSchema7,
1039+
ctx: GoCodegenCtx,
1040+
externalSchemas?: Record<string, JSONSchema7>
1041+
): void {
1042+
if (!externalSchemas) return;
1043+
1044+
const externalRefs = collectExternalSchemaRefNames(schema);
1045+
for (const [schemaFile, refNames] of externalRefs) {
1046+
const externalSchema = externalSchemas[schemaFile];
1047+
const externalImport = EXTERNAL_SCHEMA_GO_IMPORT[schemaFile];
1048+
if (!externalSchema || !externalImport || externalImport.packageName !== ctx.packageName) continue;
1049+
1050+
const externalDefinitions = collectDefinitionCollections(externalSchema as Record<string, unknown>);
1051+
const definitions: Record<string, JSONSchema7> = {
1052+
...Object.fromEntries(
1053+
Object.entries(externalDefinitions.$defs ?? {}).filter(([, value]) => typeof value === "object" && value !== null)
1054+
) as Record<string, JSONSchema7>,
1055+
...Object.fromEntries(
1056+
Object.entries(externalDefinitions.definitions ?? {}).filter(([, value]) => typeof value === "object" && value !== null)
1057+
) as Record<string, JSONSchema7>,
1058+
};
1059+
const planningCtx: GoCodegenCtx = {
1060+
structs: [],
1061+
encoding: [],
1062+
enums: [],
1063+
enumsByName: new Map(),
1064+
discriminatedUnions: new Map(),
1065+
generatedNames: new Set(),
1066+
definitions: externalDefinitions,
1067+
wrapComments: ctx.wrapComments,
1068+
discriminatedUnionRawVariantSuffix: ctx.discriminatedUnionRawVariantSuffix,
1069+
packageName: ctx.packageName,
1070+
};
1071+
1072+
for (const refName of refNames) {
1073+
const definition = definitions[refName];
1074+
if (!definition) continue;
1075+
1076+
const typeName = goDefinitionName(refName);
1077+
const plan = planGoUnion(typeName, definition, planningCtx, true);
1078+
if (!plan || plan.kind === "flattenedObject" || plan.kind === "wrapper") continue;
1079+
1080+
ctx.discriminatedUnions.set(typeName, {
1081+
typeName,
1082+
unmarshalFuncName: goUnexportedFunctionName("unmarshal", typeName),
1083+
});
1084+
}
1085+
}
1086+
}
1087+
10371088
function pushGoStructUnmarshalJSON(lines: string[], typeName: string, fields: GoStructField[], ctx: GoCodegenCtx): void {
10381089
const unionFields = fields
10391090
.map((field) => ({ field, unionField: goDiscriminatedUnionField(field.goType, ctx) }))
@@ -2992,7 +3043,11 @@ function goDeclaredTypeName(code: string): string {
29923043
/**
29933044
* Generate the complete Go session-events file content.
29943045
*/
2995-
export function generateGoSessionEventsCode(schema: JSONSchema7, packageName: string): GoGeneratedTypeCode {
3046+
export function generateGoSessionEventsCode(
3047+
schema: JSONSchema7,
3048+
packageName: string,
3049+
externalSchemas?: Record<string, JSONSchema7>
3050+
): GoGeneratedTypeCode {
29963051
const variants = extractGoEventVariants(schema);
29973052
const ctx: GoCodegenCtx = {
29983053
structs: [],
@@ -3006,6 +3061,7 @@ export function generateGoSessionEventsCode(schema: JSONSchema7, packageName: st
30063061
discriminatedUnionRawVariantSuffix: "",
30073062
packageName,
30083063
};
3064+
registerGoExternalUnionUnmarshalers(schema, ctx, externalSchemas);
30093065
const envelopeProperties = getGoSharedEventEnvelopeProperties(schema, ctx);
30103066
const sessionEventStructFields = [
30113067
...envelopeProperties.map((property) => ({
@@ -3574,17 +3630,24 @@ async function generateSessionEvents(schemaPath?: string, apiSchema?: ApiSchema)
35743630
const resolvedPath = schemaPath ?? (await getSessionEventsSchemaPath());
35753631
const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7);
35763632
const processed = propagateInternalVisibility(postProcessSchema(schema));
3577-
const sharedDefinitions = apiSchema
3633+
const processedApiSchema = apiSchema
3634+
? propagateInternalVisibility(postProcessSchema(cloneSchemaForCodegen(apiSchema as JSONSchema7)) as JSONSchema7)
3635+
: undefined;
3636+
const sharedDefinitions = processedApiSchema
35783637
? findSharedSchemaDefinitions(
35793638
processed as unknown as Record<string, unknown>,
3580-
postProcessSchema(cloneSchemaForCodegen(apiSchema as JSONSchema7)) as unknown as Record<string, unknown>
3639+
processedApiSchema as unknown as Record<string, unknown>
35813640
)
35823641
: new Set<string>();
35833642
const reachableDefinitions = collectReachableDefinitionNames(processed as unknown as Record<string, unknown>);
35843643
const sharedSessionEventDefinitions = new Set([...sharedDefinitions].filter((name) => reachableDefinitions.has(name)));
35853644
const sessionSchema = rewriteSharedDefinitionReferences(processed, sharedDefinitions, "api.schema.json", true);
35863645

3587-
const generatedSessionCode = generateGoSessionEventsCode(sessionSchema, "rpc");
3646+
const generatedSessionCode = generateGoSessionEventsCode(
3647+
sessionSchema,
3648+
"rpc",
3649+
processedApiSchema ? { "api.schema.json": processedApiSchema } : undefined
3650+
);
35883651
let generatedTypeCode = stripTrailingGoWhitespace(generatedSessionCode.typeCode);
35893652
// Annotate internal session-event types (driven by the JSON Schema definition's
35903653
// `visibility: "internal"` flag). Matches what the RPC generator does below;

0 commit comments

Comments
 (0)