Swap the names of DittoDB and DittoDatabase

This commit is contained in:
Alex Gleason 2025-02-20 11:26:27 -06:00
parent f5947eda8b
commit c7624e99d7
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
11 changed files with 100 additions and 100 deletions

View file

@ -1,6 +0,0 @@
import { DittoDB } from './DittoDB.ts';
Deno.test('DittoDB', async () => {
const db = DittoDB.create('memory://');
await DittoDB.migrate(db.kysely);
});

View file

@ -1,69 +1,15 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import type { Kysely } from 'kysely';
import { logi } from '@soapbox/logi';
import { FileMigrationProvider, type Kysely, Migrator } from 'kysely';
import { DittoPglite } from './adapters/DittoPglite.ts';
import { DittoPostgres } from './adapters/DittoPostgres.ts';
import type { JsonValue } from '@std/json';
import type { DittoDatabase, DittoDatabaseOpts } from './DittoDatabase.ts';
import type { DittoTables } from './DittoTables.ts';
export class DittoDB {
/** Open a new database connection. */
static create(databaseUrl: string, opts?: DittoDatabaseOpts): DittoDatabase {
const { protocol } = new URL(databaseUrl);
switch (protocol) {
case 'file:':
case 'memory:':
return DittoPglite.create(databaseUrl, opts);
case 'postgres:':
case 'postgresql:':
return DittoPostgres.create(databaseUrl, opts);
default:
throw new Error('Unsupported database URL.');
}
}
/** Migrate the database to the latest version. */
static async migrate(kysely: Kysely<DittoTables>) {
const migrator = new Migrator({
db: kysely,
provider: new FileMigrationProvider({
fs,
path,
migrationFolder: new URL(import.meta.resolve('./migrations')).pathname,
}),
});
logi({ level: 'info', ns: 'ditto.db.migration', msg: 'Running migrations...', state: 'started' });
const { results, error } = await migrator.migrateToLatest();
if (error) {
logi({
level: 'fatal',
ns: 'ditto.db.migration',
msg: 'Migration failed.',
state: 'failed',
results: results as unknown as JsonValue,
error: error instanceof Error ? error : null,
});
Deno.exit(1);
} else {
if (!results?.length) {
logi({ level: 'info', ns: 'ditto.db.migration', msg: 'Everything up-to-date.', state: 'skipped' });
} else {
logi({
level: 'info',
ns: 'ditto.db.migration',
msg: 'Migrations finished!',
state: 'migrated',
results: results as unknown as JsonValue,
});
}
}
}
export interface DittoDB extends AsyncDisposable {
readonly kysely: Kysely<DittoTables>;
readonly poolSize: number;
readonly availableConnections: number;
listen(channel: string, callback: (payload: string) => void): void;
}
export interface DittoDBOpts {
poolSize?: number;
debug?: 0 | 1 | 2 | 3 | 4 | 5;
}

View file

@ -0,0 +1,6 @@
import { DittoDatabase } from './DittoDatabase.ts';
Deno.test('DittoDatabase', async () => {
const db = DittoDatabase.create('memory://');
await DittoDatabase.migrate(db.kysely);
});

View file

@ -1,15 +1,69 @@
import type { Kysely } from 'kysely';
import fs from 'node:fs/promises';
import path from 'node:path';
import { logi } from '@soapbox/logi';
import { FileMigrationProvider, type Kysely, Migrator } from 'kysely';
import { DittoPglite } from './adapters/DittoPglite.ts';
import { DittoPostgres } from './adapters/DittoPostgres.ts';
import type { JsonValue } from '@std/json';
import type { DittoDB, DittoDBOpts } from './DittoDB.ts';
import type { DittoTables } from './DittoTables.ts';
export interface DittoDatabase extends AsyncDisposable {
readonly kysely: Kysely<DittoTables>;
readonly poolSize: number;
readonly availableConnections: number;
listen(channel: string, callback: (payload: string) => void): void;
}
export class DittoDatabase {
/** Open a new database connection. */
static create(databaseUrl: string, opts?: DittoDBOpts): DittoDB {
const { protocol } = new URL(databaseUrl);
export interface DittoDatabaseOpts {
poolSize?: number;
debug?: 0 | 1 | 2 | 3 | 4 | 5;
switch (protocol) {
case 'file:':
case 'memory:':
return DittoPglite.create(databaseUrl, opts);
case 'postgres:':
case 'postgresql:':
return DittoPostgres.create(databaseUrl, opts);
default:
throw new Error('Unsupported database URL.');
}
}
/** Migrate the database to the latest version. */
static async migrate(kysely: Kysely<DittoTables>) {
const migrator = new Migrator({
db: kysely,
provider: new FileMigrationProvider({
fs,
path,
migrationFolder: new URL(import.meta.resolve('./migrations')).pathname,
}),
});
logi({ level: 'info', ns: 'ditto.db.migration', msg: 'Running migrations...', state: 'started' });
const { results, error } = await migrator.migrateToLatest();
if (error) {
logi({
level: 'fatal',
ns: 'ditto.db.migration',
msg: 'Migration failed.',
state: 'failed',
results: results as unknown as JsonValue,
error: error instanceof Error ? error : null,
});
Deno.exit(1);
} else {
if (!results?.length) {
logi({ level: 'info', ns: 'ditto.db.migration', msg: 'Everything up-to-date.', state: 'skipped' });
} else {
logi({
level: 'info',
ns: 'ditto.db.migration',
msg: 'Migrations finished!',
state: 'migrated',
results: results as unknown as JsonValue,
});
}
}
}
}

View file

@ -6,11 +6,11 @@ import { Kysely } from 'kysely';
import { KyselyLogger } from '../KyselyLogger.ts';
import { isWorker } from '../utils/worker.ts';
import type { DittoDatabase, DittoDatabaseOpts } from '../DittoDatabase.ts';
import type { DittoDB, DittoDBOpts } from '../DittoDB.ts';
import type { DittoTables } from '../DittoTables.ts';
export class DittoPglite {
static create(databaseUrl: string, opts?: DittoDatabaseOpts): DittoDatabase {
static create(databaseUrl: string, opts?: DittoDBOpts): DittoDB {
const url = new URL(databaseUrl);
if (url.protocol === 'file:' && isWorker()) {

View file

@ -14,11 +14,11 @@ import postgres from 'postgres';
import { KyselyLogger } from '../KyselyLogger.ts';
import type { DittoDatabase, DittoDatabaseOpts } from '../DittoDatabase.ts';
import type { DittoDB, DittoDBOpts } from '../DittoDB.ts';
import type { DittoTables } from '../DittoTables.ts';
export class DittoPostgres {
static create(databaseUrl: string, opts?: DittoDatabaseOpts): DittoDatabase {
static create(databaseUrl: string, opts?: DittoDBOpts): DittoDB {
const pg = postgres(databaseUrl, { max: opts?.poolSize });
const kysely = new Kysely<DittoTables>({

View file

@ -1,4 +1,4 @@
export { DittoDB } from './DittoDB.ts';
export { DittoDatabase } from './DittoDatabase.ts';
export type { DittoDatabase } from './DittoDatabase.ts';
export type { DittoDB } from './DittoDB.ts';
export type { DittoTables } from './DittoTables.ts';

View file

@ -1,5 +1,5 @@
// deno-lint-ignore-file require-await
import { type DittoDatabase, DittoDB } from '@ditto/db';
import { DittoDatabase, type DittoDB } from '@ditto/db';
import { NPool, NRelay1 } from '@nostrify/nostrify';
import { logi } from '@soapbox/logi';
@ -12,25 +12,25 @@ import { seedZapSplits } from '@/utils/zap-split.ts';
export class Storages {
private static _db: Promise<DittoPgStore> | undefined;
private static _database: Promise<DittoDatabase> | undefined;
private static _database: Promise<DittoDB> | undefined;
private static _admin: Promise<AdminStore> | undefined;
private static _client: Promise<NPool<NRelay1>> | undefined;
public static async database(): Promise<DittoDatabase> {
public static async database(): Promise<DittoDB> {
if (!this._database) {
this._database = (async () => {
const db = DittoDB.create(Conf.databaseUrl, {
const db = DittoDatabase.create(Conf.databaseUrl, {
poolSize: Conf.pg.poolSize,
debug: Conf.pgliteDebug,
});
await DittoDB.migrate(db.kysely);
await DittoDatabase.migrate(db.kysely);
return db;
})();
}
return this._database;
}
public static async kysely(): Promise<DittoDatabase['kysely']> {
public static async kysely(): Promise<DittoDB['kysely']> {
const { kysely } = await this.database();
return kysely;
}

View file

@ -1,6 +1,6 @@
// deno-lint-ignore-file require-await
import { DittoDatabase, DittoTables } from '@ditto/db';
import { type DittoDB, type DittoTables } from '@ditto/db';
import { detectLanguage } from '@ditto/lang';
import { NPostgres, NPostgresSchema } from '@nostrify/db';
import { dbEventsCounter, internalSubscriptionsSizeGauge } from '@ditto/metrics';
@ -50,7 +50,7 @@ interface TagConditionOpts {
/** Options for the EventsDB store. */
interface DittoPgStoreOpts {
/** Kysely instance to use. */
db: DittoDatabase;
db: DittoDB;
/** Pubkey of the admin account. */
pubkey: string;
/** Timeout in milliseconds for database queries. */

View file

@ -1,4 +1,4 @@
import { DittoDB } from '@ditto/db';
import { DittoDatabase } from '@ditto/db';
import { NostrEvent } from '@nostrify/nostrify';
import { Conf } from '@/config.ts';
@ -13,9 +13,9 @@ export async function eventFixture(name: string): Promise<NostrEvent> {
/** Create a database for testing. It uses `DATABASE_URL`, or creates an in-memory database by default. */
export async function createTestDB(opts?: { pure?: boolean }) {
const db = DittoDB.create(Conf.databaseUrl, { poolSize: 1 });
const db = DittoDatabase.create(Conf.databaseUrl, { poolSize: 1 });
await DittoDB.migrate(db.kysely);
await DittoDatabase.migrate(db.kysely);
const store = new DittoPgStore({
db,

View file

@ -1,4 +1,4 @@
import { DittoDB } from '@ditto/db';
import { DittoDatabase } from '@ditto/db';
import '@soapbox/safe-fetch/load';
import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/nostrify';
import { ReadOnlyPolicy } from '@nostrify/policies';
@ -30,7 +30,7 @@ export class CustomPolicy implements NPolicy {
async init({ path, databaseUrl, pubkey }: PolicyInit): Promise<void> {
const Policy = (await import(path)).default;
const db = DittoDB.create(databaseUrl, { poolSize: 1 });
const db = DittoDatabase.create(databaseUrl, { poolSize: 1 });
const store = new DittoPgStore({
db,