Files
webdev-pipeline/convex/settings.ts

75 lines
1.7 KiB
TypeScript

import { v } from "convex/values";
import {
filterSafeSettingsRows,
isSafeSettingsKey,
normalizeListLimit,
} from "./domain";
import { mutation, query } from "./_generated/server";
const settingsValue = v.union(v.string(), v.number(), v.boolean(), v.null());
function assertSafeSettingsKey(key: string) {
if (!isSafeSettingsKey(key)) {
throw new Error("Settings metadata cannot store secrets or credentials.");
}
}
export const get = query({
args: { key: v.string() },
handler: async (ctx, args) => {
assertSafeSettingsKey(args.key);
return await ctx.db
.query("settings")
.withIndex("by_key", (q) => q.eq("key", args.key))
.unique();
},
});
export const list = query({
args: { limit: v.optional(v.number()) },
handler: async (ctx, args) => {
const rows = await ctx.db
.query("settings")
.order("desc")
.take(normalizeListLimit(args.limit));
return filterSafeSettingsRows(rows);
},
});
export const set = mutation({
args: {
key: v.string(),
value: settingsValue,
description: v.optional(v.string()),
},
handler: async (ctx, args) => {
assertSafeSettingsKey(args.key);
const now = Date.now();
const existing = await ctx.db
.query("settings")
.withIndex("by_key", (q) => q.eq("key", args.key))
.unique();
if (existing) {
await ctx.db.patch(existing._id, {
value: args.value,
description: args.description,
updatedAt: now,
});
return existing._id;
}
return await ctx.db.insert("settings", {
key: args.key,
value: args.value,
description: args.description,
createdAt: now,
updatedAt: now,
});
},
});