@atproto/ozone
Version:
Backend service for moderating the Bluesky network.
166 lines • 5.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SetService = void 0;
const pagination_1 = require("../db/pagination");
class SetService {
constructor(db) {
Object.defineProperty(this, "db", {
enumerable: true,
configurable: true,
writable: true,
value: db
});
}
static creator() {
return (db) => new SetService(db);
}
buildQueryForSetWithSize() {
return this.db.db.selectFrom('set_detail as s').select([
's.id',
's.name',
's.description',
's.createdAt',
's.updatedAt',
(eb) => eb
.selectFrom('set_value')
.select((e) => e.fn.count('setId').as('count'))
.whereRef('setId', '=', 's.id')
.as('setSize'),
]);
}
async query({ limit, cursor, namePrefix, sortBy, sortDirection, }) {
let qb = this.buildQueryForSetWithSize().limit(limit);
if (namePrefix) {
qb = qb.where('s.name', 'like', `${namePrefix}%`);
}
if (cursor) {
if (sortBy === 'name') {
qb = qb.where('s.name', sortDirection === 'asc' ? '>' : '<', cursor);
}
else {
qb = qb.where(`s.${sortBy}`, sortDirection === 'asc' ? '>' : '<', new Date(cursor));
}
}
qb = qb.orderBy(`s.${sortBy}`, sortDirection);
const sets = await qb.execute();
const lastItem = sets.at(-1);
return {
sets,
cursor: lastItem
? sortBy === 'name'
? lastItem?.name
: lastItem?.[sortBy].toISOString()
: undefined,
};
}
async getByName(name) {
const query = this.db.db
.selectFrom('set_detail')
.selectAll()
.where('name', '=', name);
return await query.executeTakeFirst();
}
async getByNameWithSize(name) {
return await this.buildQueryForSetWithSize()
.where('s.name', '=', name)
.executeTakeFirst();
}
async getSetWithValues({ name, limit, cursor, }) {
const set = await this.getByNameWithSize(name);
if (!set)
return undefined;
const { ref } = this.db.db.dynamic;
const qb = this.db.db
.selectFrom('set_value')
.selectAll()
.where('setId', '=', set.id);
const keyset = new pagination_1.TimeIdKeyset(ref(`createdAt`), ref('id'));
const paginatedBuilder = (0, pagination_1.paginate)(qb, {
limit,
cursor,
keyset,
direction: 'asc',
});
const result = await paginatedBuilder.execute();
return {
set,
values: result.map((v) => v.value),
cursor: keyset.packFromResult(result),
};
}
async upsert({ name, description, }) {
await this.db.db
.insertInto('set_detail')
.values({
name,
description,
updatedAt: new Date(),
})
.onConflict((oc) => {
// if description is provided as a string, even an empty one, update it
// otherwise, just update the updatedAt timestamp
return oc.column('name').doUpdateSet(typeof description === 'string'
? {
description,
updatedAt: new Date(),
}
: { updatedAt: new Date() });
})
.execute();
}
async addValues(setId, values) {
await this.db.transaction(async (txn) => {
const now = new Date();
const query = txn.db
.insertInto('set_value')
.values(values.map((value) => ({
setId,
value,
createdAt: now,
})))
.onConflict((oc) => oc.columns(['setId', 'value']).doNothing());
await query.execute();
// Update the set's updatedAt timestamp
await txn.db
.updateTable('set_detail')
.set({ updatedAt: now })
.where('id', '=', setId)
.execute();
});
}
async removeValues(setId, values) {
if (values.length < 1) {
return;
}
await this.db.transaction(async (txn) => {
const query = txn.db
.deleteFrom('set_value')
.where('setId', '=', setId)
.where('value', 'in', values);
await query.execute();
// Update the set's updatedAt timestamp
await txn.db
.updateTable('set_detail')
.set({ updatedAt: new Date() })
.where('id', '=', setId)
.execute();
});
}
async removeSet(setId) {
await this.db.transaction(async (txn) => {
await txn.db.deleteFrom('set_value').where('setId', '=', setId).execute();
await txn.db.deleteFrom('set_detail').where('id', '=', setId).execute();
});
}
view(set) {
return {
name: set.name,
description: set.description || undefined,
setSize: set.setSize,
createdAt: set.createdAt.toISOString(),
updatedAt: set.updatedAt.toISOString(),
};
}
}
exports.SetService = SetService;
//# sourceMappingURL=service.js.map