Skip to content

Commit

Permalink
chore: Refactor mutations to use helper queries and add validators fi…
Browse files Browse the repository at this point in the history
…le (#73)
  • Loading branch information
evadecker authored Sep 18, 2024
1 parent 60179b8 commit 528e060
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 111 deletions.
4 changes: 1 addition & 3 deletions convex/formFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import { query } from "./_generated/server";
// https://docs.convex.dev/functions/validation

export const getAllFieldsForForm = query({
args: {
formId: v.id("forms"),
},
args: { formId: v.id("forms") },
handler: async (ctx, args) => {
return await ctx.db
.query("formFields")
Expand Down
27 changes: 9 additions & 18 deletions convex/forms.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getAuthUserId } from "@convex-dev/auth/server";
import { v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { jurisdictions } from "./schema";
import { userMutation } from "./helpers";
import { jurisdiction } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation
Expand Down Expand Up @@ -51,7 +51,7 @@ export const generateUploadUrl = mutation(async (ctx) => {
return await ctx.storage.generateUploadUrl();
});

export const uploadPDF = mutation({
export const uploadPDF = userMutation({
args: { formId: v.id("forms"), storageId: v.id("_storage") },
handler: async (ctx, args) => {
return await ctx.db.patch(args.formId, {
Expand All @@ -60,48 +60,39 @@ export const uploadPDF = mutation({
},
});

export const createForm = mutation({
export const createForm = userMutation({
args: {
title: v.string(),
jurisdiction: jurisdictions,
jurisdiction: jurisdiction,
formCode: v.optional(v.string()),
},
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
return await ctx.db.insert("forms", {
title: args.title,
jurisdiction: args.jurisdiction,
formCode: args.formCode,
creationUser: userId,
creationUser: ctx.userId,
});
},
});

export const deleteForm = mutation({
export const deleteForm = userMutation({
args: { formId: v.id("forms") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(args.formId, { deletionTime: Date.now() });
},
});

export const undeleteForm = mutation({
export const undeleteForm = userMutation({
args: { formId: v.id("forms") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(args.formId, { deletionTime: undefined });
},
});

export const permanentlyDeleteForm = mutation({
export const permanentlyDeleteForm = userMutation({
args: { formId: v.id("forms") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");

// TODO: Delete form references in other tables

// Delete the form
Expand Down
25 changes: 25 additions & 0 deletions convex/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { getAuthUserId } from "@convex-dev/auth/server";
import {
customCtx,
customMutation,
customQuery,
} from "convex-helpers/server/customFunctions";
import { mutation, query } from "./_generated/server";

export const userQuery = customQuery(
query,
customCtx(async (ctx) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
return { userId, ctx };
}),
);

export const userMutation = customMutation(mutation, {
args: {},
input: async (ctx) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
return { ctx: { userId }, args: {} };
},
});
32 changes: 10 additions & 22 deletions convex/quests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getAuthUserId } from "@convex-dev/auth/server";
import { v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { jurisdictions } from "./schema";
import { query } from "./_generated/server";
import { userMutation } from "./helpers";
import { jurisdiction } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation
Expand Down Expand Up @@ -30,25 +30,20 @@ export const getQuest = query({
},
});

export const createQuest = mutation({
args: { title: v.string(), jurisdiction: v.optional(jurisdictions) },
export const createQuest = userMutation({
args: { title: v.string(), jurisdiction: v.optional(jurisdiction) },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
return await ctx.db.insert("quests", {
title: args.title,
jurisdiction: args.jurisdiction,
creationUser: userId,
creationUser: ctx.userId,
});
},
});

export const addQuestStep = mutation({
export const addQuestStep = userMutation({
args: { questId: v.id("quests"), title: v.string(), body: v.string() },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");

const existingSteps = (await ctx.db.get(args.questId))?.steps ?? [];

await ctx.db.patch(args.questId, {
Expand All @@ -63,30 +58,23 @@ export const addQuestStep = mutation({
},
});

export const deleteQuest = mutation({
export const deleteQuest = userMutation({
args: { questId: v.id("quests") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(args.questId, { deletionTime: Date.now() });
},
});

export const undeleteQuest = mutation({
export const undeleteQuest = userMutation({
args: { questId: v.id("quests") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(args.questId, { deletionTime: undefined });
},
});

export const permanentlyDeleteQuest = mutation({
export const permanentlyDeleteQuest = userMutation({
args: { questId: v.id("quests") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");

// Delete userQuests
const userQuests = await ctx.db
.query("usersQuests")
Expand Down
18 changes: 4 additions & 14 deletions convex/schema.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { authTables } from "@convex-dev/auth/server";
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { JURISDICTIONS } from "./constants";

export const jurisdictions = v.union(
...Object.keys(JURISDICTIONS).map((jurisdiction) => v.literal(jurisdiction)),
);

export const themes = v.union(
v.literal("system"),
v.literal("light"),
v.literal("dark"),
);
import { jurisdiction, theme } from "./validators";

export default defineSchema({
...authTables,
Expand All @@ -30,7 +20,7 @@ export default defineSchema({
formCode: v.optional(v.string()),
creationUser: v.id("users"),
file: v.optional(v.id("_storage")),
jurisdiction: jurisdictions,
jurisdiction: jurisdiction,
deletionTime: v.optional(v.number()),
}),

Expand Down Expand Up @@ -82,7 +72,7 @@ export default defineSchema({
quests: defineTable({
title: v.string(),
creationUser: v.id("users"),
jurisdiction: v.optional(jurisdictions),
jurisdiction: v.optional(jurisdiction),
deletionTime: v.optional(v.number()),
steps: v.optional(
v.array(
Expand Down Expand Up @@ -111,7 +101,7 @@ export default defineSchema({
emailVerificationTime: v.optional(v.number()),
isAnonymous: v.optional(v.boolean()),
isMinor: v.optional(v.boolean()),
theme: v.optional(themes),
theme: v.optional(theme),
}).index("email", ["email"]),

/**
Expand Down
47 changes: 17 additions & 30 deletions convex/users.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getAuthUserId } from "@convex-dev/auth/server";
import { v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { themes } from "./schema";
import { query } from "./_generated/server";
import { userMutation, userQuery } from "./helpers";
import { theme } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation
Expand All @@ -13,72 +13,59 @@ export const getAllUsers = query({
},
});

export const getCurrentUser = query({
export const getCurrentUser = userQuery({
args: {},
handler: async (ctx) => {
const userId = await getAuthUserId(ctx);
if (userId === null) return null;
return await ctx.db.get(userId);
return await ctx.db.get(ctx.userId);
},
});

export const setCurrentUserName = mutation({
export const setCurrentUserName = userMutation({
args: { name: v.optional(v.string()) },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(userId, { name: args.name });
await ctx.db.patch(ctx.userId, { name: args.name });
},
});

export const setCurrentUserIsMinor = mutation({
export const setCurrentUserIsMinor = userMutation({
args: { isMinor: v.boolean() },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(userId, { isMinor: args.isMinor });
await ctx.db.patch(ctx.userId, { isMinor: args.isMinor });
},
});

export const setUserTheme = mutation({
args: {
theme: themes,
},
export const setUserTheme = userMutation({
args: { theme: theme },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");
await ctx.db.patch(userId, { theme: args.theme });
await ctx.db.patch(ctx.userId, { theme: args.theme });
},
});

export const deleteCurrentUser = mutation({
export const deleteCurrentUser = userMutation({
args: {},
handler: async (ctx) => {
const userId = await getAuthUserId(ctx);
if (userId === null) throw new Error("Not authenticated");

// Delete userQuests
const userQuests = await ctx.db
.query("usersQuests")
.withIndex("userId", (q) => q.eq("userId", userId))
.withIndex("userId", (q) => q.eq("userId", ctx.userId))
.collect();
for (const userQuest of userQuests) await ctx.db.delete(userQuest._id);

// Delete authAccounts
const authAccounts = await ctx.db
.query("authAccounts")
.withIndex("userIdAndProvider", (q) => q.eq("userId", userId))
.withIndex("userIdAndProvider", (q) => q.eq("userId", ctx.userId))
.collect();
for (const account of authAccounts) await ctx.db.delete(account._id);

// Delete authSessions
const authSessions = await ctx.db
.query("authSessions")
.withIndex("userId", (q) => q.eq("userId", userId))
.withIndex("userId", (q) => q.eq("userId", ctx.userId))
.collect();
for (const session of authSessions) await ctx.db.delete(session._id);

// Finally, delete the user
await ctx.db.delete(userId);
await ctx.db.delete(ctx.userId);
},
});
Loading

0 comments on commit 528e060

Please sign in to comment.