"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const datasource_1 = require("../definitions/datasource");
const ioredis_1 = __importDefault(require("ioredis"));
var RedisModule;
(function (RedisModule) {
    const SCHEMA = {
        docs: "https://redis.io/docs/",
        description: "",
        friendlyName: "Redis",
        type: "Non-relational",
        datasource: {
            host: {
                type: "string",
                required: true,
                default: "localhost",
            },
            port: {
                type: "number",
                required: true,
                default: 6379,
            },
            username: {
                type: "string",
                required: false,
            },
            password: {
                type: "password",
                required: false,
            },
        },
        query: {
            create: {
                type: datasource_1.QueryTypes.FIELDS,
                fields: {
                    key: {
                        type: datasource_1.DatasourceFieldTypes.STRING,
                        required: true,
                    },
                    value: {
                        type: datasource_1.DatasourceFieldTypes.STRING,
                        required: true,
                    },
                    ttl: {
                        type: datasource_1.DatasourceFieldTypes.NUMBER,
                    },
                },
            },
            read: {
                readable: true,
                type: datasource_1.QueryTypes.FIELDS,
                fields: {
                    key: {
                        type: datasource_1.DatasourceFieldTypes.STRING,
                        required: true,
                    },
                },
            },
            delete: {
                type: datasource_1.QueryTypes.FIELDS,
                fields: {
                    key: {
                        type: datasource_1.DatasourceFieldTypes.STRING,
                        required: true,
                    },
                },
            },
            command: {
                readable: true,
                displayName: "Redis Command",
                type: datasource_1.QueryTypes.JSON,
            },
        },
    };
    class RedisIntegration {
        constructor(config) {
            this.config = config;
            this.client = new ioredis_1.default({
                host: this.config.host,
                port: this.config.port,
                username: this.config.username,
                password: this.config.password,
            });
        }
        disconnect() {
            return __awaiter(this, void 0, void 0, function* () {
                this.client.disconnect();
            });
        }
        redisContext(query) {
            return __awaiter(this, void 0, void 0, function* () {
                try {
                    return yield query();
                }
                catch (err) {
                    throw new Error(`Redis error: ${err}`);
                }
                finally {
                    this.disconnect();
                }
            });
        }
        create(query) {
            return __awaiter(this, void 0, void 0, function* () {
                return this.redisContext(() => __awaiter(this, void 0, void 0, function* () {
                    const response = yield this.client.set(query.key, query.value);
                    if (query.ttl) {
                        yield this.client.expire(query.key, query.ttl);
                    }
                    return response;
                }));
            });
        }
        read(query) {
            return __awaiter(this, void 0, void 0, function* () {
                return this.redisContext(() => __awaiter(this, void 0, void 0, function* () {
                    const response = yield this.client.get(query.key);
                    return response;
                }));
            });
        }
        delete(query) {
            return __awaiter(this, void 0, void 0, function* () {
                return this.redisContext(() => __awaiter(this, void 0, void 0, function* () {
                    const response = yield this.client.del(query.key);
                    return response;
                }));
            });
        }
        command(query) {
            return __awaiter(this, void 0, void 0, function* () {
                return this.redisContext(() => __awaiter(this, void 0, void 0, function* () {
                    const commands = query.json.trim().split(" ");
                    const pipeline = this.client.pipeline([commands]);
                    const result = yield pipeline.exec();
                    return {
                        response: result[0][1],
                    };
                }));
            });
        }
    }
    module.exports = {
        schema: SCHEMA,
        integration: RedisIntegration,
    };
})(RedisModule || (RedisModule = {}));
