260 lines
9.4 KiB
JavaScript
260 lines
9.4 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.defaultPayloadConverter = exports.DefaultPayloadConverter = exports.JsonPayloadConverter = exports.BinaryPayloadConverter = exports.UndefinedPayloadConverter = exports.CompositePayloadConverter = exports.RawValue = void 0;
|
|
exports.toPayloads = toPayloads;
|
|
exports.convertOptionalToPayload = convertOptionalToPayload;
|
|
exports.mapToPayloads = mapToPayloads;
|
|
exports.fromPayloadsAtIndex = fromPayloadsAtIndex;
|
|
exports.arrayFromPayloads = arrayFromPayloads;
|
|
exports.mapFromPayloads = mapFromPayloads;
|
|
const encoding_1 = require("../encoding");
|
|
const errors_1 = require("../errors");
|
|
const types_1 = require("./types");
|
|
/**
|
|
* Implements conversion of a list of values.
|
|
*
|
|
* @param converter
|
|
* @param values JS values to convert to Payloads
|
|
* @return list of {@link Payload}s
|
|
* @throws {@link ValueError} if conversion of the value passed as parameter failed for any
|
|
* reason.
|
|
*/
|
|
function toPayloads(converter, ...values) {
|
|
if (values.length === 0) {
|
|
return undefined;
|
|
}
|
|
return values.map((value) => converter.toPayload(value));
|
|
}
|
|
/**
|
|
* Run {@link PayloadConverter.toPayload} on an optional value, and then encode it.
|
|
*/
|
|
function convertOptionalToPayload(payloadConverter, value) {
|
|
if (value == null)
|
|
return value;
|
|
return payloadConverter.toPayload(value);
|
|
}
|
|
/**
|
|
* Run {@link PayloadConverter.toPayload} on each value in the map.
|
|
*
|
|
* @throws {@link ValueError} if conversion of any value in the map fails
|
|
*/
|
|
function mapToPayloads(converter, map) {
|
|
return Object.fromEntries(Object.entries(map).map(([k, v]) => [k, converter.toPayload(v)]));
|
|
}
|
|
/**
|
|
* Implements conversion of an array of values of different types. Useful for deserializing
|
|
* arguments of function invocations.
|
|
*
|
|
* @param converter
|
|
* @param index index of the value in the payloads
|
|
* @param payloads serialized value to convert to JS values.
|
|
* @return converted JS value
|
|
* @throws {@link PayloadConverterError} if conversion of the data passed as parameter failed for any
|
|
* reason.
|
|
*/
|
|
function fromPayloadsAtIndex(converter, index, payloads) {
|
|
// To make adding arguments a backwards compatible change
|
|
if (payloads === undefined || payloads === null || index >= payloads.length) {
|
|
return undefined;
|
|
}
|
|
const payload = payloads?.[index];
|
|
if (!payload) {
|
|
return undefined;
|
|
}
|
|
return converter.fromPayload(payload);
|
|
}
|
|
/**
|
|
* Run {@link PayloadConverter.fromPayload} on each value in the array.
|
|
*/
|
|
function arrayFromPayloads(converter, payloads) {
|
|
if (!payloads) {
|
|
return [];
|
|
}
|
|
return payloads.map((payload) => converter.fromPayload(payload));
|
|
}
|
|
function mapFromPayloads(converter, map) {
|
|
if (map == null)
|
|
return undefined;
|
|
return Object.fromEntries(Object.entries(map).map(([k, payload]) => {
|
|
const value = converter.fromPayload(payload);
|
|
return [k, value];
|
|
}));
|
|
}
|
|
/**
|
|
* RawValue is a wrapper over a payload.
|
|
* A payload that belongs to a RawValue is special in that it bypasses user-defined payload converters,
|
|
* instead using the default payload converter. The payload still undergoes codec conversion.
|
|
*/
|
|
class RawValue {
|
|
_payload;
|
|
[exports.rawPayloadTypeBrand] = undefined;
|
|
constructor(value, payloadConverter = exports.defaultPayloadConverter) {
|
|
this._payload = payloadConverter.toPayload(value);
|
|
}
|
|
static fromPayload(p) {
|
|
return new RawValue(p, identityPayloadConverter);
|
|
}
|
|
get payload() {
|
|
return this._payload;
|
|
}
|
|
}
|
|
exports.RawValue = RawValue;
|
|
/**
|
|
* Tries to convert values to {@link Payload}s using the {@link PayloadConverterWithEncoding}s provided to the constructor, in the order provided.
|
|
*
|
|
* Converts Payloads to values based on the `Payload.metadata.encoding` field, which matches the {@link PayloadConverterWithEncoding.encodingType}
|
|
* of the converter that created the Payload.
|
|
*/
|
|
class CompositePayloadConverter {
|
|
converters;
|
|
converterByEncoding = new Map();
|
|
constructor(...converters) {
|
|
if (converters.length === 0) {
|
|
throw new errors_1.PayloadConverterError('Must provide at least one PayloadConverterWithEncoding');
|
|
}
|
|
this.converters = converters;
|
|
for (const converter of converters) {
|
|
this.converterByEncoding.set(converter.encodingType, converter);
|
|
}
|
|
}
|
|
/**
|
|
* Tries to run `.toPayload(value)` on each converter in the order provided at construction.
|
|
* Returns the first successful result, throws {@link ValueError} if there is no converter that can handle the value.
|
|
*/
|
|
toPayload(value) {
|
|
if (value instanceof RawValue) {
|
|
return value.payload;
|
|
}
|
|
for (const converter of this.converters) {
|
|
const result = converter.toPayload(value);
|
|
if (result !== undefined) {
|
|
return result;
|
|
}
|
|
}
|
|
throw new errors_1.ValueError(`Unable to convert ${value} to payload`);
|
|
}
|
|
/**
|
|
* Run {@link PayloadConverterWithEncoding.fromPayload} based on the `encoding` metadata of the {@link Payload}.
|
|
*/
|
|
fromPayload(payload) {
|
|
if (payload.metadata === undefined || payload.metadata === null) {
|
|
throw new errors_1.ValueError('Missing payload metadata');
|
|
}
|
|
const encoding = (0, encoding_1.decode)(payload.metadata[types_1.METADATA_ENCODING_KEY]);
|
|
const converter = this.converterByEncoding.get(encoding);
|
|
if (converter === undefined) {
|
|
throw new errors_1.ValueError(`Unknown encoding: ${encoding}`);
|
|
}
|
|
return converter.fromPayload(payload);
|
|
}
|
|
}
|
|
exports.CompositePayloadConverter = CompositePayloadConverter;
|
|
/**
|
|
* Converts between JS undefined and NULL Payload
|
|
*/
|
|
class UndefinedPayloadConverter {
|
|
encodingType = types_1.encodingTypes.METADATA_ENCODING_NULL;
|
|
toPayload(value) {
|
|
if (value !== undefined) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
metadata: {
|
|
[types_1.METADATA_ENCODING_KEY]: types_1.encodingKeys.METADATA_ENCODING_NULL,
|
|
},
|
|
};
|
|
}
|
|
fromPayload(_content) {
|
|
return undefined; // Just return undefined
|
|
}
|
|
}
|
|
exports.UndefinedPayloadConverter = UndefinedPayloadConverter;
|
|
/**
|
|
* Converts between binary data types and RAW Payload
|
|
*/
|
|
class BinaryPayloadConverter {
|
|
encodingType = types_1.encodingTypes.METADATA_ENCODING_RAW;
|
|
toPayload(value) {
|
|
if (!(value instanceof Uint8Array)) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
metadata: {
|
|
[types_1.METADATA_ENCODING_KEY]: types_1.encodingKeys.METADATA_ENCODING_RAW,
|
|
},
|
|
data: value,
|
|
};
|
|
}
|
|
fromPayload(content) {
|
|
return (
|
|
// Wrap with Uint8Array from this context to ensure `instanceof` works
|
|
(content.data ? new Uint8Array(content.data.buffer, content.data.byteOffset, content.data.length) : content.data));
|
|
}
|
|
}
|
|
exports.BinaryPayloadConverter = BinaryPayloadConverter;
|
|
/**
|
|
* Converts between non-undefined values and serialized JSON Payload
|
|
*/
|
|
class JsonPayloadConverter {
|
|
encodingType = types_1.encodingTypes.METADATA_ENCODING_JSON;
|
|
toPayload(value) {
|
|
if (value === undefined) {
|
|
return undefined;
|
|
}
|
|
let json;
|
|
try {
|
|
json = JSON.stringify(value);
|
|
}
|
|
catch (_err) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
metadata: {
|
|
[types_1.METADATA_ENCODING_KEY]: types_1.encodingKeys.METADATA_ENCODING_JSON,
|
|
},
|
|
data: (0, encoding_1.encode)(json),
|
|
};
|
|
}
|
|
fromPayload(content) {
|
|
if (content.data === undefined || content.data === null) {
|
|
throw new errors_1.ValueError('Got payload with no data');
|
|
}
|
|
return JSON.parse((0, encoding_1.decode)(content.data));
|
|
}
|
|
}
|
|
exports.JsonPayloadConverter = JsonPayloadConverter;
|
|
class DefaultPayloadConverter extends CompositePayloadConverter {
|
|
// Match the order used in other SDKs, but exclude Protobuf converters so that the code, including
|
|
// `proto3-json-serializer`, doesn't take space in Workflow bundles that don't use Protobufs. To use Protobufs, use
|
|
// {@link DefaultPayloadConverterWithProtobufs}.
|
|
//
|
|
// Go SDK:
|
|
// https://github.com/temporalio/sdk-go/blob/5e5645f0c550dcf717c095ae32c76a7087d2e985/converter/default_data_converter.go#L28
|
|
constructor() {
|
|
super(new UndefinedPayloadConverter(), new BinaryPayloadConverter(), new JsonPayloadConverter());
|
|
}
|
|
}
|
|
exports.DefaultPayloadConverter = DefaultPayloadConverter;
|
|
/**
|
|
* The default {@link PayloadConverter} used by the SDK. Supports `Uint8Array` and JSON serializables (so if
|
|
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description | `JSON.stringify(yourArgOrRetval)`}
|
|
* works, the default payload converter will work).
|
|
*
|
|
* To also support Protobufs, create a custom payload converter with {@link DefaultPayloadConverter}:
|
|
*
|
|
* `const myConverter = new DefaultPayloadConverter({ protobufRoot })`
|
|
*/
|
|
exports.defaultPayloadConverter = new DefaultPayloadConverter();
|
|
/**
|
|
* The identity payload converter returns the inputs it was given.
|
|
*/
|
|
class IdentityPayloadConverter {
|
|
toPayload(value) {
|
|
return value;
|
|
}
|
|
fromPayload(payload) {
|
|
return payload;
|
|
}
|
|
}
|
|
const identityPayloadConverter = new IdentityPayloadConverter();
|
|
//# sourceMappingURL=payload-converter.js.map
|