"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WRITES_IDX_MAP = exports.BaseCheckpointSaver = void 0;
exports.deepCopy = deepCopy;
exports.emptyCheckpoint = emptyCheckpoint;
exports.copyCheckpoint = copyCheckpoint;
exports.compareChannelVersions = compareChannelVersions;
exports.maxChannelVersion = maxChannelVersion;
exports.getCheckpointId = getCheckpointId;
const id_js_1 = require("./id.cjs");
const types_js_1 = require("./serde/types.cjs");
const jsonplus_js_1 = require("./serde/jsonplus.cjs");
function deepCopy(obj) {
    if (typeof obj !== "object" || obj === null) {
        return obj;
    }
    const newObj = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            newObj[key] = deepCopy(obj[key]);
        }
    }
    return newObj;
}
/** @hidden */
function emptyCheckpoint() {
    return {
        v: 1,
        id: (0, id_js_1.uuid6)(-2),
        ts: new Date().toISOString(),
        channel_values: {},
        channel_versions: {},
        versions_seen: {},
        pending_sends: [],
    };
}
/** @hidden */
function copyCheckpoint(checkpoint) {
    return {
        v: checkpoint.v,
        id: checkpoint.id,
        ts: checkpoint.ts,
        channel_values: { ...checkpoint.channel_values },
        channel_versions: { ...checkpoint.channel_versions },
        versions_seen: deepCopy(checkpoint.versions_seen),
        pending_sends: [...checkpoint.pending_sends],
    };
}
class BaseCheckpointSaver {
    constructor(serde) {
        Object.defineProperty(this, "serde", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: new jsonplus_js_1.JsonPlusSerializer()
        });
        this.serde = serde || this.serde;
    }
    async get(config) {
        const value = await this.getTuple(config);
        return value ? value.checkpoint : undefined;
    }
    /**
     * Generate the next version ID for a channel.
     *
     * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,
     * as long as they are monotonically increasing.
     */
    getNextVersion(current, _channel) {
        if (typeof current === "string") {
            throw new Error("Please override this method to use string versions.");
        }
        return (current !== undefined && typeof current === "number" ? current + 1 : 1);
    }
}
exports.BaseCheckpointSaver = BaseCheckpointSaver;
function compareChannelVersions(a, b) {
    if (typeof a === "number" && typeof b === "number") {
        return Math.sign(a - b);
    }
    return String(a).localeCompare(String(b));
}
function maxChannelVersion(...versions) {
    return versions.reduce((max, version, idx) => {
        if (idx === 0)
            return version;
        return compareChannelVersions(max, version) >= 0 ? max : version;
    });
}
/**
 * Mapping from error type to error index.
 * Regular writes just map to their index in the list of writes being saved.
 * Special writes (e.g. errors) map to negative indices, to avoid those writes from
 * conflicting with regular writes.
 * Each Checkpointer implementation should use this mapping in put_writes.
 */
exports.WRITES_IDX_MAP = {
    [types_js_1.ERROR]: -1,
    [types_js_1.SCHEDULED]: -2,
    [types_js_1.INTERRUPT]: -3,
    [types_js_1.RESUME]: -4,
};
function getCheckpointId(config) {
    return (config.configurable?.checkpoint_id || config.configurable?.thread_ts || "");
}
//# sourceMappingURL=base.js.map