"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.executionInfoFromRaw = executionInfoFromRaw;
exports.decodeCountWorkflowExecutionsResponse = decodeCountWorkflowExecutionsResponse;
exports.rethrowKnownErrorTypes = rethrowKnownErrorTypes;
const grpc_js_1 = require("@grpc/grpc-js");
const common_1 = require("@temporalio/common");
const payload_search_attributes_1 = require("@temporalio/common/lib/converter/payload-search-attributes");
const time_1 = require("@temporalio/common/lib/time");
const codec_helpers_1 = require("@temporalio/common/lib/internal-non-workflow/codec-helpers");
const proto_1 = require("@temporalio/proto");
function workflowStatusCodeToName(code) {
    return workflowStatusCodeToNameInternal(code) ?? 'UNKNOWN';
}
/**
 * Intentionally leave out `default` branch to get compilation errors when new values are added
 */
function workflowStatusCodeToNameInternal(code) {
    switch (code) {
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED:
            return 'UNSPECIFIED';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_RUNNING:
            return 'RUNNING';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED:
            return 'FAILED';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TIMED_OUT:
            return 'TIMED_OUT';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CANCELED:
            return 'CANCELLED';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TERMINATED:
            return 'TERMINATED';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED:
            return 'COMPLETED';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
            return 'CONTINUED_AS_NEW';
        case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_PAUSED:
            return 'PAUSED';
    }
}
async function executionInfoFromRaw(raw, dataConverter, rawDataToEmbed) {
    return {
        type: raw.type.name,
        workflowId: raw.execution.workflowId,
        runId: raw.execution.runId,
        taskQueue: raw.taskQueue,
        status: {
            code: raw.status,
            name: workflowStatusCodeToName(raw.status),
        },
        // Safe to convert to number, max history length is 50k, which is much less than Number.MAX_SAFE_INTEGER
        historyLength: raw.historyLength.toNumber(),
        // Exact truncation for multi-petabyte histories
        // historySize === 0 means WFT was generated by pre-1.20.0 server, and the history size is unknown
        historySize: raw.historySizeBytes?.toNumber() || undefined,
        startTime: (0, time_1.requiredTsToDate)(raw.startTime, 'startTime'),
        executionTime: (0, time_1.optionalTsToDate)(raw.executionTime),
        closeTime: (0, time_1.optionalTsToDate)(raw.closeTime),
        memo: await (0, codec_helpers_1.decodeMapFromPayloads)(dataConverter, raw.memo?.fields),
        searchAttributes: (0, payload_search_attributes_1.decodeSearchAttributes)(raw.searchAttributes?.indexedFields),
        typedSearchAttributes: (0, payload_search_attributes_1.decodeTypedSearchAttributes)(raw.searchAttributes?.indexedFields),
        parentExecution: raw.parentExecution
            ? {
                workflowId: raw.parentExecution.workflowId,
                runId: raw.parentExecution.runId,
            }
            : undefined,
        rootExecution: raw.rootExecution
            ? {
                workflowId: raw.rootExecution.workflowId,
                runId: raw.rootExecution.runId,
            }
            : undefined,
        raw: rawDataToEmbed,
        priority: (0, common_1.decodePriority)(raw.priority),
    };
}
function decodeCountWorkflowExecutionsResponse(raw) {
    return {
        // Note: lossy conversion of Long to number
        count: raw.count.toNumber(),
        groups: raw.groups.map((group) => {
            return {
                // Note: lossy conversion of Long to number
                count: group.count.toNumber(),
                groupValues: group.groupValues.map((value) => payload_search_attributes_1.searchAttributePayloadConverter.fromPayload(value)),
            };
        }),
    };
}
/**
 * If the error type can be determined based on embedded grpc error details,
 * then rethrow the appropriate TypeScript error. Otherwise do nothing.
 *
 * This function should be used before falling back to generic error handling
 * based on grpc error code. Very few error types are currently supported, but
 * this function will be expanded over time as more server error types are added.
 */
function rethrowKnownErrorTypes(err) {
    // We really don't expect multiple error details, but this really is an array, so just in case...
    for (const entry of getGrpcStatusDetails(err) ?? []) {
        if (!entry.type_url || !entry.value)
            continue;
        const type = entry.type_url.replace(/^type.googleapis.com\//, '');
        switch (type) {
            case 'temporal.api.errordetails.v1.NamespaceNotFoundFailure': {
                const { namespace } = proto_1.temporal.api.errordetails.v1.NamespaceNotFoundFailure.decode(entry.value);
                throw new common_1.NamespaceNotFoundError(namespace);
            }
            case 'temporal.api.errordetails.v1.MultiOperationExecutionFailure': {
                // MultiOperationExecutionFailure contains error statuses for multiple
                // operations. A MultiOperationExecutionAborted error status means that
                // the corresponding operation was aborted due to an error in one of the
                // other operations. We rethrow the first operation error that is not
                // MultiOperationExecutionAborted.
                const { statuses } = proto_1.temporal.api.errordetails.v1.MultiOperationExecutionFailure.decode(entry.value);
                for (const status of statuses) {
                    const detail = status.details?.[0];
                    const statusType = detail?.type_url?.replace(/^type.googleapis.com\//, '');
                    if (statusType === 'temporal.api.failure.v1.MultiOperationExecutionAborted' ||
                        status.code === grpc_js_1.status.OK) {
                        continue;
                    }
                    err.message = status.message ?? err.message;
                    err.code = status.code || err.code;
                    err.details = detail?.value?.toString() || err.details;
                    throw err;
                }
            }
        }
    }
}
function getGrpcStatusDetails(err) {
    const statusBuffer = err.metadata.get('grpc-status-details-bin')?.[0];
    if (!statusBuffer || typeof statusBuffer === 'string') {
        return undefined;
    }
    return proto_1.google.rpc.Status.decode(statusBuffer).details;
}
//# sourceMappingURL=helpers.js.map