diff --git a/prisma/dev.db b/prisma/dev.db index 14dfc11..7886134 100644 Binary files a/prisma/dev.db and b/prisma/dev.db differ diff --git a/prisma/dev.db-journal b/prisma/dev.db-journal deleted file mode 100644 index be0024e..0000000 Binary files a/prisma/dev.db-journal and /dev/null differ diff --git a/prisma/migrations/20241211200947_add_timestamps/migration.sql b/prisma/migrations/20241211200947_add_timestamps/migration.sql new file mode 100644 index 0000000..d4aa687 --- /dev/null +++ b/prisma/migrations/20241211200947_add_timestamps/migration.sql @@ -0,0 +1,37 @@ +/* + Warnings: + + - Made the column `content` on table `Post` required. This step will fail if there are existing NULL values in that column. + - Made the column `name` on table `User` required. This step will fail if there are existing NULL values in that column. + +*/ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Post" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "published" BOOLEAN DEFAULT false, + "authorId" INTEGER NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); +INSERT INTO "new_Post" ("authorId", "content", "id", "published", "title") SELECT "authorId", "content", "id", "published", "title" FROM "Post"; +DROP TABLE "Post"; +ALTER TABLE "new_Post" RENAME TO "Post"; +CREATE TABLE "new_User" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT, + "name" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP +); +INSERT INTO "new_User" ("email", "id", "name") SELECT "email", "id", "name" FROM "User"; +DROP TABLE "User"; +ALTER TABLE "new_User" RENAME TO "User"; +CREATE UNIQUE INDEX "User_id_key" ON "User"("id"); +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8160664..c2faf75 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,9 +15,9 @@ datasource db { } model User { - id Int @id @default(autoincrement()) - email String @unique - name String? + id Int @id @default(autoincrement()) @unique + email String? @unique + name String posts Post[] createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt @@ -26,8 +26,8 @@ model User { model Post { id Int @id @default(autoincrement()) title String - content String? - published Boolean @default(false) + content String + published Boolean? @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int createdAt DateTime @default(now()) diff --git a/src/lib/server/pothos/builder.ts b/src/lib/server/pothos/builder.ts index fe450fa..0b7fda4 100644 --- a/src/lib/server/pothos/builder.ts +++ b/src/lib/server/pothos/builder.ts @@ -2,7 +2,7 @@ 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 './Scalars'; +import type { Scalars } from './schema/Scalars'; type PothosType = { Context: ReturnType; @@ -10,6 +10,8 @@ type PothosType = { Scalars: Scalars; }; +SchemaBuilder.allowPluginReRegistration = true; + export const builder = new SchemaBuilder({ plugins: [PrismaPlugin], prisma: { diff --git a/src/lib/server/pothos/index.ts b/src/lib/server/pothos/index.ts index d6bd62d..5d5aa13 100644 --- a/src/lib/server/pothos/index.ts +++ b/src/lib/server/pothos/index.ts @@ -1,3 +1 @@ -import { builder } from './builder'; - -export const Schema = builder.toSchema(); \ No newline at end of file +export * from './schema'; \ No newline at end of file diff --git a/src/lib/server/pothos/schema.ts b/src/lib/server/pothos/schema.ts deleted file mode 100644 index 0789677..0000000 --- a/src/lib/server/pothos/schema.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { prisma } from '$lib/server/prisma'; -import { builder } from './builder'; - -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 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' - }) - }) -}); - -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(); - } - }) - }) -}); \ No newline at end of file diff --git a/src/lib/server/pothos/Scalars/Date.ts b/src/lib/server/pothos/schema/Scalars/Date.ts similarity index 87% rename from src/lib/server/pothos/Scalars/Date.ts rename to src/lib/server/pothos/schema/Scalars/Date.ts index 6d61571..6573f0a 100644 --- a/src/lib/server/pothos/Scalars/Date.ts +++ b/src/lib/server/pothos/schema/Scalars/Date.ts @@ -1,4 +1,4 @@ -import { builder } from '../builder'; +import { builder } from '../../builder'; export const DateScalar = builder.scalarType('Date', { description: 'Date Scalar in ISO format', diff --git a/src/lib/server/pothos/Scalars/index.ts b/src/lib/server/pothos/schema/Scalars/index.ts similarity index 100% rename from src/lib/server/pothos/Scalars/index.ts rename to src/lib/server/pothos/schema/Scalars/index.ts diff --git a/src/lib/server/pothos/schema/index.ts b/src/lib/server/pothos/schema/index.ts new file mode 100644 index 0000000..acdab44 --- /dev/null +++ b/src/lib/server/pothos/schema/index.ts @@ -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(); \ No newline at end of file diff --git a/src/lib/server/pothos/schema/posts.ts b/src/lib/server/pothos/schema/posts.ts new file mode 100644 index 0000000..f616871 --- /dev/null +++ b/src/lib/server/pothos/schema/posts.ts @@ -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; + } + }) +})); \ No newline at end of file diff --git a/src/lib/server/pothos/schema/users.ts b/src/lib/server/pothos/schema/users.ts new file mode 100644 index 0000000..c15b8bb --- /dev/null +++ b/src/lib/server/pothos/schema/users.ts @@ -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; + } + }) +})); \ No newline at end of file