diff --git a/packages/worker/package.json b/packages/worker/package.json index d71de87d..318333db 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -13,9 +13,7 @@ }, "dependencies": { "animegarden": "workspace:*", - "itty-router": "^3.0.12", - "kysely": "^0.24.2", - "kysely-d1": "^0.3.0" + "itty-router": "^3.0.12" }, "devDependencies": { "@prisma/client": "^4.12.0", diff --git a/packages/worker/prisma/migrations/20230409071929_resource_relation/migration.sql b/packages/worker/prisma/migrations/20230409071929_resource_relation/migration.sql new file mode 100644 index 00000000..041e019e --- /dev/null +++ b/packages/worker/prisma/migrations/20230409071929_resource_relation/migration.sql @@ -0,0 +1,25 @@ +/* + Warnings: + + - You are about to drop the column `teamId` on the `Resource` table. All the data in the column will be lost. + - You are about to drop the column `userId` on the `Resource` table. All the data in the column will be lost. + - Added the required column `publisherId` to the `Resource` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE `Resource` DROP FOREIGN KEY `Resource_teamId_fkey`; + +-- DropForeignKey +ALTER TABLE `Resource` DROP FOREIGN KEY `Resource_userId_fkey`; + +-- AlterTable +ALTER TABLE `Resource` DROP COLUMN `teamId`, + DROP COLUMN `userId`, + ADD COLUMN `fansubId` INTEGER NULL, + ADD COLUMN `publisherId` INTEGER NOT NULL; + +-- AddForeignKey +ALTER TABLE `Resource` ADD CONSTRAINT `Resource_fansubId_fkey` FOREIGN KEY (`fansubId`) REFERENCES `Team`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `Resource` ADD CONSTRAINT `Resource_publisherId_fkey` FOREIGN KEY (`publisherId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/packages/worker/prisma/schema.prisma b/packages/worker/prisma/schema.prisma index deeac407..0779b463 100644 --- a/packages/worker/prisma/schema.prisma +++ b/packages/worker/prisma/schema.prisma @@ -21,14 +21,14 @@ model User { } model Resource { - title String - href String @id - type String - magnet String - size String - teamId Int - userId Int - fansub Team? @relation(fields: [teamId], references: [id]) - publisher User @relation(fields: [userId], references: [id]) - createdAt Int + title String + href String @id + type String + magnet String + size String + fansubId Int? + publisherId Int + fansub Team? @relation(fields: [fansubId], references: [id]) + publisher User @relation(fields: [publisherId], references: [id]) + createdAt Int } diff --git a/packages/worker/src/database.ts b/packages/worker/src/database.ts deleted file mode 100644 index b2418a2f..00000000 --- a/packages/worker/src/database.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Kysely } from 'kysely'; -import { D1Dialect } from 'kysely-d1'; - -import type { Database } from './types'; - -export function makeDatabase(d1: D1Database) { - return new Kysely({ dialect: new D1Dialect({ database: d1 }) }); -} diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index 21523ea6..51453022 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -1,62 +1,53 @@ import { Router } from 'itty-router'; +import { PrismaClient } from '@prisma/client/edge'; import type { Env } from './types'; -import { makeDatabase } from './database'; import { handleScheduled } from './scheduled'; +const prisma = new PrismaClient(); + const router = Router(); router.get('/', () => makeResponse({ message: 'This is AnimeGarden' })); router.get('/resources', async (request, env: Env) => { - const database = makeDatabase(env.database); - const params = resolveParams(); if (!params) { return makeErrorResponse({ message: 'Request is not valid' }); } const { page, pageSize } = params; - const sql = database - .selectFrom('resource') - .innerJoin('user', 'user.id', 'resource.publisher') - .leftJoin('team', 'team.id', 'resource.fansub') - .select([ - 'title', - 'href', - 'type', - 'magnet', - 'size', - 'user.id as publisher_id', - 'user.name as publisher_name', - 'team.id as fansub_id', - 'team.name as fansub_name', - 'createdAt' - ]) - .offset((page - 1) * pageSize) - .limit(pageSize) - .orderBy('createdAt', 'desc'); - - const resources = (await sql.execute()).map((r) => ({ + const plan = await prisma.resource.findMany({ + skip: (page - 1) * pageSize, + take: pageSize, + orderBy: { + createdAt: 'desc' + }, + include: { + fansub: true, + publisher: true + } + }); + + const resources = plan.map((r) => ({ title: r.title, href: r.href, type: r.type, magnet: r.magnet, size: r.size, createdAt: new Date(r.createdAt), - fansub: - r.fansub_id && r.fansub_name - ? { - id: r.fansub_id, - name: r.fansub_name, - href: `https://share.dmhy.org/topics/list/team_id/${r.fansub_id}` - } - : undefined, + fansub: r.fansub + ? { + id: r.fansub.id, + name: r.fansub.name, + href: `https://share.dmhy.org/topics/list/team_id/${r.fansub.id}` + } + : undefined, publisher: { - id: r.publisher_id, - name: r.publisher_name, - href: `https://share.dmhy.org/topics/list/user_id/${r.publisher_id}` + id: r.publisher.id, + name: r.publisher.name, + href: `https://share.dmhy.org/topics/list/user_id/${r.publisher.id}` } })); @@ -83,14 +74,12 @@ router.put('/resources', async (request, env: Env) => { }); router.get('/users', async (request, env: Env) => { - const database = makeDatabase(env.database); - const users = await database.selectFrom('user').selectAll().execute(); + const users = await prisma.user.findMany(); return makeResponse({ users }); }); router.get('/teams', async (request, env: Env) => { - const database = makeDatabase(env.database); - const teams = await database.selectFrom('team').selectAll().execute(); + const teams = await prisma.team.findMany(); return makeResponse({ teams }); }); diff --git a/packages/worker/src/scheduled.ts b/packages/worker/src/scheduled.ts index 7a511cf3..a25065b0 100644 --- a/packages/worker/src/scheduled.ts +++ b/packages/worker/src/scheduled.ts @@ -1,10 +1,11 @@ -import { makeDatabase } from './database'; import type { Env } from './types'; import { fetchPage } from 'animegarden'; +import { PrismaClient } from '@prisma/client/edge'; + +const prisma = new PrismaClient(); export async function handleScheduled(env: Env) { - const database = makeDatabase(env.database); const teams = new Set(); const users = new Set(); @@ -14,61 +15,58 @@ export async function handleScheduled(env: Env) { // Check teams and users for (const r of res) { if (!users.has(+r.publisher.id)) { - const u = await database - .selectFrom('user') - .selectAll() - .where('id', '=', +r.publisher.id) - .executeTakeFirst(); + const u = await prisma.user.findUnique({ + where: { + id: +r.publisher.id + } + }); if (u) { users.add(u.id); } else { - await database - .insertInto('user') - .values({ id: +r.publisher.id, name: r.publisher.name }) - .executeTakeFirst(); + await prisma.user.create({ + data: { + id: +r.publisher.id, + name: r.publisher.name + } + }); users.add(+r.publisher.id); } } if (r.fansub && !teams.has(+r.fansub.id)) { - const u = await database - .selectFrom('team') - .selectAll() - .where('id', '=', +r.fansub.id) - .executeTakeFirst(); + const u = await prisma.team.findUnique({ + where: { + id: +r.fansub.id + } + }); if (u) { teams.add(u.id); } else { - await database - .insertInto('team') - .values({ id: +r.fansub.id, name: r.fansub.name }) - .executeTakeFirst(); + await prisma.team.create({ + data: { + id: +r.fansub.id, + name: r.fansub.name + } + }); teams.add(+r.fansub.id); } } } - const query = database - .insertInto('resource') - .values( - res.map((r) => ({ - title: r.title, - href: r.href, - type: r.type, - magnet: r.magnet, - size: r.size, - // Convert to UTC+8 - createdAt: new Date(r.createdAt).getTime() - 8 * 60 * 60 * 1000, - fansub: r.fansub ? +r.fansub.id : undefined, - publisher: +r.publisher.id - })) - ) - .onConflict((oc) => oc.doNothing()); - const insert = await query.execute(); - const inserted = insert.reduce((acc, r) => acc + (r.numInsertedOrUpdatedRows ?? 0n), 0n); - if (inserted === 0n) { - break; - } + const { count } = await prisma.resource.createMany({ + data: res.map((r) => ({ + title: r.title, + href: r.href, + type: r.type, + magnet: r.magnet, + size: r.size, + // Convert to UTC+8 + createdAt: new Date(r.createdAt).getTime() - 8 * 60 * 60 * 1000, + fansubId: r.fansub ? +r.fansub.id : undefined, + publisherId: +r.publisher.id + })), + skipDuplicates: true + }); - console.log(`There are ${inserted} resources inserted`); + console.log(`There are ${count} resources inserted`); } } diff --git a/packages/worker/src/types.ts b/packages/worker/src/types.ts index e6d7cac0..a53ff52e 100644 --- a/packages/worker/src/types.ts +++ b/packages/worker/src/types.ts @@ -1,41 +1,3 @@ export interface Env { database: D1Database; } - -export interface TeamTable { - id: number; - - name: string; -} - -export interface UserTable { - id: number; - - name: string; -} - -export interface ResourceTable { - title: string; - - href: string; - - type: string; - - magnet: string; - - size: string; - - fansub?: number; - - publisher: number; - - createdAt: number; -} - -export interface Database { - user: UserTable; - - team: TeamTable; - - resource: ResourceTable; -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b9dbdc3..1d814e71 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,12 +87,6 @@ importers: itty-router: specifier: ^3.0.12 version: 3.0.12 - kysely: - specifier: ^0.24.2 - version: 0.24.2 - kysely-d1: - specifier: ^0.3.0 - version: 0.3.0(kysely@0.24.2) devDependencies: '@prisma/client': specifier: ^4.12.0 @@ -2848,19 +2842,6 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} - /kysely-d1@0.3.0(kysely@0.24.2): - resolution: {integrity: sha512-9wTbE6ooLiYtBa4wPg9e4fjfcmvRtgE/2j9pAjYrIq+iz+EsH/Hj9YbtxpEXA6JoRgfulVQ1EtGj6aycGGRpYw==} - peerDependencies: - kysely: '*' - dependencies: - kysely: 0.24.2 - dev: false - - /kysely@0.24.2: - resolution: {integrity: sha512-+7eaTJNUYm2yRq1x+lEOZc+78TO35dTZ9b0dh49+Z9CTt2byMSbMiOKpwPlOyCAaHD4kILkAYWYZNywFlmBwRA==} - engines: {node: '>=14.0.0'} - dev: false - /load-yaml-file@0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'}