Purpose: Ensure TypeScript clients and API documentation match the actual JSON format produced by Go servers. When int64 is encoded as NUMBER, TypeScript should use 'number' type and OpenAPI should document it as integer.
Output: ts-client generates correct TypeScript types based on encoding annotation. OpenAPI generates correct schemas with appropriate type and precision warnings.
<execution_context> @/Users/sebastienmelki/.claude/get-shit-done/workflows/execute-plan.md @/Users/sebastienmelki/.claude/get-shit-done/templates/summary.md </execution_context>
Generator code to modify
@internal/tsclientgen/types.go @internal/tsclientgen/generator.go @internal/openapiv3/types.go @internal/openapiv3/generator.go
Annotation package from Plan 01#
@internal/annotations/int64_encoding.go
-
Update tsScalarType function to accept *protogen.Field instead of just protoreflect.Kind:
- Current:
func tsScalarType(kind protoreflect.Kind) string - New:
func tsScalarTypeForField(field *protogen.Field) string - Keep tsScalarType as internal helper that tsScalarTypeForField calls
- Current:
-
For int64/uint64 kinds, check annotation:
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind,
protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
if annotations.IsInt64NumberEncoding(field) {
return tsNumber // "number" - precision risk but matches JSON
}
return tsString // default: "string" per proto3 JSON spec-
Update callers of tsScalarType to use tsScalarTypeForField where field context is available
-
Update tsZeroCheck for NUMBER encoding:
case "int64", "sint64", "sfixed64", "uint64", "fixed64":
// Check if NUMBER encoding - zero check is different
// STRING: ' !== "0"'
// NUMBER: ' !== 0'
// Note: Need to pass field or encoding info to tsZeroCheck- Consider adding a comment in generated TypeScript for NUMBER encoding:
export interface Tweet {
id: number; // int64 with NUMBER encoding - values > 2^53 may lose precision
authorId: string; // int64 with STRING encoding (default)
}- For int64/uint64 kinds, check annotation and generate appropriate schema:
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
if annotations.IsInt64NumberEncoding(field) {
schema.Type = []string{headerTypeInteger}
schema.Format = headerTypeInt64
// Add precision warning to description
warningDesc := "Warning: Values > 2^53 may lose precision in JavaScript"
if schema.Description != "" {
schema.Description = schema.Description + ". " + warningDesc
} else {
schema.Description = warningDesc
}
} else {
// Default: string encoding per proto3 JSON spec
schema.Type = []string{headerTypeString}
schema.Format = headerTypeInt64
}
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
if annotations.IsInt64NumberEncoding(field) {
schema.Type = []string{headerTypeInteger}
schema.Format = headerTypeUint64
zero := 0.0
schema.Minimum = &zero
// Add precision warning
warningDesc := "Warning: Values > 2^53 may lose precision in JavaScript"
if schema.Description != "" {
schema.Description = schema.Description + ". " + warningDesc
} else {
schema.Description = warningDesc
}
} else {
// Default: string encoding per proto3 JSON spec
schema.Type = []string{headerTypeString}
schema.Format = headerTypeUint64
}- Verify OpenAPI output matches expected format from RESEARCH.md:
NUMBER encoding:
id:
type: integer
format: int64
description: "Warning: Values > 2^53 may lose precision in JavaScript"STRING encoding (default):
id:
type: string
format: int64- For ts-client (symlink or copy from httpgen testdata):
# If using symlinks like other testdata
ln -sf ../../httpgen/testdata/encoding.proto internal/tsclientgen/testdata/encoding.protoOr create internal/tsclientgen/testdata/encoding.proto with int64_encoding annotations.
-
For openapiv3, create internal/openapiv3/testdata/encoding.proto (or symlink).
-
Run golden file tests with UPDATE_GOLDEN:
UPDATE_GOLDEN=1 go test -run TestGoldenFiles ./internal/tsclientgen/...
UPDATE_GOLDEN=1 go test -run TestExhaustiveGoldenFiles ./internal/openapiv3/...- Verify golden files contain expected patterns:
TypeScript golden (encoding_client.ts):
export interface Int64EncodingTest {
defaultInt64: string; // default -> string
stringInt64: string; // explicit STRING -> string
numberInt64: number; // NUMBER -> number
defaultUint64: string; // default -> string
numberUint64: number; // NUMBER -> number
repeatedNumberInt64: number[]; // repeated NUMBER -> number[]
}OpenAPI golden (EncodingTestService.openapi.yaml):
Int64EncodingTest:
type: object
properties:
defaultInt64:
type: string
format: int64
numberInt64:
type: integer
format: int64
description: "Warning: Values > 2^53 may lose precision in JavaScript"<success_criteria>
- TypeScript: int64_encoding=NUMBER ->
number, STRING/UNSPECIFIED ->string - OpenAPI: int64_encoding=NUMBER ->
type: integer, STRING/UNSPECIFIED ->type: string - OpenAPI NUMBER fields include precision warning in description
- Cross-generator consistency: TS types match OpenAPI schemas match Go JSON output
- Backward compatible: protos without annotations produce identical output to before </success_criteria>
