diff --git a/features/data_converter/binary_protobuf/feature.ts b/features/data_converter/binary_protobuf/feature.ts index ed60d7ec..3d0f3854 100644 --- a/features/data_converter/binary_protobuf/feature.ts +++ b/features/data_converter/binary_protobuf/feature.ts @@ -2,16 +2,17 @@ import * as assert from 'assert'; import { Feature } from '@temporalio/harness'; import * as proto from '@temporalio/proto'; -// Inject Buffer and Uint8Array from the node context to the workflow context to workaround SDK bug -// TODO(antlai-temporal) Remove when SDK bug is fixed -const g = globalThis as any; -g.Uint8Array = g.constructor.constructor('return globalThis.Uint8Array')(); - const expectedResult = proto.temporal.api.common.v1.DataBlob.create({ encodingType: proto.temporal.api.enums.v1.EncodingType.ENCODING_TYPE_UNSPECIFIED, data: new Uint8Array([0xde, 0xad, 0xbe, 0xef]), }); +// Do an encode/decode roundtrip to make sure our test expectations match exactly +// what protobufjs 8 will produce (e.g. default values are omitted, etc.) +const expectedResultOnWire = proto.temporal.api.common.v1.DataBlob.decode( + proto.temporal.api.common.v1.DataBlob.encode(expectedResult).finish(), +); + // An "echo" workflow export async function workflow( res: proto.temporal.api.common.v1.DataBlob, @@ -30,7 +31,7 @@ export const feature = new Feature({ async checkResult(runner, handle) { // verify client result is DataBlob `0xdeadbeef` const result = await handle.result(); - assert.deepEqual(result, expectedResult); + assert.deepEqual(result, expectedResultOnWire); // get result payload of WorkflowExecutionCompleted event from workflow history const payload = await runner.getWorkflowResultPayload(handle); @@ -45,7 +46,7 @@ export const feature = new Feature({ assert.ok(payload.data); const resultInHistory = proto.temporal.api.common.v1.DataBlob.decode(payload.data); - assert.deepEqual(resultInHistory, expectedResult); + assert.deepEqual(resultInHistory, expectedResultOnWire); // get argument payload of WorkflowExecutionStarted event from workflow history const payloadArg = await runner.getWorkflowArgumentPayload(handle); diff --git a/features/data_converter/json_protobuf/feature.ts b/features/data_converter/json_protobuf/feature.ts index fa59a758..d1853c09 100644 --- a/features/data_converter/json_protobuf/feature.ts +++ b/features/data_converter/json_protobuf/feature.ts @@ -1,5 +1,5 @@ import * as assert from 'assert'; -import { fromProto3JSON } from 'proto3-json-serializer'; +import * as protojson from 'protobufjs/ext/protojson'; import { Feature } from '@temporalio/harness'; import * as proto from '@temporalio/proto'; import { patchProtobufRoot } from '@temporalio/proto/lib/patch-protobuf-root'; @@ -9,16 +9,17 @@ import { decode } from '@temporalio/common/lib/encoding'; const patched = patchProtobufRoot(proto) as any; const dataBlobType = patched.lookupType('temporal.api.common.v1.DataBlob'); -// Inject Buffer and Uint8Array from the node context to the workflow context to workaround SDK bug -// TODO(antlai-temporal) Remove workaround when SDK bug is fixed -const g = globalThis as any; -g.Buffer = g.constructor.constructor('return globalThis.Buffer')(); - const expectedResult = proto.temporal.api.common.v1.DataBlob.create({ encodingType: proto.temporal.api.enums.v1.EncodingType.ENCODING_TYPE_UNSPECIFIED, data: new Uint8Array([0xde, 0xad, 0xbe, 0xef]), }); +// Do an encode/decode roundtrip to make sure our test expectations match exactly +// what protobufjs 8 will produce (e.g. default values are omitted, etc.) +const expectedResultOnWire = proto.temporal.api.common.v1.DataBlob.decode( + proto.temporal.api.common.v1.DataBlob.encode(expectedResult).finish(), +); + // An "echo" workflow export async function workflow( res: proto.temporal.api.common.v1.DataBlob, @@ -37,7 +38,7 @@ export const feature = new Feature({ async checkResult(runner, handle) { // verify client result is DataBlob `0xdeadbeef` const result = await handle.result(); - assert.deepEqual(result, expectedResult); + assert.deepEqual(result, expectedResultOnWire); // get result payload of WorkflowExecutionCompleted event from workflow history const payload = await runner.getWorkflowResultPayload(handle); @@ -50,9 +51,9 @@ export const feature = new Feature({ assert.equal(Buffer.from(payload.metadata.messageType).toString(), 'temporal.api.common.v1.DataBlob'); assert.ok(payload.data); - const resultInHistory = fromProto3JSON(dataBlobType, JSON.parse(decode(payload.data))); + const resultInHistory = protojson.fromJson(dataBlobType, JSON.parse(decode(payload.data))); assert.ok(resultInHistory); - assert.deepEqual(resultInHistory, expectedResult); + assert.deepEqual(resultInHistory, expectedResultOnWire); // get argument payload of WorkflowExecutionStarted event from workflow history const payloadArg = await runner.getWorkflowArgumentPayload(handle); @@ -65,7 +66,7 @@ export const feature = new Feature({ assert.equal(Buffer.from(payloadArg.metadata.messageType).toString(), 'temporal.api.common.v1.DataBlob'); assert.ok(payloadArg.data); - const resultArgInHistory = fromProto3JSON(dataBlobType, JSON.parse(decode(payloadArg.data))); + const resultArgInHistory = protojson.fromJson(dataBlobType, JSON.parse(decode(payloadArg.data))); assert.ok(resultArgInHistory); assert.deepEqual(resultInHistory, resultArgInHistory); }, diff --git a/package-lock.json b/package-lock.json index 01544086..73cda0eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,7 @@ "commander": "^8.3.0", "ms": "^3.0.0-canary.1", "nexus-rpc": "^0.0.1", - "proto3-json-serializer": "^1.1.1", - "protobufjs": "7.5.1" + "protobufjs": "^8.7.1" }, "devDependencies": { "@tsconfig/node24": "^24.0.4", @@ -1281,6 +1280,29 @@ "node": ">=14.0.0" } }, + "node_modules/@temporalio/common/node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/@temporalio/core-bridge": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/@temporalio/core-bridge/-/core-bridge-1.18.1.tgz", @@ -5024,37 +5046,13 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/proto3-json-serializer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz", - "integrity": "sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw==", - "license": "Apache-2.0", - "dependencies": { - "protobufjs": "^7.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/protobufjs": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.1.tgz", - "integrity": "sha512-3qx3IRjR9WPQKagdwrKjO3Gu8RgQR2qqw+1KnigWhoVjFqegIj1K3bP11sGqhxrO46/XL7lekuG4jmjL+4cLsw==", - "hasInstallScript": true, + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.7.1.tgz", + "integrity": "sha512-agdGHrXNTv0IrYscJPDou/PlEJk1c/hBZ9o/B5NH2i/nSPtPqacNxzgwf1CebXxFMjMrZH5sqv9uQuw96aGt/A==", "license": "BSD-3-Clause", "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" + "long": "^5.3.2" }, "engines": { "node": ">=12.0.0" diff --git a/package.json b/package.json index 9edd2c25..2a6b9eb4 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,7 @@ "commander": "^8.3.0", "ms": "^3.0.0-canary.1", "nexus-rpc": "^0.0.1", - "proto3-json-serializer": "^1.1.1", - "protobufjs": "7.5.1" + "protobufjs": "^8.7.1" }, "devDependencies": { "@tsconfig/node24": "^24.0.4", diff --git a/sdkbuild/typescript.go b/sdkbuild/typescript.go index 3ba3db5a..3334bf38 100644 --- a/sdkbuild/typescript.go +++ b/sdkbuild/typescript.go @@ -141,18 +141,13 @@ func BuildTypeScriptProgram(ctx context.Context, options BuildTypeScriptProgramO "commander": "^8.3.0", "ms": "^3.0.0-canary.1", "nexus-rpc": "^0.0.1", - "proto3-json-serializer": "^1.1.1" + "protobufjs": "^8.7.1" }, "devDependencies": { "@tsconfig/node24": "^24.0.4", "@types/node": "^24.1.0", "tsconfig-paths": "^3.12.0", "typescript": "^5.9.3" - }, - "pnpm": { - "overrides": { - "protobufjs": "7.5.1" - } } }` if err := os.WriteFile(filepath.Join(dir, "package.json"), []byte(packageJSON), 0644); err != nil {