UNPKG

@temporalio/common

Version:

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

242 lines 9.58 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypedSearchAttributes = exports.TypedSearchAttributeUpdateValue = exports.TypedSearchAttributeValue = exports._ = exports.encodeSearchAttributeIndexedValueType = exports.SearchAttributeType = void 0; exports.isValidValueForType = isValidValueForType; exports.defineSearchAttributeKey = defineSearchAttributeKey; const internal_workflow_1 = require("./internal-workflow"); exports.SearchAttributeType = { TEXT: 'TEXT', KEYWORD: 'KEYWORD', INT: 'INT', DOUBLE: 'DOUBLE', BOOL: 'BOOL', DATETIME: 'DATETIME', KEYWORD_LIST: 'KEYWORD_LIST', }; // Note: encodeSearchAttributeIndexedValueType exported for use in tests to register search attributes // ts-prune-ignore-next _a = (0, internal_workflow_1.makeProtoEnumConverters)({ [exports.SearchAttributeType.TEXT]: 1, [exports.SearchAttributeType.KEYWORD]: 2, [exports.SearchAttributeType.INT]: 3, [exports.SearchAttributeType.DOUBLE]: 4, [exports.SearchAttributeType.BOOL]: 5, [exports.SearchAttributeType.DATETIME]: 6, [exports.SearchAttributeType.KEYWORD_LIST]: 7, UNSPECIFIED: 0, }, 'INDEXED_VALUE_TYPE_'), exports.encodeSearchAttributeIndexedValueType = _a[0], exports._ = _a[1]; function isValidValueForType(type, value) { switch (type) { case exports.SearchAttributeType.TEXT: case exports.SearchAttributeType.KEYWORD: return typeof value === 'string'; case exports.SearchAttributeType.INT: return Number.isInteger(value); case exports.SearchAttributeType.DOUBLE: return typeof value === 'number'; case exports.SearchAttributeType.BOOL: return typeof value === 'boolean'; case exports.SearchAttributeType.DATETIME: return value instanceof Date; case exports.SearchAttributeType.KEYWORD_LIST: return Array.isArray(value) && value.every((item) => typeof item === 'string'); default: return false; } } function defineSearchAttributeKey(name, type) { return { name, type }; } class BaseSearchAttributeValue { _type; _value; constructor(type, value) { this._type = type; this._value = value; } get type() { return this._type; } get value() { return this._value; } } // Internal type for class private data. // Exported for use in payload conversion. class TypedSearchAttributeValue extends BaseSearchAttributeValue { } exports.TypedSearchAttributeValue = TypedSearchAttributeValue; // ts-prune-ignore-next class TypedSearchAttributeUpdateValue extends BaseSearchAttributeValue { } exports.TypedSearchAttributeUpdateValue = TypedSearchAttributeUpdateValue; class TypedSearchAttributes { searchAttributes = {}; constructor(initialAttributes) { if (initialAttributes === undefined) return; for (const pair of initialAttributes) { if (pair.key.name in this.searchAttributes) { throw new Error(`Duplicate search attribute key: ${pair.key.name}`); } this.searchAttributes[pair.key.name] = new TypedSearchAttributeValue(pair.key.type, pair.value); } } get(key) { const attr = this.searchAttributes[key.name]; // Key not found or type mismatch. if (attr === undefined || !isValidValueForType(key.type, attr.value)) { return undefined; } return attr.value; } /** Returns a deep copy of the given TypedSearchAttributes instance */ copy() { const state = {}; for (const [key, attr] of Object.entries(this.searchAttributes)) { // Create a new instance with the same properties let value = attr.value; // For non-primitive types, create a deep copy if (attr.value instanceof Date) { value = new Date(attr.value); } else if (Array.isArray(attr.value)) { value = [...attr.value]; } state[key] = new TypedSearchAttributeValue(attr.type, value); } // Create return value with manually assigned state. const res = new TypedSearchAttributes(); res.searchAttributes = state; return res; } /** * @hidden * Return JSON representation of this class as SearchAttributePair[] * Default toJSON method is not used because it's JSON representation includes private state. */ toJSON() { return this.getAll(); } /** Returns a copy of the current TypedSearchAttributes instance with the updated attributes. */ updateCopy(updates) { // Create a deep copy of the current instance. const res = this.copy(); // Apply updates. res.update(updates); return res; } // Performs direct mutation on the current instance. update(updates) { // Apply updates. for (const pair of updates) { // Delete attribute. if (pair.value === null) { // Delete only if the update matches a key and type. const attrVal = this.searchAttributes[pair.key.name]; if (attrVal && attrVal.type === pair.key.type) { delete this.searchAttributes[pair.key.name]; } continue; } // Add or update attribute. this.searchAttributes[pair.key.name] = new TypedSearchAttributeValue(pair.key.type, pair.value); } } getAll() { const res = []; for (const [key, attr] of Object.entries(this.searchAttributes)) { const attrKey = { name: key, type: attr.type }; // Sanity check, should always be legal. if (isValidValueForType(attrKey.type, attr.value)) { res.push({ key: attrKey, value: attr.value }); } } return res; } static getKeyFromUntyped(key, value // eslint-disable-line @typescript-eslint/no-deprecated ) { if (value == null) { return; } // Unpack single-element arrays. const val = value.length === 1 ? value[0] : value; switch (typeof val) { case 'string': // Check if val is an ISO string, if so, return a DATETIME key. if (!isNaN(Date.parse(val)) && Date.parse(val) === new Date(val).getTime()) { return { name: key, type: exports.SearchAttributeType.DATETIME }; } return { name: key, type: exports.SearchAttributeType.TEXT }; case 'number': return { name: key, type: Number.isInteger(val) ? exports.SearchAttributeType.INT : exports.SearchAttributeType.DOUBLE, }; case 'boolean': return { name: key, type: exports.SearchAttributeType.BOOL }; case 'object': if (val instanceof Date) { return { name: key, type: exports.SearchAttributeType.DATETIME }; } if (Array.isArray(val) && val.every((item) => typeof item === 'string')) { return { name: key, type: exports.SearchAttributeType.KEYWORD_LIST }; } return; default: return; } } static toMetadataType(type) { switch (type) { case exports.SearchAttributeType.TEXT: return 'Text'; case exports.SearchAttributeType.KEYWORD: return 'Keyword'; case exports.SearchAttributeType.INT: return 'Int'; case exports.SearchAttributeType.DOUBLE: return 'Double'; case exports.SearchAttributeType.BOOL: return 'Bool'; case exports.SearchAttributeType.DATETIME: return 'Datetime'; case exports.SearchAttributeType.KEYWORD_LIST: return 'KeywordList'; default: throw new Error(`Unknown search attribute type: ${type}`); } } static toSearchAttributeType(type) { // The type metadata is usually in PascalCase (e.g. "KeywordList") but in // rare cases may be in SCREAMING_SNAKE_CASE (e.g. "INDEXED_VALUE_TYPE_KEYWORD_LIST"). switch (type) { case 'Text': case 'INDEXED_VALUE_TYPE_TEXT': return exports.SearchAttributeType.TEXT; case 'Keyword': case 'INDEXED_VALUE_TYPE_KEYWORD': return exports.SearchAttributeType.KEYWORD; case 'Int': case 'INDEXED_VALUE_TYPE_INT': return exports.SearchAttributeType.INT; case 'Double': case 'INDEXED_VALUE_TYPE_DOUBLE': return exports.SearchAttributeType.DOUBLE; case 'Bool': case 'INDEXED_VALUE_TYPE_BOOL': return exports.SearchAttributeType.BOOL; case 'Datetime': case 'INDEXED_VALUE_TYPE_DATETIME': return exports.SearchAttributeType.DATETIME; case 'KeywordList': case 'INDEXED_VALUE_TYPE_KEYWORD_LIST': return exports.SearchAttributeType.KEYWORD_LIST; default: return; } } } exports.TypedSearchAttributes = TypedSearchAttributes; //# sourceMappingURL=search-attributes.js.map