diff --git a/src/main.ts b/src/main.ts index 821604db3..5989288b0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -468,8 +468,14 @@ export type Utils = ReturnType & ReturnType & ReturnType; +export enum MakeUtilsExportCreatePartialAs { + EXPORT_AS_UNDEFINED, + EXPORT_AS_DEFINED, + EXPORT_AS_OPTIONAL, +} + /** These are runtime utility methods used by the generated code. */ -export function makeUtils(options: Options): Utils { +export function makeUtils(options: Options, exportPartialAs: MakeUtilsExportCreatePartialAs): Utils { const bytes = makeByteUtils(options); const longs = makeLongUtils(options, bytes); const deepPartial = makeDeepPartial(options, longs); @@ -485,7 +491,7 @@ export function makeUtils(options: Options): Utils { ...makeGrpcWebErrorClass(bytes), ...extension, ...makeAssertionUtils(bytes), - ...makeMessageFns(options, deepPartial, extension), + ...makeMessageFns(options, deepPartial, extension, exportPartialAs), }; } @@ -707,6 +713,7 @@ function makeMessageFns( options: Options, deepPartial: ReturnType, extension: ReturnType, + exportPartialAs: MakeUtilsExportCreatePartialAs, ) { const BinaryWriter = imp("BinaryWriter@@bufbuild/protobuf/wire"); const BinaryReader = imp("BinaryReader@@bufbuild/protobuf/wire"); @@ -773,10 +780,20 @@ function makeMessageFns( if (options.outputPartialMethods) { if (options.useExactTypes) { commonStaticMembers.push(code`create, I>>(base?: I): T;`); - commonStaticMembers.push(code`fromPartial, I>>(object: I): T;`); + + if (exportPartialAs === MakeUtilsExportCreatePartialAs.EXPORT_AS_DEFINED) { + commonStaticMembers.push(code`fromPartial, I>>(object: I): T;`); + } else if (exportPartialAs === MakeUtilsExportCreatePartialAs.EXPORT_AS_OPTIONAL) { + commonStaticMembers.push(code`fromPartial?: , I>>(object: I) => T;`); + } } else { commonStaticMembers.push(code`create(base?: DeepPartial): T;`); - commonStaticMembers.push(code`fromPartial(object: DeepPartial): T;`); + + if (exportPartialAs === MakeUtilsExportCreatePartialAs.EXPORT_AS_DEFINED) { + commonStaticMembers.push(code`fromPartial(object: DeepPartial): T;`); + } else if (exportPartialAs === MakeUtilsExportCreatePartialAs.EXPORT_AS_OPTIONAL) { + commonStaticMembers.push(code`fromPartial?: (object: DeepPartial) => T;`); + } } } diff --git a/src/plugin.ts b/src/plugin.ts index e0df00540..3d2e08ab4 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -5,12 +5,12 @@ import { FileDescriptorProto, } from "ts-proto-descriptors"; import { promisify } from "util"; -import { generateIndexFiles, getVersions, protoFilesToGenerate, readToBuffer } from "./utils"; -import { generateFile, makeUtils } from "./main"; -import { createTypeMap } from "./types"; import { BaseContext, createFileContext } from "./context"; -import { getTsPoetOpts, optionsFromParameter } from "./options"; import { generateTypeRegistry } from "./generate-type-registry"; +import { generateFile, makeUtils, MakeUtilsExportCreatePartialAs } from "./main"; +import { getTsPoetOpts, optionsFromParameter } from "./options"; +import { createTypeMap } from "./types"; +import { generateIndexFiles, getVersions, protoFilesToGenerate, readToBuffer } from "./utils"; // this would be the plugin called by the protoc compiler async function main() { @@ -23,8 +23,6 @@ async function main() { const options = optionsFromParameter(request.parameter); const typeMap = createTypeMap(request, options); - const utils = makeUtils(options); - const ctx: BaseContext = { typeMap, options, utils }; let filesToGenerate: FileDescriptorProto[]; @@ -50,14 +48,22 @@ async function main() { const files = await Promise.all( filesToGenerate.map(async (file) => { - const [path, code] = generateFile({ ...ctx, currentFile: createFileContext(file) }, file); + const fileContext = createFileContext(file); + const utils = makeUtils( + options, + fileContext.isProto3Syntax ? + MakeUtilsExportCreatePartialAs.EXPORT_AS_DEFINED : + MakeUtilsExportCreatePartialAs.EXPORT_AS_UNDEFINED + ); + const ctx: BaseContext = { typeMap, options, utils }; + const [path, code] = generateFile({ ...ctx, currentFile: fileContext }, file); const content = code.toString({ ...getTsPoetOpts(options, tsProtoVersion, protocVersion, file.name), path }); return { name: path, content }; }), ); if (options.outputTypeRegistry) { - const utils = makeUtils(options); + const utils = makeUtils(options, MakeUtilsExportCreatePartialAs.EXPORT_AS_OPTIONAL); const ctx: BaseContext = { options, typeMap, utils }; const path = "typeRegistry.ts";