Mutation implementations (#5)

* split up files

* timestamps, scalars and dayjs

* lib server directory

* move bun types to dev

* move storybook dark mode to dev

* got timestamps working

* fix reference

* separate schema into files and add mutations
This commit is contained in:
Baobeld 2024-12-11 15:59:02 -05:00 committed by GitHub
parent 5395e7f904
commit 37d901a86c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 321 additions and 80 deletions

View file

@ -1,65 +0,0 @@
import { prisma } from '$lib/prisma';
import { Context } from '$lib/yoga/context';
import SchemaBuilder from '@pothos/core';
import PrismaPlugin, { type PrismaTypesFromClient } from '@pothos/plugin-prisma';
type ContextType = ReturnType<typeof Context>;
export const builder = new SchemaBuilder<{
Context: ContextType;
PrismaTypes: PrismaTypesFromClient<typeof prisma>;
}>({
plugins: [PrismaPlugin],
prisma: {
client: prisma,
// defaults to false, uses /// comments from prisma schema as descriptions
// for object types, relations and exposed fields.
// descriptions can be omitted by setting description to false
exposeDescriptions: false,
// use where clause from prismaRelatedConnection for totalCount (defaults to true)
filterConnectionTotalCount: true,
// warn when not using a query parameter correctly
onUnusedQuery: process.env.NODE_ENV === 'production' ? null : 'warn'
}
});
const User = builder.prismaObject('User', {
fields: (t) => ({
id: t.exposeID('id'),
email: t.exposeString('email'),
name: t.exposeString('name'),
posts: t.relation('posts')
})
});
const Post = builder.prismaObject('Post', {
fields: (t) => ({
id: t.exposeID('id'),
title: t.exposeString('title'),
content: t.exposeString('content'),
published: t.exposeBoolean('published'),
author: t.relation('author')
})
});
builder.queryType({
fields: (t) => ({
version: t.string({
resolve: (parent, args, context) => context.config.app_version
}),
users: t.prismaField({
type: [User],
resolve: async () => {
return await prisma.user.findMany();
}
}),
posts: t.prismaField({
type: [Post],
resolve: async () => {
return await prisma.post.findMany();
}
})
})
});
export const Schema = builder.toSchema();

View file

@ -1,4 +1,4 @@
import { logger } from '$lib/logger';
import { logger } from '$lib/server/logger';
import { z } from 'zod';
export interface Configuration {

View file

@ -0,0 +1,28 @@
import { prisma } from '$lib/server/prisma';
import type { Context } from '$lib/server/yoga';
import SchemaBuilder from '@pothos/core';
import PrismaPlugin, { type PrismaTypesFromClient } from '@pothos/plugin-prisma';
import type { Scalars } from './schema/Scalars';
type PothosType = {
Context: ReturnType<typeof Context>;
PrismaTypes: PrismaTypesFromClient<typeof prisma>;
Scalars: Scalars;
};
SchemaBuilder.allowPluginReRegistration = true;
export const builder = new SchemaBuilder<PothosType>({
plugins: [PrismaPlugin],
prisma: {
client: prisma,
// defaults to false, uses /// comments from prisma schema as descriptions
// for object types, relations and exposed fields.
// descriptions can be omitted by setting description to false
exposeDescriptions: false,
// use where clause from prismaRelatedConnection for totalCount (defaults to true)
filterConnectionTotalCount: true,
// warn when not using a query parameter correctly
onUnusedQuery: process.env.NODE_ENV === 'production' ? null : 'warn'
}
});

View file

@ -0,0 +1 @@
export * from './schema';

View file

@ -0,0 +1,14 @@
import { builder } from '../../builder';
export const DateScalar = builder.scalarType('Date', {
description: 'Date Scalar in ISO format',
serialize: (date) => {
return date.toISOString();
},
parseValue: (date) => {
if (typeof date !== 'string') {
throw new Error('Cyka blyat');
}
return new Date(date);
}
});

View file

@ -0,0 +1,8 @@
export * from './Date';
export type Scalars = {
Date: {
Input: Date;
Output: Date;
};
};

View file

@ -0,0 +1,18 @@
import { builder } from '../builder';
builder.queryType({});
builder.queryField('version', (t) =>
t.string({
description: 'Application version',
resolve: (parent, args, context) => context.config.app_version
})
);
builder.mutationType({});
import './Scalars';
import './posts';
import './users';
export const Schema = builder.toSchema();

View file

@ -0,0 +1,110 @@
import { prisma } from '$lib/server/prisma';
import { builder } from '../builder';
export const Post = builder.prismaObject('Post', {
fields: (t) => ({
id: t.exposeID('id'),
title: t.exposeString('title'),
content: t.exposeString('content'),
published: t.exposeBoolean('published'),
author: t.relation('author'),
createdAt: t.expose('createdAt', {
type: 'Date'
}),
updatedAt: t.expose('updatedAt', {
type: 'Date'
})
})
});
const CreatePost = builder.inputType('CreatePost', {
fields: (t) => ({
title: t.string({
required: true
}),
content: t.string({
required: true
}),
published: t.boolean(),
authorId: t.id({
required: true
})
})
});
const UpdatePost = builder.inputType('UpdatePost', {
fields: (t) => ({
id: t.id({
required: true
}),
title: t.string(),
content: t.string(),
published: t.boolean(),
authorId: t.id()
})
});
builder.queryFields((t) => ({
posts: t.prismaField({
type: [Post],
resolve: async () => {
return await prisma.post.findMany();
}
})
}));
builder.mutationFields((t) => ({
createPost: t.field({
type: Post,
args: {
input: t.arg({ required: true, type: CreatePost })
},
resolve: async (parent, args) => {
const author = await prisma.user.findUnique({
where: { id: Number(args.input.authorId) }
});
if (!author) {
throw new Error('Author does not exist!');
}
const post = await prisma.post.create({
data: {
title: args.input.title,
content: args.input.content,
published: args.input.published,
author: {
connect: {
id: author.id
}
}
}
});
return post;
}
}),
updatePost: t.field({
type: Post,
args: {
input: t.arg({ required: true, type: UpdatePost })
},
resolve: async (parent, args) => {
const post = await prisma.post.update({
where: {
id: Number(args.input.id)
},
data: {
title: args.input.title ?? undefined,
content: args.input.content ?? undefined,
published: args.input.published,
...(args.input.authorId && {
author: {
connect: {
id: Number(args.input.authorId)
}
}
})
}
});
return post;
}
})
}));

View file

@ -0,0 +1,83 @@
import { prisma } from '$lib/server/prisma';
import { builder } from '../builder';
export const User = builder.prismaObject('User', {
fields: (t) => ({
id: t.exposeID('id'),
email: t.exposeString('email'),
name: t.exposeString('name'),
posts: t.relation('posts'),
createdAt: t.expose('createdAt', {
type: 'Date'
}),
updatedAt: t.expose('updatedAt', {
type: 'Date'
})
})
});
const CreateUser = builder.inputType('CreateUser', {
fields: (t) => ({
email: t.string({
required: true
}),
name: t.string({
required: true
})
})
});
const UpdateUser = builder.inputType('UpdateUser', {
fields: (t) => ({
id: t.id({
required: true
}),
email: t.string(),
name: t.string()
})
});
builder.queryFields((t) => ({
users: t.prismaField({
type: [User],
resolve: async () => {
return await prisma.user.findMany();
}
})
}));
builder.mutationFields((t) => ({
createUser: t.field({
type: User,
args: {
input: t.arg({ required: true, type: CreateUser })
},
resolve: async (parent, args) => {
const post = await prisma.user.create({
data: {
email: args.input.email,
name: args.input.name
}
});
return post;
}
}),
updateUser: t.field({
type: User,
args: {
input: t.arg({ required: true, type: UpdateUser })
},
resolve: async (parent, args) => {
const post = await prisma.user.update({
where: {
id: Number(args.input.id)
},
data: {
email: args.input.email,
name: args.input.name ?? undefined
}
});
return post;
}
})
}));

View file

@ -1,4 +1,4 @@
import { Config } from '$lib/config';
import { Config } from '$lib/server/config';
import type { YogaInitialContext } from 'graphql-yoga';
export const Context = (initialContext: YogaInitialContext) => ({

View file

@ -0,0 +1,2 @@
export * from './context';
export * from './server';

View file

@ -1,5 +1,5 @@
import { yogaLogger } from '$lib/logger';
import { Schema } from '$lib/pothos';
import { yogaLogger } from '$lib/server/logger';
import { Schema } from '$lib/server/pothos';
import type { RequestEvent } from '@sveltejs/kit';
import { createYoga } from 'graphql-yoga';
import { Context } from './context';