@worker-tools/deno-kv-storage
Version:
An implementation of the StorageArea (1,2,3) interface for Deno with an extensible system for supporting various database backends.
123 lines • 4.05 kB
JavaScript
// deno-lint-ignore-file no-explicit-any
import "../_dnt.polyfills.js";
import { Client } from "../deps/deno.land/x/postgres@v0.15.0/mod.js";
const CREATE = 'CREATE TABLE IF NOT EXISTS kv_storage (area TEXT, key TEXT, value TEXT, PRIMARY KEY (area, key))';
const GET = 'SELECT value FROM kv_storage WHERE key=$2 AND area=$1';
const UPSERT = 'INSERT INTO kv_storage (area, key, value) VALUES ($1, $2, $3) ON CONFLICT(area, key) DO UPDATE SET value=$3';
const DELETE = 'DELETE FROM kv_storage WHERE key=$2 AND area=$1';
const CLEAR = 'DELETE FROM kv_storage WHERE area=$1';
const KEYS = 'SELECT key FROM kv_storage WHERE area=$1';
const VALUES = 'SELECT value FROM kv_storage WHERE area=$1';
const ENTRIES = 'SELECT key, value FROM kv_storage WHERE area=$1';
export class PostgresAdapter {
constructor({ area, url }) {
Object.defineProperty(this, "area", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "url", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "init", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "client", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.area = area;
this.url = url;
this.init = (async () => {
const client = this.client = new Client(url);
await client.connect();
// https://stackoverflow.com/questions/26150758/suppressing-notice-relation-exists-when-using-create-if-not-exists
await client.queryArray(`SET client_min_messages = warning`);
await client.queryArray(CREATE);
this.keepOpen();
})();
}
keepOpen() {
queueMicrotask(() => {
var _a;
if ((_a = this.client) === null || _a === void 0 ? void 0 : _a.connected)
this.client.end();
delete this.client;
});
}
async query(query, { key, value } = {}) {
await this.init;
const client = this.client || (this.client = new Client(this.url));
if (!client.connected)
await client.connect();
const ret = (await client.queryArray({
text: query,
args: [this.area, ...key ? [key] : [], ...value ? [value] : []],
})).rows;
this.keepOpen();
return ret;
}
async get(key) {
var _a;
const res = (_a = (await this.query(GET, { key }))[0]) === null || _a === void 0 ? void 0 : _a[0];
this.keepOpen();
return res;
}
async set(key, value) {
await this.query(UPSERT, { key, value });
this.keepOpen();
}
async delete(key) {
await this.query(DELETE, { key });
this.keepOpen();
}
async clear() {
await this.query(CLEAR);
this.keepOpen();
}
async *keys() {
try {
for (const [key] of await this.query(KEYS)) {
yield key;
}
}
finally {
this.keepOpen();
}
}
async *values() {
try {
for (const [value] of await this.query(VALUES)) {
yield value;
}
}
finally {
this.keepOpen();
}
}
async *entries() {
try {
for (const [key, value] of await this.query(ENTRIES)) {
yield [key, value];
}
}
finally {
this.keepOpen();
}
}
backingStore() {
return new Client(this.url);
}
}
// @ts-ignore: ...
(globalThis.deno_storage_area__adapters || (globalThis.deno_storage_area__adapters = new Map())).set('postgres:', PostgresAdapter);
//# sourceMappingURL=postgres.js.map