"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__tsfTypeAliases = void 0;
exports.getSharedMySQLSessionManagerConfig = getSharedMySQLSessionManagerConfig;
exports.ensureSharedMySQLSessionDatabase = ensureSharedMySQLSessionDatabase;
exports.releaseSharedMySQLSessionDatabase = releaseSharedMySQLSessionDatabase;
exports.prepareSharedMySQLSessionSchema = prepareSharedMySQLSessionSchema;
exports.completeSharedMySQLSessionSchema = completeSharedMySQLSessionSchema;
exports.createSharedMySQLSessionPool = createSharedMySQLSessionPool;
const tslib_1 = require("tslib");
const _a = tslib_1.__importStar(require("@zyno-io/ts-reflection/type-metadata-runtime"));
const node_crypto_1 = require("node:crypto");
const env_1 = require("../../env");
const mysql_session_rpc_1 = require("./mysql-session-rpc");
const __tsf_metadata_type = _a.createCompactMetadataRegistryV1("[1,[{\"kind\":22,\"type\":{\"kind\":18,\"typeName\":\"MySQLConnectionLike\",\"types\":[]}},{\"kind\":22,\"type\":{\"kind\":3}},{\"kind\":6},{\"kind\":18,\"typeName\":\"Record\",\"utilityType\":\"Record\",\"typeArguments\":[{\"kind\":6},{\"kind\":2}],\"index\":{\"kind\":2},\"types\":[]},{\"kind\":22,\"type\":{\"kind\":2,\"typeName\":\"T\"}},{\"kind\":18,\"typeName\":\"SharedMySQLSessionManagerConfig\",\"types\":[{\"kind\":20,\"name\":\"port\",\"type\":{\"kind\":7},\"optional\":false},{\"kind\":20,\"name\":\"token\",\"type\":{\"kind\":6},\"optional\":false}]},{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},{\"kind\":14,\"type\":{\"kind\":2}},{\"kind\":22,\"type\":{\"kind\":15,\"types\":[{\"type\":{\"kind\":2,\"typeName\":\"T\"}},{\"type\":{\"kind\":2}}]}}]]", []);
function getSharedMySQLSessionManagerConfig() {
    const port = env_1.Env.TSF_TEST_MYSQL_SESSION_MANAGER_PORT ? Number(env_1.Env.TSF_TEST_MYSQL_SESSION_MANAGER_PORT) : undefined;
    const token = env_1.Env.TSF_TEST_MYSQL_SESSION_MANAGER_TOKEN;
    if (!port || !token)
        return undefined;
    return { port, token };
}
async function ensureSharedMySQLSessionDatabase(options) {
    return withManagerPeer(peer => callManager(peer, 'ensureDatabase', {
        key: options.key,
        prefix: options.prefix,
        keepDatabase: options.keepDatabase
    }));
}
async function releaseSharedMySQLSessionDatabase(key, leaseId) {
    await withManagerPeer(peer => callManager(peer, 'releaseDatabase', { key, leaseId }));
}
async function prepareSharedMySQLSessionSchema(key, leaseId) {
    return withManagerPeer(peer => callManager(peer, 'prepareSchema', { key, leaseId }));
}
async function completeSharedMySQLSessionSchema(key, leaseId, preparationId, error) {
    await withManagerPeer(peer => callManager(peer, 'completeSchema', {
        key,
        leaseId,
        preparationId,
        ok: error === undefined,
        error: error instanceof Error ? error.message : error === undefined ? undefined : String(error)
    }));
}
function createSharedMySQLSessionPool(key, clientId = `${process.pid}:${(0, node_crypto_1.randomUUID)()}`, leaseId = env_1.Env.TSF_TEST_MYSQL_SESSION_LEASE_ID) {
    const manager = getSharedMySQLSessionManagerConfig();
    if (!manager)
        throw new Error('Shared MySQL session manager is not configured');
    return new SharedMySQLSessionPool(manager, key, clientId, leaseId);
}
async function withManagerPeer(worker) {
    const manager = getSharedMySQLSessionManagerConfig();
    if (!manager)
        throw new Error('Shared MySQL session manager is not configured');
    const peer = await (0, mysql_session_rpc_1.connectRpc)(manager.port);
    try {
        return await worker(peer);
    }
    finally {
        peer.close();
    }
}
function callManager(peer, method, params = {}) {
    const manager = getSharedMySQLSessionManagerConfig();
    if (!manager)
        throw new Error('Shared MySQL session manager is not configured');
    return peer.call(method, { ...params, token: manager.token });
}
let _SharedMySQLSessionPoolMetadata_1;
class SharedMySQLSessionPool {
    manager;
    key;
    clientId;
    leaseId;
    constructor(manager, key, clientId, leaseId) {
        this.manager = manager;
        this.key = key;
        this.clientId = clientId;
        this.leaseId = leaseId;
    }
    async getConnection() {
        const peer = await (0, mysql_session_rpc_1.connectRpc)(this.manager.port);
        await this.call(peer, 'acquire', { key: this.key, leaseId: this.leaseId, clientId: this.clientId });
        return new SharedMySQLSessionConnection(peer, this);
    }
    async end() { }
    call(peer, method, params = {}) {
        return peer.call(method, { ...params, token: this.manager.token });
    }
    static __tsfType = _SharedMySQLSessionPoolMetadata_1 = _a.decodeCompactMetadataV1("[1,{\"kind\":16,\"name\":\"SharedMySQLSessionPool\",\"typeName\":\"SharedMySQLSessionPool\",\"classType\":{\"$tsf\":0},\"properties\":[],\"methods\":[{\"name\":\"getConnection\",\"parameters\":[],\"returnType\":{\"$tsfType\":0}},{\"name\":\"end\",\"parameters\":[],\"returnType\":{\"$tsfType\":1}},{\"name\":\"call\",\"parameters\":[{\"name\":\"peer\",\"type\":{\"kind\":16,\"typeName\":\"RpcPeer\",\"classType\":{\"$tsfImport\":[1,\"./mysql-session-rpc\",\"RpcPeer\"]}},\"optional\":false,\"default\":false},{\"name\":\"method\",\"type\":{\"$tsfType\":2},\"optional\":false,\"default\":false},{\"name\":\"params\",\"type\":{\"$tsfType\":3},\"optional\":true,\"default\":true}],\"returnType\":{\"$tsfType\":4}}],\"hasConstructor\":true,\"constructorParameters\":[{\"name\":\"manager\",\"type\":{\"$tsfType\":5},\"optional\":false,\"default\":false},{\"name\":\"key\",\"type\":{\"$tsfType\":2},\"optional\":false,\"default\":false},{\"name\":\"clientId\",\"type\":{\"$tsfType\":2},\"optional\":false,\"default\":false},{\"name\":\"leaseId\",\"type\":{\"$tsfType\":6},\"optional\":false,\"default\":false}]}]", [() => SharedMySQLSessionPool, require], __tsf_metadata_type);
}
_SharedMySQLSessionPoolMetadata_1.classType = SharedMySQLSessionPool;
SharedMySQLSessionPool.__tsfType = _SharedMySQLSessionPoolMetadata_1;
let _SharedMySQLSessionConnectionMetadata_1;
class SharedMySQLSessionConnection {
    peer;
    pool;
    released = false;
    constructor(peer, pool) {
        this.peer = peer;
        this.pool = pool;
    }
    async query(sql, values = []) {
        const result = await this.pool.call(this.peer, 'query', { sql, values });
        return [result, undefined];
    }
    async execute(sql, values = []) {
        const result = await this.pool.call(this.peer, 'execute', { sql, values });
        return [result, undefined];
    }
    async release() {
        if (this.released)
            return;
        this.released = true;
        try {
            await this.pool.call(this.peer, 'release');
        }
        finally {
            this.peer.close();
        }
    }
    static __tsfType = _SharedMySQLSessionConnectionMetadata_1 = _a.decodeCompactMetadataV1("[1,{\"kind\":16,\"name\":\"SharedMySQLSessionConnection\",\"typeName\":\"SharedMySQLSessionConnection\",\"classType\":{\"$tsf\":0},\"properties\":[],\"methods\":[{\"name\":\"query\",\"parameters\":[{\"name\":\"sql\",\"type\":{\"$tsfType\":2},\"optional\":false,\"default\":false},{\"name\":\"values\",\"type\":{\"$tsfType\":7},\"optional\":true,\"default\":true}],\"returnType\":{\"$tsfType\":8}},{\"name\":\"execute\",\"parameters\":[{\"name\":\"sql\",\"type\":{\"$tsfType\":2},\"optional\":false,\"default\":false},{\"name\":\"values\",\"type\":{\"$tsfType\":7},\"optional\":true,\"default\":true}],\"returnType\":{\"$tsfType\":8}},{\"name\":\"release\",\"parameters\":[],\"returnType\":{\"$tsfType\":1}}],\"hasConstructor\":true,\"constructorParameters\":[{\"name\":\"peer\",\"type\":{\"kind\":16,\"typeName\":\"RpcPeer\",\"classType\":{\"$tsfImport\":[1,\"./mysql-session-rpc\",\"RpcPeer\"]}},\"optional\":false,\"default\":false},{\"name\":\"pool\",\"type\":{\"kind\":16,\"typeName\":\"SharedMySQLSessionPool\",\"classType\":{\"$tsf\":2}},\"optional\":false,\"default\":false}]}]", [() => SharedMySQLSessionConnection, require, () => (typeof SharedMySQLSessionPool !== "undefined" ? SharedMySQLSessionPool : (typeof exports !== "undefined" ? exports.SharedMySQLSessionPool : undefined))], __tsf_metadata_type);
}
_SharedMySQLSessionConnectionMetadata_1.classType = SharedMySQLSessionConnection;
SharedMySQLSessionConnection.__tsfType = _SharedMySQLSessionConnectionMetadata_1;
exports.__tsfTypeAliases = JSON.parse("[1,{\"SharedMySQLSessionDatabase\":{\"kind\":18,\"typeName\":\"SharedMySQLSessionDatabase\",\"types\":[{\"kind\":20,\"name\":\"databaseName\",\"type\":{\"kind\":6},\"optional\":false},{\"kind\":20,\"name\":\"leaseId\",\"type\":{\"kind\":6},\"optional\":false}]},\"SharedMySQLSessionDatabaseOptions\":{\"kind\":18,\"typeName\":\"SharedMySQLSessionDatabaseOptions\",\"types\":[{\"kind\":20,\"name\":\"key\",\"type\":{\"kind\":6},\"optional\":false},{\"kind\":20,\"name\":\"prefix\",\"type\":{\"kind\":6},\"optional\":false},{\"kind\":20,\"name\":\"keepDatabase\",\"type\":{\"kind\":8},\"optional\":false}]},\"SharedMySQLSessionManagerConfig\":{\"kind\":18,\"typeName\":\"SharedMySQLSessionManagerConfig\",\"types\":[{\"kind\":20,\"name\":\"port\",\"type\":{\"kind\":7},\"optional\":false},{\"kind\":20,\"name\":\"token\",\"type\":{\"kind\":6},\"optional\":false}]},\"SharedMySQLSessionSchemaPreparation\":{\"kind\":18,\"typeName\":\"SharedMySQLSessionSchemaPreparation\",\"types\":[{\"kind\":20,\"name\":\"run\",\"type\":{\"kind\":8},\"optional\":false},{\"kind\":20,\"name\":\"preparationId\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true}]}}]")[1];
//# sourceMappingURL=mysql-session.js.map