UNPKG

auron

Version:

Interact with your ATProto labeler from your terminal

170 lines (169 loc) 7.29 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.database = void 0; const kysely_1 = require("kysely"); const better_sqlite3_1 = __importDefault(require("better-sqlite3")); const initializers_1 = require("../schemas/initializers"); const transformers_1 = require("./subject/transformers"); // Initialize Kysely with SQLite const db = new kysely_1.Kysely({ dialect: new kysely_1.SqliteDialect({ database: new better_sqlite3_1.default(process.env.LOCAL_DB_PATH || "aurondb.sqlite"), }), }); // Create the subjects table if it doesn't exist exports.database = { async initialize() { await (0, initializers_1.initializeSubjectTable)(db); await (0, initializers_1.initializeEventTable)(db); await (0, initializers_1.initializeRepoTable)(db); await (0, initializers_1.initializeRecordTable)(db); await (0, initializers_1.initializeProfileTable)(db); }, async insertSubjects(subjectStatuses) { await this.initialize(); const ids = subjectStatuses.map(({ id }) => id); // This is questionable, probably could do update on conflict or something but quick n dirty for now await db.deleteFrom("subjects").where("id", "in", ids).execute(); const { ref } = db.dynamic; return await db .insertInto("subjects") .values(subjectStatuses) .onConflict((oc) => { return oc.doUpdateSet({ reviewState: (0, kysely_1.sql) `${ref(`excluded.reviewState`)}`, lastReviewedAt: (0, kysely_1.sql) `${ref(`excluded.lastReviewedAt`)}`, lastReportedAt: (0, kysely_1.sql) `${ref(`excluded.lastReportedAt`)}`, updatedAt: (0, kysely_1.sql) `${ref("excluded.updatedAt")}`, lastReviewedBy: (0, kysely_1.sql) `${ref("excluded.lastReviewedBy")}`, takendown: (0, kysely_1.sql) `${ref("excluded.takendown")}`, tags: (0, kysely_1.sql) `${ref("excluded.tags")}`, lastAppealedAt: (0, kysely_1.sql) `${ref("excluded.lastAppealedAt")}`, suspendUntil: (0, kysely_1.sql) `${ref("excluded.suspendUntil")}`, muteUntil: (0, kysely_1.sql) `${ref("excluded.muteUntil")}`, comment: (0, kysely_1.sql) `${ref("excluded.comment")}`, }); }) .execute(); }, async insertEvents(events) { await this.initialize(); const ids = events.map(({ id }) => id); // This is questionable, probably could do update on conflict or something but quick n dirty for now await db.deleteFrom("events").where("id", "in", ids).execute(); return await db.insertInto("events").values(events).execute(); }, async listSubjects({ subjectType, takendown, cursor, limit, }) { await this.initialize(); let builder = db .selectFrom("subjects") .leftJoin("repos", "subjects.did", "repos.did") .leftJoin("profiles", "subjects.did", "profiles.did") .leftJoin("records", (join) => join.onRef("records.uri", "=", (0, kysely_1.sql) `'at://' || subjects.did || '/' || subjects.recordPath`)) .selectAll(["subjects", "repos", "records", "profiles"]); if (subjectType === "account") { builder = builder.where("recordPath", "=", ""); } else if (subjectType === "record") { builder = builder.where("recordPath", "!=", ""); } if (takendown !== undefined) { builder = builder.where("takendown", "=", takendown ? 1 : 0); } if (limit) { builder = builder.limit(limit); } if (cursor) { builder = builder.where("lastReportedAt", "<", cursor); } const results = await builder.orderBy("lastReportedAt", "desc").execute(); // @ts-ignore return results.map(transformers_1.transformFullStatusFromDatabase); }, async clearSubjects() { await this.initialize(); await db.deleteFrom("subjects").execute(); }, async getMissingRepoDids() { await this.initialize(); const results = await db .selectFrom("subjects") .select("did") .distinct() .where("did", "not in", (qb) => qb.selectFrom("repos").select(["did"])) .execute(); return results.map(({ did }) => did); }, async getMissingProfileDids() { await this.initialize(); const syncPeriod = new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString(); const results = await db .selectFrom("subjects") .select("did") .distinct() .where("did", "not in", (qb) => { return qb .selectFrom("profiles") .select("did") .where("syncedAt", ">", syncPeriod); }) .execute(); return results.map(({ did }) => did); }, async getMissingRecordUris() { await this.initialize(); const results = await db .selectFrom("subjects") .leftJoin("records", (join) => join.onRef("records.uri", "=", (0, kysely_1.sql) `'at://' || subjects.did || '/' || subjects.recordPath`)) .select(["subjects.did", "subjects.recordPath"]) .where("records.uri", "is", null) .where("subjects.recordPath", "!=", "") .execute(); return results.map(({ did, recordPath }) => `at://${did}/${recordPath}`); }, async saveRepos(repos) { await this.initialize(); await db.insertInto("repos").values(repos).execute(); }, async saveRecords(records) { await this.initialize(); await db.insertInto("records").values(records).execute(); }, async saveProfiles(profiles) { await this.initialize(); const dids = profiles.map(({ did }) => did); // Remove all existing profiles first if (dids.length) { await db.deleteFrom("profiles").where("did", "in", dids).execute(); } await db.insertInto("profiles").values(profiles).execute(); }, async getEvents(opts) { let qb = db.selectFrom("events"); if (opts.cursor) { qb = qb.where("id", opts.order === "asc" ? ">" : "<", opts.cursor); } if (opts.types.length) { qb = qb.where("action", "in", opts.types); } if (opts.createdAfter) { qb = qb.where("createdAt", ">", opts.createdAfter); } if (opts.createdBefore) { qb = qb.where("createdAt", "<", opts.createdBefore); } return qb .orderBy("id", opts.order || "asc") .select(["subjectDid", "subjectUri", "action", "createdAt", "createdBy"]) .execute(); }, async clear() { await db.schema.dropTable("events").execute(); await db.schema.dropTable("subjects").execute(); await db.schema.dropTable("repos").execute(); await db.schema.dropTable("profiles").execute(); }, };