75 lines
1.7 KiB
TypeScript
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,
|
|
});
|
|
},
|
|
});
|