218 lines
8.6 KiB
JavaScript
218 lines
8.6 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.DefaultPayloadConverterWithProtobufs = exports.ProtobufJsonPayloadConverter = exports.ProtobufBinaryPayloadConverter = void 0;
|
|
const protoJsonSerializer = __importStar(require("proto3-json-serializer"));
|
|
const encoding_1 = require("../encoding");
|
|
const errors_1 = require("../errors");
|
|
const type_helpers_1 = require("../type-helpers");
|
|
const payload_converter_1 = require("./payload-converter");
|
|
const types_1 = require("./types");
|
|
const GLOBAL_BUFFER = globalThis.constructor.constructor('return globalThis.Buffer')();
|
|
class ProtobufPayloadConverter {
|
|
root;
|
|
// Don't use type Root here because root.d.ts doesn't export Root, so users would have to type assert
|
|
constructor(root) {
|
|
if (root) {
|
|
if (!isRoot(root)) {
|
|
throw new TypeError('root must be an instance of a protobufjs Root');
|
|
}
|
|
this.root = root;
|
|
}
|
|
}
|
|
validatePayload(content) {
|
|
if (content.data === undefined || content.data === null) {
|
|
throw new errors_1.ValueError('Got payload with no data');
|
|
}
|
|
if (!content.metadata || !(types_1.METADATA_MESSAGE_TYPE_KEY in content.metadata)) {
|
|
throw new errors_1.ValueError(`Got protobuf payload without metadata.${types_1.METADATA_MESSAGE_TYPE_KEY}`);
|
|
}
|
|
if (!this.root) {
|
|
throw new errors_1.PayloadConverterError('Unable to deserialize protobuf message without `root` being provided');
|
|
}
|
|
const messageTypeName = (0, encoding_1.decode)(content.metadata[types_1.METADATA_MESSAGE_TYPE_KEY]);
|
|
let messageType;
|
|
try {
|
|
messageType = this.root.lookupType(messageTypeName);
|
|
}
|
|
catch (e) {
|
|
if ((0, type_helpers_1.errorMessage)(e)?.includes('no such type')) {
|
|
throw new errors_1.PayloadConverterError(`Got a \`${messageTypeName}\` protobuf message but cannot find corresponding message class in \`root\``);
|
|
}
|
|
throw e;
|
|
}
|
|
return { messageType, data: content.data };
|
|
}
|
|
constructPayload({ messageTypeName, message }) {
|
|
return {
|
|
metadata: {
|
|
[types_1.METADATA_ENCODING_KEY]: (0, encoding_1.encode)(this.encodingType),
|
|
[types_1.METADATA_MESSAGE_TYPE_KEY]: (0, encoding_1.encode)(messageTypeName),
|
|
},
|
|
data: message,
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Converts between protobufjs Message instances and serialized Protobuf Payload
|
|
*/
|
|
class ProtobufBinaryPayloadConverter extends ProtobufPayloadConverter {
|
|
encodingType = types_1.encodingTypes.METADATA_ENCODING_PROTOBUF;
|
|
/**
|
|
* @param root The value returned from {@link patchProtobufRoot}
|
|
*/
|
|
constructor(root) {
|
|
super(root);
|
|
}
|
|
toPayload(value) {
|
|
if (!isProtobufMessage(value)) {
|
|
return undefined;
|
|
}
|
|
return this.constructPayload({
|
|
messageTypeName: getNamespacedTypeName(value.$type),
|
|
message: value.$type.encode(value).finish(),
|
|
});
|
|
}
|
|
fromPayload(content) {
|
|
const { messageType, data } = this.validatePayload(content);
|
|
// Wrap with Uint8Array from this context to ensure `instanceof` works
|
|
const localData = data ? new Uint8Array(data.buffer, data.byteOffset, data.length) : data;
|
|
return messageType.decode(localData);
|
|
}
|
|
}
|
|
exports.ProtobufBinaryPayloadConverter = ProtobufBinaryPayloadConverter;
|
|
/**
|
|
* Converts between protobufjs Message instances and serialized JSON Payload
|
|
*/
|
|
class ProtobufJsonPayloadConverter extends ProtobufPayloadConverter {
|
|
encodingType = types_1.encodingTypes.METADATA_ENCODING_PROTOBUF_JSON;
|
|
/**
|
|
* @param root The value returned from {@link patchProtobufRoot}
|
|
*/
|
|
constructor(root) {
|
|
super(root);
|
|
}
|
|
toPayload(value) {
|
|
if (!isProtobufMessage(value)) {
|
|
return undefined;
|
|
}
|
|
const hasBufferChanged = setBufferInGlobal();
|
|
try {
|
|
const jsonValue = protoJsonSerializer.toProto3JSON(value);
|
|
return this.constructPayload({
|
|
messageTypeName: getNamespacedTypeName(value.$type),
|
|
message: (0, encoding_1.encode)(JSON.stringify(jsonValue)),
|
|
});
|
|
}
|
|
finally {
|
|
resetBufferInGlobal(hasBufferChanged);
|
|
}
|
|
}
|
|
fromPayload(content) {
|
|
const hasBufferChanged = setBufferInGlobal();
|
|
try {
|
|
const { messageType, data } = this.validatePayload(content);
|
|
const res = protoJsonSerializer.fromProto3JSON(messageType, JSON.parse((0, encoding_1.decode)(data)));
|
|
if (Buffer.isBuffer(res)) {
|
|
return new Uint8Array(res);
|
|
}
|
|
replaceBuffers(res);
|
|
return res;
|
|
}
|
|
finally {
|
|
resetBufferInGlobal(hasBufferChanged);
|
|
}
|
|
}
|
|
}
|
|
exports.ProtobufJsonPayloadConverter = ProtobufJsonPayloadConverter;
|
|
function replaceBuffers(obj) {
|
|
const replaceBuffersImpl = (value, key, target) => {
|
|
if (Buffer.isBuffer(value)) {
|
|
target[key] = new Uint8Array(value);
|
|
}
|
|
else {
|
|
replaceBuffers(value);
|
|
}
|
|
};
|
|
if (obj != null && typeof obj === 'object') {
|
|
// Performance optimization for large arrays
|
|
if (Array.isArray(obj)) {
|
|
obj.forEach(replaceBuffersImpl);
|
|
}
|
|
else {
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
replaceBuffersImpl(value, key, obj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function setBufferInGlobal() {
|
|
if (typeof globalThis.Buffer === 'undefined') {
|
|
globalThis.Buffer = GLOBAL_BUFFER;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function resetBufferInGlobal(hasChanged) {
|
|
if (hasChanged) {
|
|
delete globalThis.Buffer;
|
|
}
|
|
}
|
|
function isProtobufType(type) {
|
|
return ((0, type_helpers_1.isRecord)(type) &&
|
|
// constructor.name may get mangled by minifiers; thanksfuly protobufjs also sets a className property
|
|
type.constructor.className === 'Type' &&
|
|
(0, type_helpers_1.hasOwnProperties)(type, ['parent', 'name', 'create', 'encode', 'decode']) &&
|
|
typeof type.name === 'string' &&
|
|
typeof type.create === 'function' &&
|
|
typeof type.encode === 'function' &&
|
|
typeof type.decode === 'function');
|
|
}
|
|
function isProtobufMessage(value) {
|
|
return (0, type_helpers_1.isRecord)(value) && (0, type_helpers_1.hasOwnProperty)(value, '$type') && isProtobufType(value.$type);
|
|
}
|
|
function getNamespacedTypeName(node) {
|
|
if (node.parent && !isRoot(node.parent)) {
|
|
return getNamespacedTypeName(node.parent) + '.' + node.name;
|
|
}
|
|
else {
|
|
return node.name;
|
|
}
|
|
}
|
|
function isRoot(root) {
|
|
// constructor.name may get mangled by minifiers; thanksfuly protobufjs also sets a className property
|
|
return (0, type_helpers_1.isRecord)(root) && root.constructor.className === 'Root';
|
|
}
|
|
class DefaultPayloadConverterWithProtobufs extends payload_converter_1.CompositePayloadConverter {
|
|
// Match the order used in other SDKs.
|
|
//
|
|
// Go SDK:
|
|
// https://github.com/temporalio/sdk-go/blob/5e5645f0c550dcf717c095ae32c76a7087d2e985/converter/default_data_converter.go#L28
|
|
constructor({ protobufRoot }) {
|
|
super(new payload_converter_1.UndefinedPayloadConverter(), new payload_converter_1.BinaryPayloadConverter(), new ProtobufJsonPayloadConverter(protobufRoot), new ProtobufBinaryPayloadConverter(protobufRoot), new payload_converter_1.JsonPayloadConverter());
|
|
}
|
|
}
|
|
exports.DefaultPayloadConverterWithProtobufs = DefaultPayloadConverterWithProtobufs;
|
|
//# sourceMappingURL=protobuf-payload-converters.js.map
|