diff --git a/src/Uwave.js b/src/Uwave.js index 4174806b..c898b8cb 100644 --- a/src/Uwave.js +++ b/src/Uwave.js @@ -20,7 +20,7 @@ import acl from './plugins/acl.js'; import waitlist from './plugins/waitlist.js'; import passport from './plugins/passport.js'; import migrations from './plugins/migrations.js'; -import { SqliteDateColumnsPlugin, connect as connectSqlite } from './utils/sqlite.js'; +import { SqliteDateColumnsPlugin, connect as connectSqlite, jsonb } from './utils/sqlite.js'; const DEFAULT_MONGO_URL = 'mongodb://localhost:27017/uwave'; const DEFAULT_REDIS_URL = 'redis://localhost:6379'; @@ -180,6 +180,37 @@ class UwaveServer extends EventEmitter { this.redis.quit(), ])); + class KeyValue { + #db; + + /** @param {Kysely} db */ + constructor(db) { + this.#db = db; + } + + /** @param {string} key */ + async get(key, db = this.#db) { + const row = await db.selectFrom('keyval') + .select('value') + .where('key', '=', key) + .executeTakeFirst(); + return row != null ? JSON.parse(/** @type {string} */ (/** @type {unknown} */ (row.value))) : null; + } + + /** + * @param {string} key + * @param {import('type-fest').JsonValue} value + */ + async set(key, value, db = this.#db) { + await db.insertInto('keyval') + .values({ key, value: jsonb(value) }) + .onConflict((oc) => oc.column('key').doUpdateSet({ value: jsonb(value) })) + .execute(); + } + } + + this.keyv = new KeyValue(this.db); + boot.use(migrations); boot.use(configStore); diff --git a/src/migrations/002-sql.cjs b/src/migrations/002-sql.cjs index 6c39bc5a..4517dbab 100644 --- a/src/migrations/002-sql.cjs +++ b/src/migrations/002-sql.cjs @@ -16,6 +16,11 @@ async function up({ context: uw }) { .addColumn('value', 'jsonb') .execute(); + await db.schema.createTable('keyval') + .addColumn('key', 'text', (col) => col.primaryKey()) + .addColumn('value', 'jsonb') + .execute(); + await db.schema.createTable('media') .addColumn('id', 'uuid', (col) => col.primaryKey()) .addColumn('source_type', 'text', (col) => col.notNull()) diff --git a/src/schema.ts b/src/schema.ts index 53d80423..ac2870e4 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1,5 +1,5 @@ import type { Kysely as KyselyBase, Generated } from 'kysely'; -import type { JsonObject, Tagged } from 'type-fest'; // eslint-disable-line n/no-missing-import, n/no-unpublished-import +import type { JsonObject, JsonValue, Tagged } from 'type-fest'; // eslint-disable-line n/no-missing-import, n/no-unpublished-import export type UserID = Tagged; export type MediaID = Tagged; @@ -134,12 +134,18 @@ export interface ConfigurationTable { value: JsonObject | null, } +export interface KeyvalTable { + key: string, + value: JsonValue, +} + export interface MigrationTable { name: string, } export interface Database { configuration: ConfigurationTable, + keyval: KeyvalTable, migrations: MigrationTable, media: MediaTable, users: UserTable,