@keyv/postgres
Version:
PostgreSQL storage adapter for Keyv
205 lines (201 loc) • 7.09 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
KeyvPostgres: () => KeyvPostgres,
createKeyv: () => createKeyv,
default: () => index_default
});
module.exports = __toCommonJS(index_exports);
var import_node_events = __toESM(require("events"), 1);
var import_keyv = __toESM(require("keyv"), 1);
// src/pool.ts
var import_pg = __toESM(require("pg"), 1);
var postgresPool;
var globalUri;
var pool = (uri, options = {}) => {
if (globalUri !== uri) {
postgresPool = void 0;
globalUri = uri;
}
postgresPool ??= new import_pg.default.Pool({ connectionString: uri, ...options });
return postgresPool;
};
var endPool = async () => {
await postgresPool?.end();
globalUri = void 0;
};
// src/index.ts
var KeyvPostgres = class extends import_node_events.default {
ttlSupport;
opts;
query;
namespace;
constructor(options) {
super();
this.ttlSupport = false;
if (typeof options === "string") {
const uri = options;
options = {
dialect: "postgres",
uri
};
} else {
options = {
dialect: "postgres",
uri: "postgresql://localhost:5432",
...options
};
}
this.opts = {
table: "keyv",
schema: "public",
keySize: 255,
...options
};
let createTable = `CREATE${this.opts.useUnloggedTable ? " UNLOGGED " : " "}TABLE IF NOT EXISTS ${this.opts.schema}.${this.opts.table}(key VARCHAR(${Number(this.opts.keySize)}) PRIMARY KEY, value TEXT )`;
if (this.opts.schema !== "public") {
createTable = `CREATE SCHEMA IF NOT EXISTS ${this.opts.schema}; ${createTable}`;
}
const connected = this.connect().then(async (query) => {
try {
await query(createTable);
} catch (error) {
if (error.code !== "23505") {
this.emit("error", error);
}
return query;
}
return query;
}).catch((error) => this.emit("error", error));
this.query = async (sqlString, values) => connected.then((query) => query(sqlString, values));
}
async get(key) {
const select = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1`;
const rows = await this.query(select, [key]);
const row = rows[0];
return row === void 0 ? void 0 : row.value;
}
async getMany(keys) {
const getMany = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = ANY($1)`;
const rows = await this.query(getMany, [keys]);
const rowsMap = new Map(rows.map((row) => [row.key, row]));
return keys.map((key) => rowsMap.get(key)?.value);
}
// biome-ignore lint/suspicious/noExplicitAny: type format
async set(key, value) {
const upsert = `INSERT INTO ${this.opts.schema}.${this.opts.table} (key, value)
VALUES($1, $2)
ON CONFLICT(key)
DO UPDATE SET value=excluded.value;`;
await this.query(upsert, [key, value]);
}
async setMany(entries) {
const keys = [];
const values = [];
for (const { key, value } of entries) {
keys.push(key);
values.push(value);
}
const upsert = `INSERT INTO ${this.opts.schema}.${this.opts.table} (key, value)
SELECT * FROM UNNEST($1::text[], $2::text[])
ON CONFLICT(key)
DO UPDATE SET value=excluded.value;`;
await this.query(upsert, [keys, values]);
}
async delete(key) {
const select = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1`;
const del = `DELETE FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1`;
const rows = await this.query(select, [key]);
if (rows[0] === void 0) {
return false;
}
await this.query(del, [key]);
return true;
}
async deleteMany(keys) {
const select = `SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = ANY($1)`;
const del = `DELETE FROM ${this.opts.schema}.${this.opts.table} WHERE key = ANY($1)`;
const rows = await this.query(select, [keys]);
if (rows[0] === void 0) {
return false;
}
await this.query(del, [keys]);
return true;
}
async clear() {
const del = `DELETE FROM ${this.opts.schema}.${this.opts.table} WHERE key LIKE $1`;
await this.query(del, [this.namespace ? `${this.namespace}:%` : "%"]);
}
async *iterator(namespace) {
const limit = Number.parseInt(String(this.opts.iterationLimit), 10) || 10;
async function* iterate(offset, options, query) {
const select = `SELECT * FROM ${options.schema}.${options.table} WHERE key LIKE $1 LIMIT $2 OFFSET $3`;
const entries = await query(select, [
// biome-ignore lint/style/useTemplate: need to fix
`${namespace ? namespace + ":" : ""}%`,
limit,
offset
]);
if (entries.length === 0) {
return;
}
for (const entry of entries) {
offset += 1;
yield [entry.key, entry.value];
}
yield* iterate(offset, options, query);
}
yield* iterate(0, this.opts, this.query);
}
async has(key) {
const exists = `SELECT EXISTS ( SELECT * FROM ${this.opts.schema}.${this.opts.table} WHERE key = $1 )`;
const rows = await this.query(exists, [key]);
return rows[0].exists;
}
async connect() {
const conn = pool(this.opts.uri, this.opts);
return async (sql, values) => {
const data = await conn.query(sql, values);
return data.rows;
};
}
async disconnect() {
await endPool();
}
};
var createKeyv = (options) => new import_keyv.default({ store: new KeyvPostgres(options) });
var index_default = KeyvPostgres;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
KeyvPostgres,
createKeyv
});
/* v8 ignore next -- @preserve */