validation
This commit is contained in:
@@ -47,7 +47,7 @@ export default function PostForm(props: PostFormProps) {
|
|||||||
const [loading, setLoading] = createSignal(false);
|
const [loading, setLoading] = createSignal(false);
|
||||||
const [error, setError] = createSignal("");
|
const [error, setError] = createSignal("");
|
||||||
const [showAutoSaveMessage, setShowAutoSaveMessage] = createSignal(false);
|
const [showAutoSaveMessage, setShowAutoSaveMessage] = createSignal(false);
|
||||||
const [isInitialLoad, setIsInitialLoad] = createSignal(props.mode === "edit");
|
const [isInitialLoad, setIsInitialLoad] = createSignal(true);
|
||||||
const [initialBody, setInitialBody] = createSignal<string | undefined>(
|
const [initialBody, setInitialBody] = createSignal<string | undefined>(
|
||||||
props.initialData?.body
|
props.initialData?.body
|
||||||
);
|
);
|
||||||
@@ -57,9 +57,10 @@ export default function PostForm(props: PostFormProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Mark initial load as complete after data is loaded (for edit mode)
|
// Mark initial load as complete after data is loaded (for edit mode)
|
||||||
|
// Use setTimeout to ensure this runs after all signals are initialized
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (props.mode === "edit" && props.initialData) {
|
if (props.mode === "edit" && props.initialData) {
|
||||||
setIsInitialLoad(false);
|
setTimeout(() => setIsInitialLoad(false), 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { env } from "~/env/server";
|
|||||||
import { ConnectionFactory, hashPassword, checkPassword } from "~/server/utils";
|
import { ConnectionFactory, hashPassword, checkPassword } from "~/server/utils";
|
||||||
import { SignJWT, jwtVerify } from "jose";
|
import { SignJWT, jwtVerify } from "jose";
|
||||||
import { setCookie, getCookie } from "vinxi/http";
|
import { setCookie, getCookie } from "vinxi/http";
|
||||||
import type { User } from "~/types/user";
|
import type { User } from "~/db/types";
|
||||||
import {
|
import {
|
||||||
fetchWithTimeout,
|
fetchWithTimeout,
|
||||||
checkResponse,
|
checkResponse,
|
||||||
@@ -15,6 +15,12 @@ import {
|
|||||||
TimeoutError,
|
TimeoutError,
|
||||||
APIError
|
APIError
|
||||||
} from "~/server/fetch-utils";
|
} from "~/server/fetch-utils";
|
||||||
|
import {
|
||||||
|
registerUserSchema,
|
||||||
|
loginUserSchema,
|
||||||
|
resetPasswordSchema,
|
||||||
|
requestPasswordResetSchema
|
||||||
|
} from "../schemas/user";
|
||||||
|
|
||||||
async function createJWT(
|
async function createJWT(
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -501,16 +507,11 @@ export const authRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
emailRegistration: publicProcedure
|
emailRegistration: publicProcedure
|
||||||
.input(
|
.input(registerUserSchema)
|
||||||
z.object({
|
|
||||||
email: z.string().email(),
|
|
||||||
password: z.string().min(8),
|
|
||||||
passwordConfirmation: z.string().min(8)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { email, password, passwordConfirmation } = input;
|
const { email, password, passwordConfirmation } = input;
|
||||||
|
|
||||||
|
// Schema already validates password match, but double check
|
||||||
if (password !== passwordConfirmation) {
|
if (password !== passwordConfirmation) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
@@ -549,13 +550,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
emailPasswordLogin: publicProcedure
|
emailPasswordLogin: publicProcedure
|
||||||
.input(
|
.input(loginUserSchema)
|
||||||
z.object({
|
|
||||||
email: z.string().email(),
|
|
||||||
password: z.string(),
|
|
||||||
rememberMe: z.boolean().optional()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { email, password, rememberMe } = input;
|
const { email, password, rememberMe } = input;
|
||||||
|
|
||||||
@@ -746,7 +741,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
requestPasswordReset: publicProcedure
|
requestPasswordReset: publicProcedure
|
||||||
.input(z.object({ email: z.string().email() }))
|
.input(requestPasswordResetSchema)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { email } = input;
|
const { email } = input;
|
||||||
|
|
||||||
@@ -862,16 +857,11 @@ export const authRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
resetPassword: publicProcedure
|
resetPassword: publicProcedure
|
||||||
.input(
|
.input(resetPasswordSchema)
|
||||||
z.object({
|
|
||||||
token: z.string(),
|
|
||||||
newPassword: z.string().min(8),
|
|
||||||
newPasswordConfirmation: z.string().min(8)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { token, newPassword, newPasswordConfirmation } = input;
|
const { token, newPassword, newPasswordConfirmation } = input;
|
||||||
|
|
||||||
|
// Schema already validates password match, but double check
|
||||||
if (newPassword !== newPasswordConfirmation) {
|
if (newPassword !== newPasswordConfirmation) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
@@ -945,7 +935,7 @@ export const authRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
resendEmailVerification: publicProcedure
|
resendEmailVerification: publicProcedure
|
||||||
.input(z.object({ email: z.string().email() }))
|
.input(requestPasswordResetSchema)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { email } = input;
|
const { email } = input;
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,35 @@ import { ConnectionFactory } from "~/server/utils";
|
|||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { env } from "~/env/server";
|
import { env } from "~/env/server";
|
||||||
import { cache, withCacheAndStale } from "~/server/cache";
|
import { cache, withCacheAndStale } from "~/server/cache";
|
||||||
|
import type {
|
||||||
|
Comment,
|
||||||
|
CommentReaction,
|
||||||
|
Post,
|
||||||
|
PostLike,
|
||||||
|
User,
|
||||||
|
Tag
|
||||||
|
} from "~/db/types";
|
||||||
|
import {
|
||||||
|
getCommentReactionsQuerySchema,
|
||||||
|
toggleCommentReactionMutationSchema,
|
||||||
|
deleteCommentWithTypeSchema,
|
||||||
|
getCommentsByPostIdSchema,
|
||||||
|
getPostByIdSchema,
|
||||||
|
getPostByTitleSchema,
|
||||||
|
createPostSchema,
|
||||||
|
updatePostSchema,
|
||||||
|
idSchema,
|
||||||
|
togglePostLikeMutationSchema,
|
||||||
|
getUserByIdSchema,
|
||||||
|
updateUserImageSchema,
|
||||||
|
updateUserEmailSchema
|
||||||
|
} from "../schemas/database";
|
||||||
|
|
||||||
const BLOG_CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours
|
const BLOG_CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours
|
||||||
|
|
||||||
export const databaseRouter = createTRPCRouter({
|
export const databaseRouter = createTRPCRouter({
|
||||||
getCommentReactions: publicProcedure
|
getCommentReactions: publicProcedure
|
||||||
.input(z.object({ commentID: z.string() }))
|
.input(getCommentReactionsQuerySchema)
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -22,7 +45,9 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
sql: query,
|
sql: query,
|
||||||
args: [input.commentID]
|
args: [input.commentID]
|
||||||
});
|
});
|
||||||
return { commentReactions: results.rows };
|
return {
|
||||||
|
commentReactions: results.rows as unknown as CommentReaction[]
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -32,13 +57,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
addCommentReaction: publicProcedure
|
addCommentReaction: publicProcedure
|
||||||
.input(
|
.input(toggleCommentReactionMutationSchema)
|
||||||
z.object({
|
|
||||||
type: z.string(),
|
|
||||||
comment_id: z.string(),
|
|
||||||
user_id: z.string()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -57,7 +76,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
args: [input.comment_id]
|
args: [input.comment_id]
|
||||||
});
|
});
|
||||||
|
|
||||||
return { commentReactions: res.rows };
|
return { commentReactions: res.rows as unknown as CommentReaction[] };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -67,13 +86,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
removeCommentReaction: publicProcedure
|
removeCommentReaction: publicProcedure
|
||||||
.input(
|
.input(toggleCommentReactionMutationSchema)
|
||||||
z.object({
|
|
||||||
type: z.string(),
|
|
||||||
comment_id: z.string(),
|
|
||||||
user_id: z.string()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -92,7 +105,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
args: [input.comment_id]
|
args: [input.comment_id]
|
||||||
});
|
});
|
||||||
|
|
||||||
return { commentReactions: res.rows };
|
return { commentReactions: res.rows as unknown as CommentReaction[] };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -121,13 +134,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
deleteComment: protectedProcedure
|
deleteComment: protectedProcedure
|
||||||
.input(
|
.input(deleteCommentWithTypeSchema)
|
||||||
z.object({
|
|
||||||
commentID: z.number(),
|
|
||||||
commenterID: z.string(),
|
|
||||||
deletionType: z.enum(["user", "admin", "database"])
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -238,7 +245,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
getCommentsByPostId: publicProcedure
|
getCommentsByPostId: publicProcedure
|
||||||
.input(z.object({ post_id: z.string() }))
|
.input(getCommentsByPostIdSchema)
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -253,7 +260,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
sql: query,
|
sql: query,
|
||||||
args: [input.post_id]
|
args: [input.post_id]
|
||||||
});
|
});
|
||||||
return { comments: res.rows };
|
return { comments: res.rows as unknown as Comment[] };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -263,12 +270,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
getPostById: publicProcedure
|
getPostById: publicProcedure
|
||||||
.input(
|
.input(getPostByIdSchema)
|
||||||
z.object({
|
|
||||||
category: z.literal("blog"),
|
|
||||||
id: z.number()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
return withCacheAndStale(
|
return withCacheAndStale(
|
||||||
`blog-post-id-${input.id}`,
|
`blog-post-id-${input.id}`,
|
||||||
@@ -311,12 +313,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
getPostByTitle: publicProcedure
|
getPostByTitle: publicProcedure
|
||||||
.input(
|
.input(getPostByTitleSchema)
|
||||||
z.object({
|
|
||||||
category: z.literal("blog"),
|
|
||||||
title: z.string()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.query(async ({ input, ctx }) => {
|
.query(async ({ input, ctx }) => {
|
||||||
return withCacheAndStale(
|
return withCacheAndStale(
|
||||||
`blog-post-title-${input.title}`,
|
`blog-post-title-${input.title}`,
|
||||||
@@ -510,55 +507,48 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
deletePost: publicProcedure
|
deletePost: publicProcedure.input(idSchema).mutation(async ({ input }) => {
|
||||||
.input(z.object({ id: z.number() }))
|
try {
|
||||||
.mutation(async ({ input }) => {
|
const conn = ConnectionFactory();
|
||||||
try {
|
|
||||||
const conn = ConnectionFactory();
|
|
||||||
|
|
||||||
await conn.execute({
|
await conn.execute({
|
||||||
sql: "DELETE FROM Tag WHERE post_id = ?",
|
sql: "DELETE FROM Tag WHERE post_id = ?",
|
||||||
args: [input.id.toString()]
|
args: [input.id.toString()]
|
||||||
});
|
});
|
||||||
|
|
||||||
await conn.execute({
|
await conn.execute({
|
||||||
sql: "DELETE FROM PostLike WHERE post_id = ?",
|
sql: "DELETE FROM PostLike WHERE post_id = ?",
|
||||||
args: [input.id.toString()]
|
args: [input.id.toString()]
|
||||||
});
|
});
|
||||||
|
|
||||||
await conn.execute({
|
await conn.execute({
|
||||||
sql: "DELETE FROM Comment WHERE post_id = ?",
|
sql: "DELETE FROM Comment WHERE post_id = ?",
|
||||||
args: [input.id]
|
args: [input.id]
|
||||||
});
|
});
|
||||||
|
|
||||||
await conn.execute({
|
await conn.execute({
|
||||||
sql: "DELETE FROM Post WHERE id = ?",
|
sql: "DELETE FROM Post WHERE id = ?",
|
||||||
args: [input.id]
|
args: [input.id]
|
||||||
});
|
});
|
||||||
|
|
||||||
cache.deleteByPrefix("blog-");
|
cache.deleteByPrefix("blog-");
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
message: "Failed to delete post"
|
message: "Failed to delete post"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Post Likes Routes
|
// Post Likes Routes
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
addPostLike: publicProcedure
|
addPostLike: publicProcedure
|
||||||
.input(
|
.input(togglePostLikeMutationSchema)
|
||||||
z.object({
|
|
||||||
user_id: z.string(),
|
|
||||||
post_id: z.string()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -574,7 +564,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
args: [input.post_id]
|
args: [input.post_id]
|
||||||
});
|
});
|
||||||
|
|
||||||
return { newLikes: res.rows };
|
return { newLikes: res.rows as unknown as PostLike[] };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -584,12 +574,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
removePostLike: publicProcedure
|
removePostLike: publicProcedure
|
||||||
.input(
|
.input(togglePostLikeMutationSchema)
|
||||||
z.object({
|
|
||||||
user_id: z.string(),
|
|
||||||
post_id: z.string()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -608,7 +593,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
args: [input.post_id]
|
args: [input.post_id]
|
||||||
});
|
});
|
||||||
|
|
||||||
return { newLikes: res.rows };
|
return { newLikes: res.rows as unknown as PostLike[] };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -622,7 +607,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
getUserById: publicProcedure
|
getUserById: publicProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(getUserByIdSchema)
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -654,7 +639,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
getUserPublicData: publicProcedure
|
getUserPublicData: publicProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(getUserByIdSchema)
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -683,7 +668,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
getUserImage: publicProcedure
|
getUserImage: publicProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(getUserByIdSchema)
|
||||||
.query(async ({ input }) => {
|
.query(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -702,12 +687,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
updateUserImage: publicProcedure
|
updateUserImage: publicProcedure
|
||||||
.input(
|
.input(updateUserImageSchema)
|
||||||
z.object({
|
|
||||||
id: z.string(),
|
|
||||||
imageURL: z.string()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
@@ -729,13 +709,7 @@ export const databaseRouter = createTRPCRouter({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
updateUserEmail: publicProcedure
|
updateUserEmail: publicProcedure
|
||||||
.input(
|
.input(updateUserEmailSchema)
|
||||||
z.object({
|
|
||||||
id: z.string(),
|
|
||||||
newEmail: z.string().email(),
|
|
||||||
oldEmail: z.string().email()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
try {
|
try {
|
||||||
const conn = ConnectionFactory();
|
const conn = ConnectionFactory();
|
||||||
|
|||||||
@@ -277,6 +277,85 @@ export const paginationSchema = z.object({
|
|||||||
offset: z.number().min(0).default(0)
|
offset: z.number().min(0).default(0)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Additional Database Router Schemas
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get post by ID or title
|
||||||
|
*/
|
||||||
|
export const getPostByIdSchema = z.object({
|
||||||
|
category: z.literal("blog"),
|
||||||
|
id: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getPostByTitleSchema = z.object({
|
||||||
|
category: z.literal("blog"),
|
||||||
|
title: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get comments by post ID
|
||||||
|
*/
|
||||||
|
export const getCommentsByPostIdSchema = z.object({
|
||||||
|
post_id: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle post like (add/remove)
|
||||||
|
*/
|
||||||
|
export const togglePostLikeMutationSchema = z.object({
|
||||||
|
user_id: z.string(),
|
||||||
|
post_id: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle comment reaction (add/remove)
|
||||||
|
*/
|
||||||
|
export const toggleCommentReactionMutationSchema = z.object({
|
||||||
|
type: reactionTypeSchema,
|
||||||
|
comment_id: z.number(),
|
||||||
|
user_id: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get comment reactions
|
||||||
|
*/
|
||||||
|
export const getCommentReactionsQuerySchema = z.object({
|
||||||
|
commentID: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete comment with deletion type
|
||||||
|
*/
|
||||||
|
export const deleteCommentWithTypeSchema = z.object({
|
||||||
|
commentID: z.number(),
|
||||||
|
commenterID: z.string(),
|
||||||
|
deletionType: z.enum(["user", "admin", "database"])
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User query schemas
|
||||||
|
*/
|
||||||
|
export const getUserByIdSchema = z.object({
|
||||||
|
id: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getUserPublicDataSchema = z.object({
|
||||||
|
id: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateUserImageSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
imageURL: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateUserEmailSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
newEmail: z.string().email(),
|
||||||
|
oldEmail: z.string().email()
|
||||||
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Type Exports
|
// Type Exports
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -293,3 +372,23 @@ export type CreatePostLikeInput = z.infer<typeof createPostLikeSchema>;
|
|||||||
export type CreateTagInput = z.infer<typeof createTagSchema>;
|
export type CreateTagInput = z.infer<typeof createTagSchema>;
|
||||||
export type CreateConnectionInput = z.infer<typeof createConnectionSchema>;
|
export type CreateConnectionInput = z.infer<typeof createConnectionSchema>;
|
||||||
export type PaginationInput = z.infer<typeof paginationSchema>;
|
export type PaginationInput = z.infer<typeof paginationSchema>;
|
||||||
|
export type GetPostByIdInput = z.infer<typeof getPostByIdSchema>;
|
||||||
|
export type GetPostByTitleInput = z.infer<typeof getPostByTitleSchema>;
|
||||||
|
export type GetCommentsByPostIdInput = z.infer<
|
||||||
|
typeof getCommentsByPostIdSchema
|
||||||
|
>;
|
||||||
|
export type TogglePostLikeMutationInput = z.infer<
|
||||||
|
typeof togglePostLikeMutationSchema
|
||||||
|
>;
|
||||||
|
export type ToggleCommentReactionMutationInput = z.infer<
|
||||||
|
typeof toggleCommentReactionMutationSchema
|
||||||
|
>;
|
||||||
|
export type GetCommentReactionsQueryInput = z.infer<
|
||||||
|
typeof getCommentReactionsQuerySchema
|
||||||
|
>;
|
||||||
|
export type DeleteCommentWithTypeInput = z.infer<
|
||||||
|
typeof deleteCommentWithTypeSchema
|
||||||
|
>;
|
||||||
|
export type GetUserByIdInput = z.infer<typeof getUserByIdSchema>;
|
||||||
|
export type UpdateUserImageInput = z.infer<typeof updateUserImageSchema>;
|
||||||
|
export type UpdateUserEmailInput = z.infer<typeof updateUserEmailSchema>;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// lineage User
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string;
|
id: string;
|
||||||
email: string | null;
|
email: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user