UNPKG

@temporalio/common

Version:

Common library for code that's used across the Client, Worker, and/or Workflow

171 lines 9.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.typedSearchAttributePayloadConverter = exports.TypedSearchAttributePayloadConverter = exports.searchAttributePayloadConverter = exports.SearchAttributePayloadConverter = void 0; exports.encodeUnifiedSearchAttributes = encodeUnifiedSearchAttributes; exports.decodeSearchAttributes = decodeSearchAttributes; exports.decodeTypedSearchAttributes = decodeTypedSearchAttributes; const encoding_1 = require("../encoding"); const errors_1 = require("../errors"); const search_attributes_1 = require("../search-attributes"); const payload_converter_1 = require("./payload-converter"); /** * Converts Search Attribute values using JsonPayloadConverter */ class SearchAttributePayloadConverter { jsonConverter = new payload_converter_1.JsonPayloadConverter(); validNonDateTypes = ['string', 'number', 'boolean']; toPayload(values) { if (!Array.isArray(values)) { throw new errors_1.ValueError(`SearchAttribute value must be an array`); } if (values.length > 0) { const firstValue = values[0]; const firstType = typeof firstValue; if (firstType === 'object') { for (const [idx, value] of values.entries()) { if (!(value instanceof Date)) { throw new errors_1.ValueError(`SearchAttribute values must arrays of strings, numbers, booleans, or Dates. The value ${value} at index ${idx} is of type ${typeof value}`); } } } else { if (!this.validNonDateTypes.includes(firstType)) { throw new errors_1.ValueError(`SearchAttribute array values must be: string | number | boolean | Date`); } for (const [idx, value] of values.entries()) { if (typeof value !== firstType) { throw new errors_1.ValueError(`All SearchAttribute array values must be of the same type. The first value ${firstValue} of type ${firstType} doesn't match value ${value} of type ${typeof value} at index ${idx}`); } } } } // JSON.stringify takes care of converting Dates to ISO strings const ret = this.jsonConverter.toPayload(values); if (ret === undefined) { throw new errors_1.ValueError('Could not convert search attributes to payloads'); } return ret; } /** * Datetime Search Attribute values are converted to `Date`s */ fromPayload(payload) { if (payload.metadata == null) { throw new errors_1.ValueError('Missing payload metadata'); } const value = this.jsonConverter.fromPayload(payload); let arrayWrappedValue = Array.isArray(value) ? value : [value]; const searchAttributeType = payload.metadata.type ? (0, encoding_1.decode)(payload.metadata.type) : undefined; if (searchAttributeType === 'Datetime') { arrayWrappedValue = arrayWrappedValue.map((dateString) => new Date(dateString)); } return arrayWrappedValue; } } exports.SearchAttributePayloadConverter = SearchAttributePayloadConverter; exports.searchAttributePayloadConverter = new SearchAttributePayloadConverter(); class TypedSearchAttributePayloadConverter { jsonConverter = new payload_converter_1.JsonPayloadConverter(); toPayload(attr) { if (!(attr instanceof search_attributes_1.TypedSearchAttributeValue || attr instanceof search_attributes_1.TypedSearchAttributeUpdateValue)) { throw new errors_1.ValueError(`Expect input to be instance of TypedSearchAttributeValue or TypedSearchAttributeUpdateValue, got: ${JSON.stringify(attr)}`); } // We check for deletion as well as regular typed search attributes. if (attr.value !== null && !(0, search_attributes_1.isValidValueForType)(attr.type, attr.value)) { throw new errors_1.ValueError(`Invalid search attribute value ${attr.value} for given type ${attr.type}`); } // For server search attributes to work properly, we cannot set the metadata // type when we set null if (attr.value === null) { const payload = this.jsonConverter.toPayload(attr.value); if (payload === undefined) { throw new errors_1.ValueError('Could not convert typed search attribute to payload'); } return payload; } // JSON.stringify takes care of converting Dates to ISO strings const payload = this.jsonConverter.toPayload(attr.value); if (payload === undefined) { throw new errors_1.ValueError('Could not convert typed search attribute to payload'); } // Note: this shouldn't be the case but the compiler complains without this check. if (payload.metadata == null) { throw new errors_1.ValueError('Missing payload metadata'); } // Add encoded type of search attribute to metatdata payload.metadata['type'] = (0, encoding_1.encode)(search_attributes_1.TypedSearchAttributes.toMetadataType(attr.type)); return payload; } // Note: type casting undefined values is not clear to caller. // We can't change the typing of the method to return undefined, it's not allowed by the interface. fromPayload(payload) { if (payload.metadata == null) { throw new errors_1.ValueError('Missing payload metadata'); } // If no 'type' metadata field or no given value, we skip. if (payload.metadata.type == null) { return undefined; } const type = search_attributes_1.TypedSearchAttributes.toSearchAttributeType((0, encoding_1.decode)(payload.metadata.type)); // Unrecognized metadata type (sanity check). if (type === undefined) { return undefined; } let value = this.jsonConverter.fromPayload(payload); // Handle legacy values without KEYWORD_LIST type. if (type !== search_attributes_1.SearchAttributeType.KEYWORD_LIST && Array.isArray(value)) { // Cannot have an array with multiple values for non-KEYWORD_LIST type. if (value.length > 1) { return undefined; } // Unpack single value array. value = value[0]; } if (type === search_attributes_1.SearchAttributeType.DATETIME && value) { value = new Date(value); } // Check if the value is a valid for the given type. If not, skip. if (!(0, search_attributes_1.isValidValueForType)(type, value)) { return undefined; } return new search_attributes_1.TypedSearchAttributeValue(type, value); } } exports.TypedSearchAttributePayloadConverter = TypedSearchAttributePayloadConverter; exports.typedSearchAttributePayloadConverter = new TypedSearchAttributePayloadConverter(); // If both params are provided, conflicting keys will be overwritten by typedSearchAttributes. function encodeUnifiedSearchAttributes(searchAttributes, // eslint-disable-line @typescript-eslint/no-deprecated typedSearchAttributes) { return { ...(searchAttributes ? (0, payload_converter_1.mapToPayloads)(exports.searchAttributePayloadConverter, searchAttributes) : {}), ...(typedSearchAttributes ? (0, payload_converter_1.mapToPayloads)(exports.typedSearchAttributePayloadConverter, Object.fromEntries((Array.isArray(typedSearchAttributes) ? typedSearchAttributes : typedSearchAttributes.getAll()).map((pair) => { return [pair.key.name, new search_attributes_1.TypedSearchAttributeUpdateValue(pair.key.type, pair.value)]; }))) : {}), }; } // eslint-disable-next-line @typescript-eslint/no-deprecated function decodeSearchAttributes(indexedFields) { if (!indexedFields) return {}; return Object.fromEntries( // eslint-disable-next-line @typescript-eslint/no-deprecated Object.entries((0, payload_converter_1.mapFromPayloads)(exports.searchAttributePayloadConverter, indexedFields)).filter(([_, v]) => v && v.length > 0) // Filter out empty arrays returned by pre 1.18 servers ); } function decodeTypedSearchAttributes(indexedFields) { return new search_attributes_1.TypedSearchAttributes(Object.entries((0, payload_converter_1.mapFromPayloads)(exports.typedSearchAttributePayloadConverter, indexedFields) ?? {}).reduce((acc, [k, attr]) => { // Filter out undefined values from converter. if (!attr) { return acc; } const key = { name: k, type: attr.type }; // Ensure is valid pair. if ((0, search_attributes_1.isValidValueForType)(key.type, attr.value)) { acc.push({ key, value: attr.value }); } return acc; }, [])); } //# sourceMappingURL=payload-search-attributes.js.map