Skip to content

Commit 19306a0

Browse files
authored
Merge pull request #23 from XKCDY/feat-kysely
2 parents 3418595 + 9e3e76d commit 19306a0

File tree

28 files changed

+2059
-2766
lines changed

28 files changed

+2059
-2766
lines changed

.github/workflows/lint.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,12 @@ jobs:
66
lint:
77
runs-on: ubuntu-latest
88
steps:
9-
- uses: actions/checkout@v1
9+
- uses: actions/checkout@v2
1010

11-
- name: Get yarn cache directory path
12-
id: yarn-cache-dir-path
13-
run: echo "::set-output name=dir::$(yarn cache dir)"
14-
15-
- name: Cache yarn dependencies
16-
uses: actions/cache@v2
17-
id: yarn-cache
11+
- uses: actions/setup-node@v3
1812
with:
19-
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
20-
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
21-
restore-keys: |
22-
${{ runner.os }}-yarn-
13+
node-version: 16
14+
cache: yarn
2315

2416
- name: Install dependencies
2517
run: yarn install

package.json

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,28 @@
2121
"lint:fix": "xo --fix",
2222
"test": "lint",
2323
"migrations:generate": "prisma migrate dev --preview-feature",
24-
"migrations:run": "prisma migrate deploy --preview-feature"
24+
"migrations:run": "prisma migrate deploy --preview-feature",
25+
"generate-typings": "kysely-codegen --out-file ./src/types/db.d.ts"
2526
},
2627
"devDependencies": {
2728
"@nestjs/cli": "^7.5.6",
2829
"@types/cors": "^2.8.6",
2930
"@types/morgan": "^1.9.1",
30-
"@types/node": "^14.0.14",
31+
"@types/node": "^16.0.0",
32+
"@types/pg": "8.6.5",
3133
"@types/probe-image-size": "^5.0.1",
3234
"@types/uuid": "^8.0.0",
3335
"@types/validator": "^13.1.0",
3436
"@typescript-eslint/eslint-plugin": "^4.19.0",
3537
"@typescript-eslint/parser": "^4.19.0",
3638
"eslint": "^7.22.0",
3739
"husky": "^4.2.5",
40+
"kysely-codegen": "0.5.3",
3841
"lint-staged": "^10.5.3",
39-
"prisma": "4.0.0",
42+
"prisma": "4.3.1",
4043
"rimraf": "^3.0.2",
41-
"typescript": "^4.2.3",
42-
"xo": "^0.38.2"
44+
"typescript": "^4.8.2",
45+
"xo": "^0.52.3"
4346
},
4447
"xo": {
4548
"ignore": [
@@ -51,7 +54,13 @@
5154
{
5255
"capIsNewExceptionPattern": "@*"
5356
}
54-
]
57+
],
58+
"n/prefer-global/process": "off",
59+
"n/prefer-global/buffer": "off",
60+
"import/extensions": "off",
61+
"@typescript-eslint/naming-convention": "off",
62+
"unicorn/prefer-module": "off",
63+
"@typescript-eslint/comma-dangle": "off"
5564
}
5665
},
5766
"husky": {
@@ -66,13 +75,14 @@
6675
},
6776
"dependencies": {
6877
"@codetheweb/nestjs-bull": "^0.3.1",
69-
"@nestjs/common": "^7.6.15",
78+
"@fastify/static": "6.5.0",
79+
"@nestjs/common": "^9.0.11",
7080
"@nestjs/config": "^0.6.3",
71-
"@nestjs/core": "^7.6.15",
72-
"@nestjs/platform-fastify": "^7.6.15",
73-
"@nestjs/serve-static": "^2.1.4",
74-
"@nestjs/swagger": "^4.8.0",
75-
"@prisma/client": "4.0.0",
81+
"@nestjs/core": "^9.0.11",
82+
"@nestjs/platform-fastify": "^9.0.11",
83+
"@nestjs/serve-static": "^3.0.0",
84+
"@nestjs/swagger": "^6.1.2",
85+
"@prisma/client": "4.3.1",
7686
"apn": "^2.2.0",
7787
"bullmq": "^1.15.1",
7888
"class-transformer": "^0.4.0",
@@ -81,10 +91,13 @@
8191
"dd-trace": "^0.31.1",
8292
"dotenv": "^8.2.0",
8393
"exifr": "^5.0.3",
84-
"fastify-swagger": "^4.4.2",
94+
"fastify": "4.5.3",
95+
"fastify-swagger": "^5.2.0",
8596
"got": "^11.3.0",
8697
"ioredis": "^4.24.3",
98+
"kysely": "0.21.6",
8799
"p-limit": "^3.0.2",
100+
"pg": "8.7.3",
88101
"probe-image-size": "^5.0.0",
89102
"reflect-metadata": "^0.1.13",
90103
"rxjs": "^6.6.6",
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[comic_id,size]` on the table `comic_imgs` will be added. If there are existing duplicate values, this will fail.
5+
6+
*/
7+
-- DropForeignKey
8+
ALTER TABLE "comic_imgs" DROP CONSTRAINT "comic_imgs_comic_id_fkey";
9+
10+
-- CreateIndex
11+
CREATE UNIQUE INDEX "comic_imgs_comic_id_size_key" ON "comic_imgs"("comic_id", "size");
12+
13+
-- AddForeignKey
14+
ALTER TABLE "comic_imgs" ADD CONSTRAINT "comic_imgs_comic_id_fkey" FOREIGN KEY ("comic_id") REFERENCES "comics"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[token]` on the table `device_tokens` will be added. If there are existing duplicate values, this will fail.
5+
6+
*/
7+
-- CreateIndex
8+
CREATE UNIQUE INDEX "device_tokens_token_key" ON "device_tokens"("token");

prisma/schema.prisma

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ model ComicImg {
1919
comics Comic @relation(fields: [comic_id], references: [id])
2020
2121
@@index([comic_id], name: "comic_imgs_comic_id")
22+
@@unique([comic_id, size])
2223
}
2324

2425
model Comic {
@@ -38,7 +39,7 @@ model Comic {
3839

3940
model DeviceToken {
4041
@@map("device_tokens")
41-
token String @id @db.VarChar(255)
42+
token String @id @db.VarChar(255) @unique
4243
version String? @db.VarChar(255)
4344
lastComicIdSent Int
4445
createdAt DateTime @db.Timestamptz(6) @default(now())

src/app.module.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
1+
import {join} from 'node:path';
12
import {Module} from '@nestjs/common';
23
import {ConfigModule} from '@nestjs/config';
34
import {BullModule} from '@codetheweb/nestjs-bull';
45
import {ServeStaticModule} from '@nestjs/serve-static';
5-
import {join} from 'path';
66
import Redis from 'ioredis';
77
import {ComicModule} from './comic/comic.module';
88
import {DeviceTokenModule} from './device-token/device-token.module';
99

10-
const redisConnection = process.env.REDIS_URL ? new Redis(process.env.REDIS_URL) : {
11-
port: Number.parseInt(process.env.REDIS_PORT!, 10),
12-
host: process.env.REDIS_HOST
13-
};
14-
1510
@Module({
1611
imports: [
1712
ConfigModule.forRoot(),
1813
BullModule.forRoot({
19-
connection: redisConnection
14+
connection: process.env.REDIS_URL ? new Redis(process.env.REDIS_URL) : {
15+
port: Number.parseInt(process.env.REDIS_PORT!, 10),
16+
host: process.env.REDIS_HOST,
17+
},
2018
}),
2119
ServeStaticModule.forRoot({
2220
rootPath: join(__dirname, '..', 'public'),
23-
serveRoot: '/static'
21+
serveRoot: '/static',
2422
}),
2523
ComicModule,
26-
DeviceTokenModule
24+
DeviceTokenModule,
2725
],
2826
controllers: [],
29-
providers: []
27+
providers: [],
3028
})
3129
export class AppModule {}

src/comic/comic.controller.ts

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,47 @@
1-
import {Controller, Get, Header, Injectable, InternalServerErrorException, NotFoundException, Param, Query} from '@nestjs/common';
2-
import {Prisma} from '@prisma/client';
3-
import {PrismaService} from 'src/prisma/prisma.service';
1+
import {Controller, Get, Header, Injectable, NotFoundException, Param, Query} from '@nestjs/common';
2+
import {sql} from 'kysely';
3+
import {DbService} from 'src/db/db.service';
44
import {GetAllComicsParameters} from './types';
55

6-
const findManyOptions: Prisma.ComicFindManyArgs = {
7-
include: {
8-
imgs: {
9-
select: {
10-
height: true,
11-
width: true,
12-
ratio: true,
13-
sourceUrl: true,
14-
size: true
15-
}
16-
}
17-
},
18-
orderBy: {
19-
id: 'asc'
20-
}
21-
};
6+
const getBaseQuery = (db: DbService) => db
7+
.selectFrom('comics')
8+
.innerJoin('comic_imgs', 'comic_imgs.comic_id', 'comics.id')
9+
.selectAll('comics')
10+
.select([sql`json_agg(json_build_object('width', width, 'height', height, 'ratio', ratio, 'sourceUrl', comic_imgs."sourceUrl", 'size', size))`.as('imgs')])
11+
.groupBy('comics.id');
2212

2313
@Controller('comics')
2414
@Injectable()
2515
export class ComicController {
26-
constructor(private readonly prisma: PrismaService) {}
16+
constructor(private readonly db: DbService) {}
2717

2818
@Get()
2919
@Header('Cache-Control', 'max-age=300')
3020
async getAllComics(@Query() parameters?: GetAllComicsParameters) {
31-
if (typeof parameters?.since === 'number') {
32-
return this.prisma.comic.findMany({
33-
...findManyOptions,
34-
where: {
35-
id: {
36-
gt: parameters.since
37-
}
38-
}
39-
});
40-
}
41-
42-
return this.prisma.comic.findMany(findManyOptions);
21+
return getBaseQuery(this.db)
22+
.orderBy('comics.id', 'asc')
23+
.where('comics.id', '>', parameters?.since ?? 0)
24+
.execute();
4325
}
4426

4527
@Get('/latest')
4628
@Header('Cache-Control', 'max-age=300')
4729
async getLatestComic() {
48-
const comic = await this.prisma.comic.findFirst({...findManyOptions, orderBy: {
49-
id: 'desc'
50-
}});
30+
const comic = await getBaseQuery(this.db).orderBy('comics.id', 'desc').executeTakeFirst();
5131

5232
if (comic) {
5333
return comic;
5434
}
5535

56-
throw new InternalServerErrorException('No comics');
36+
throw new NotFoundException('No comics');
5737
}
5838

5939
@Get(':comicId')
6040
@Header('Cache-Control', 'max-age=300')
6141
async getComic(@Param('comicId') comicId: string) {
6242
const id = Number.parseInt(comicId, 10);
6343

64-
const comic = await this.prisma.comic.findUnique({
65-
include: findManyOptions.include,
66-
where: {id}
67-
});
44+
const comic = await getBaseQuery(this.db).where('comics.id', '=', id).executeTakeFirst();
6845

6946
if (!comic) {
7047
throw new NotFoundException(`${id} not found`);

src/comic/comic.module.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
import {join} from 'node:path';
12
import {BullModule} from '@codetheweb/nestjs-bull';
23
import {Module} from '@nestjs/common';
3-
import {join} from 'path';
4-
import {PrismaModule} from 'src/prisma/prisma.module';
4+
import {DbModule} from 'src/db/db.module';
55
import {ComicController} from './comic.controller';
66
import {ComicService} from './comic.service';
77

88
@Module({
99
imports: [
10-
PrismaModule,
10+
DbModule,
1111
BullModule.registerQueue({
1212
name: 'scrape-comics',
1313
processors: [join(__dirname, 'processors/scrape-comics.js')]

src/comic/comic.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {Injectable, OnModuleInit} from '@nestjs/common';
1+
import type {OnModuleInit} from '@nestjs/common';
2+
import {Injectable} from '@nestjs/common';
23
import {InjectQueue} from '@codetheweb/nestjs-bull';
34
import {Queue} from 'bullmq';
45

0 commit comments

Comments
 (0)