From 49035a47e1d859563c631267ea7e1724cbf2c4a8 Mon Sep 17 00:00:00 2001 From: Zak Henry Date: Tue, 12 Nov 2024 03:14:07 +1300 Subject: [PATCH] fix(Schema generation): ensure Buffer api is only used when in nodejs environment (#1134) Co-authored-by: Zak Henry --- integration/options/options.ts | 17 +++++++++++++++-- src/schema.ts | 8 ++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/integration/options/options.ts b/integration/options/options.ts index fd07762c4..cb0b47d86 100644 --- a/integration/options/options.ts +++ b/integration/options/options.ts @@ -472,7 +472,7 @@ export const protoMetadata: ProtoMetadata = { options: { "my_message_option": 1234 }, fields: { "foo": { "my_field_option": 4.5 }, - "foo_2": { "something": Something.decode(Buffer.from("CgV3b3JsZBIDe9kC", "base64")) }, + "foo_2": { "something": Something.decode(bytesFromBase64("CgV3b3JsZBIDe9kC")) }, }, oneof: { "qux": { "my_oneof_option": 42 } }, }, @@ -482,7 +482,7 @@ export const protoMetadata: ProtoMetadata = { options: { "my_service_option": 0 }, methods: { "MyMethod": { - "my_method_option": MyMessage.decode(Buffer.from("CJYBEJYBGgtTb21lIHN0cmluZyILU29tZSBzdHJpbmc=", "base64")), + "my_method_option": MyMessage.decode(bytesFromBase64("CJYBEJYBGgtTb21lIHN0cmluZyILU29tZSBzdHJpbmc=")), }, }, }, @@ -491,6 +491,19 @@ export const protoMetadata: ProtoMetadata = { }, }; +function bytesFromBase64(b64: string): Uint8Array { + if ((globalThis as any).Buffer) { + return Uint8Array.from(globalThis.Buffer.from(b64, "base64")); + } else { + const bin = globalThis.atob(b64); + const arr = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; ++i) { + arr[i] = bin.charCodeAt(i); + } + return arr; + } +} + export interface MessageFns { encode(message: T, writer?: BinaryWriter): BinaryWriter; decode(input: BinaryReader | Uint8Array, length?: number): T; diff --git a/src/schema.ts b/src/schema.ts index 8b5e46f0a..e2fc3be62 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -11,7 +11,7 @@ import SourceInfo from "./sourceInfo"; import { impFile, maybePrefixPackage } from "./utils"; import { basicTypeName, toReaderCall } from "./types"; import { BinaryReader } from "@bufbuild/protobuf/wire"; -import { OutputSchemaOption } from "./options"; +import { EnvOption, OutputSchemaOption } from "./options"; const fileDescriptorProto = imp("FileDescriptorProto@ts-proto-descriptors"); @@ -216,7 +216,11 @@ function getExtensionValue(ctx: Context, extension: FieldDescriptorProto, data: }), ); const result = resultBuffer.toString("base64"); - return code`'${extension.name}': ${typeName}.decode(Buffer.from('${result}', 'base64'))`; + const encoded = + ctx.options.env === EnvOption.NODE + ? code`Buffer.from('${result}', 'base64')` + : code`${ctx.utils.bytesFromBase64}("${result}")`; + return code`'${extension.name}': ${typeName}.decode(${encoded})`; } else { const reader = new BinaryReader(data[0]); let value = (reader as any)[toReaderCall(extension)]();