From 9b3db4923c88a62ce46419b34df081243353e457 Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Sat, 19 Aug 2023 17:04:31 +0700 Subject: [PATCH 1/6] migrate to postgres --- .env.example | 2 +- .env.production.gpg | Bin 523 -> 574 bytes .env.test.gpg | 3 ++ .github/workflows/ci.yml | 7 ++- .gitignore | 2 +- controllers/shorten.ts | 6 ++- jest.config.js | 12 +++-- package.json | 1 + .../migration.sql | 37 --------------- .../20230313094039_unique_meta/migration.sql | 8 ---- .../migration.sql | 3 -- .../migration.sql | 19 -------- .../migration.sql | 44 ++++++++++++++++++ prisma/migrations/migration_lock.toml | 2 +- prisma/schema.prisma | 2 +- redis/client.ts | 3 +- scripts/encrypt_secret.sh | 2 + test/shorten.test.ts | 4 +- types/constants.ts | 1 + utils/axios.ts | 5 +- 20 files changed, 80 insertions(+), 83 deletions(-) create mode 100644 .env.test.gpg delete mode 100644 prisma/migrations/20230313040231_initial_migration/migration.sql delete mode 100644 prisma/migrations/20230313094039_unique_meta/migration.sql delete mode 100644 prisma/migrations/20230318094918_feature_password/migration.sql delete mode 100644 prisma/migrations/20230320084352_delete_cascade_meta/migration.sql create mode 100644 prisma/migrations/20230819040604_init_migration/migration.sql create mode 100644 scripts/encrypt_secret.sh diff --git a/.env.example b/.env.example index 549926c1..06d71def 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -DATABASE_URL="file:./dev.db" +DATABASE_URL="postgres://" REDIS_AUTH="xxxxxx" # NEXT_PUBLIC_MIX_PANEL_TOKEN="xxxxxx" NEXT_PUBLIC_PLATFORM_AUTH="xxxxxx" diff --git a/.env.production.gpg b/.env.production.gpg index 3a3fd1d16e24d5683cfa13bd3df9b13fab380d66..e7edb2aa801a27ebb36def03e5120e47bf7cb95a 100644 GIT binary patch literal 574 zcmV-E0>S-^4Fm}T0v4pl?=|9X;cW1 zo~QQnh4H=0+c{M3^Lh}h7aKaH4Tf9cU{&E0tBxb8IUjN@kC(6D+xx>4x(y4~yQ@3o zTT=S@*#0%Tt{F_DlFARoH5$&7Q51hy;lN%ql_#hjhv9o5$1Ti{f@Eu4o_ys{1%Mv0 ztlWk{DPP5Sxng!Go`Qf|4+>8HQ@m^D)|6TmNW*P6K3||ZJ&M(p|Nlp}vnBH0j~Ng& zvf8}?GF4nJ@9j?daZ8`N)+L|JLxW#wl6rAquuiRx^4AizrRi+XZn!VerJSCF6NXph zPCe-AK3>p%9*4X4v_pUojHg;ooc6>JC}c@f5PvmfvujV_Vt|U z(kyj&)$J;O!(PN9v&89wul!BgX+4btidl~gi*`-63%h7UuBbJ;y|Cj$mBmCOuqNK$ zTgL2$((Np-0h}RZZ*OqxEQxA9J9XdUc7{z|#pyv3NJLeuBT}9pC7wG9G7n~1pm^(IRQmzo0X{lqarIOs#-{3k=;TB&uLAz!5IY1 zg^=avA``8}Do;}VVzHY`4h0J-zE@|lqIC${5_l5Hn_zMD7e$~u4rQb|hZFt1HAnzx z;J7MZhkk%-Yx!gEjx^MJ@E98YbpjZ_yZg}b6^CqO40ZC|6VeU)pX2W4 zt&;zh2!sk1HFyegbAVzpkJ8t@NBEsE)7|Ss+Pj0Ig@qH+&*p}UR>XGQ4w=l9<*}iR z14crlNs}hnFwLi3wx_>f$FI}|Yai75YUUYnV7x&ffMs2eMOfqa*~ST&$?02KT?W$N zFACazYQ=k#C}hse!qm2HT(m!Y+arFu5!{O zth)+-YhI`yiA0-Tz_dIoBE^ Nn5X6!ePOioe6%W01zZ3C diff --git a/.env.test.gpg b/.env.test.gpg new file mode 100644 index 00000000..88338961 --- /dev/null +++ b/.env.test.gpg @@ -0,0 +1,3 @@ +  &Jh]Үঈ[U-OǟJ%FisObZ)sz.pU؅r{(PTnQL#bstt ]k\&6 V[w)J>(\ y'l:N.&{D +Ӷ"'#S@%6ԨZ,M5{A"Qo.ADŽ]9Í J<寡h,r~/>Xp-bgP(EZ-!TiD|g#Qڏ2DTŖ_VQ$! ^w֜NY'-Yˍ_o H( await redis.expire(hashShortenedLinkKey, LIMIT_SHORTENED_SECOND); await redis.incr(keyLimit); const keyHash = getRedisKey(REDIS_KEY.HASH_HISTORY_BY_ID, ip); + let record: UrlShortenerRecord | null = null; // retrive client id and write to db let clientRedisId = await redis.hget(keyHash, 'dbId'); if (!clientRedisId) { @@ -79,7 +81,7 @@ export const handler = api( }); if (!clientDb) { // new client's ip - let record = await prisma.urlShortenerRecord.findFirst({ + record = await prisma.urlShortenerRecord.findFirst({ where: { ip }, }); if (!record) { @@ -95,7 +97,7 @@ export const handler = api( } const dataHashClient = ['lastUrl', url, 'lastHash', targetHash, 'dbId', clientRedisId]; await redis.hset(keyHash, dataHashClient); - let record = await prisma.urlShortenerRecord.findFirst({ where: { id: +clientRedisId } }); + record = record ?? (await prisma.urlShortenerRecord.findFirst({ where: { ip } })); if (!record) record = await prisma.urlShortenerRecord.create({ data: { ip }, diff --git a/jest.config.js b/jest.config.js index 0ffe07a0..718b1da1 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,9 +3,13 @@ module.exports = { testEnvironment: 'node', testPathIgnorePatterns: ['/node_modules', '/.next'], setupFilesAfterEnv: ['./test/index.ts'], - globals: { - 'ts-jest': { - isolatedModules: true, - }, + transform: { + '^.+\\.{ts|tsx}?$': [ + 'ts-jest', + { + isolatedModules: true, + tsConfig: 'tsconfig.json', + }, + ], }, }; diff --git a/package.json b/package.json index 728b1111..b7171367 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "dev": "nodemon --exec 'next dev -p 5000'", "test": "jest --logHeapUsage --forceExit", "migrate:dev": "npx prisma migrate dev --name", + "migrate:status": "npx prisma migrate status", "build": "next build", "start": "next start", "lint": "next lint", diff --git a/prisma/migrations/20230313040231_initial_migration/migration.sql b/prisma/migrations/20230313040231_initial_migration/migration.sql deleted file mode 100644 index c8bc30e7..00000000 --- a/prisma/migrations/20230313040231_initial_migration/migration.sql +++ /dev/null @@ -1,37 +0,0 @@ --- CreateTable -CREATE TABLE "UrlShortenerRecord" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "ip" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "UrlShortenerHistory" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "url" TEXT NOT NULL, - "hash" TEXT NOT NULL, - "urlShortenerRecordId" INTEGER NOT NULL, - CONSTRAINT "UrlShortenerHistory_urlShortenerRecordId_fkey" FOREIGN KEY ("urlShortenerRecordId") REFERENCES "UrlShortenerRecord" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); - --- CreateTable -CREATE TABLE "UrlForwardMeta" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "userAgent" TEXT, - "countryCode" TEXT, - "ip" TEXT, - "fromClientSide" BOOLEAN DEFAULT false, - "urlShortenerHistoryId" INTEGER NOT NULL, - CONSTRAINT "UrlForwardMeta_urlShortenerHistoryId_fkey" FOREIGN KEY ("urlShortenerHistoryId") REFERENCES "UrlShortenerHistory" ("id") ON DELETE RESTRICT ON UPDATE CASCADE -); - --- CreateIndex -CREATE UNIQUE INDEX "UrlShortenerRecord_ip_key" ON "UrlShortenerRecord"("ip"); - --- CreateIndex -CREATE UNIQUE INDEX "UrlShortenerHistory_hash_key" ON "UrlShortenerHistory"("hash"); diff --git a/prisma/migrations/20230313094039_unique_meta/migration.sql b/prisma/migrations/20230313094039_unique_meta/migration.sql deleted file mode 100644 index 2884acec..00000000 --- a/prisma/migrations/20230313094039_unique_meta/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[userAgent,ip,urlShortenerHistoryId]` on the table `UrlForwardMeta` will be added. If there are existing duplicate values, this will fail. - -*/ --- CreateIndex -CREATE UNIQUE INDEX "UrlForwardMeta_userAgent_ip_urlShortenerHistoryId_key" ON "UrlForwardMeta"("userAgent", "ip", "urlShortenerHistoryId"); diff --git a/prisma/migrations/20230318094918_feature_password/migration.sql b/prisma/migrations/20230318094918_feature_password/migration.sql deleted file mode 100644 index afce8199..00000000 --- a/prisma/migrations/20230318094918_feature_password/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "UrlShortenerHistory" ADD COLUMN "email" TEXT; -ALTER TABLE "UrlShortenerHistory" ADD COLUMN "password" TEXT; diff --git a/prisma/migrations/20230320084352_delete_cascade_meta/migration.sql b/prisma/migrations/20230320084352_delete_cascade_meta/migration.sql deleted file mode 100644 index f37ac748..00000000 --- a/prisma/migrations/20230320084352_delete_cascade_meta/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- RedefineTables -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_UrlForwardMeta" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "userAgent" TEXT, - "countryCode" TEXT, - "ip" TEXT, - "fromClientSide" BOOLEAN DEFAULT false, - "urlShortenerHistoryId" INTEGER NOT NULL, - CONSTRAINT "UrlForwardMeta_urlShortenerHistoryId_fkey" FOREIGN KEY ("urlShortenerHistoryId") REFERENCES "UrlShortenerHistory" ("id") ON DELETE CASCADE ON UPDATE CASCADE -); -INSERT INTO "new_UrlForwardMeta" ("countryCode", "createdAt", "fromClientSide", "id", "ip", "updatedAt", "urlShortenerHistoryId", "userAgent") SELECT "countryCode", "createdAt", "fromClientSide", "id", "ip", "updatedAt", "urlShortenerHistoryId", "userAgent" FROM "UrlForwardMeta"; -DROP TABLE "UrlForwardMeta"; -ALTER TABLE "new_UrlForwardMeta" RENAME TO "UrlForwardMeta"; -CREATE UNIQUE INDEX "UrlForwardMeta_userAgent_ip_urlShortenerHistoryId_key" ON "UrlForwardMeta"("userAgent", "ip", "urlShortenerHistoryId"); -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON; diff --git a/prisma/migrations/20230819040604_init_migration/migration.sql b/prisma/migrations/20230819040604_init_migration/migration.sql new file mode 100644 index 00000000..335ac441 --- /dev/null +++ b/prisma/migrations/20230819040604_init_migration/migration.sql @@ -0,0 +1,44 @@ +-- CreateTable +CREATE TABLE "UrlShortenerRecord" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "ip" TEXT NOT NULL, + CONSTRAINT "UrlShortenerRecord_pkey" PRIMARY KEY ("id") +); +-- CreateTable +CREATE TABLE "UrlShortenerHistory" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "url" TEXT NOT NULL, + "hash" TEXT NOT NULL, + "email" TEXT, + "password" TEXT, + "urlShortenerRecordId" INTEGER NOT NULL, + CONSTRAINT "UrlShortenerHistory_pkey" PRIMARY KEY ("id") +); +-- CreateTable +CREATE TABLE "UrlForwardMeta" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userAgent" TEXT, + "countryCode" TEXT, + "ip" TEXT, + "fromClientSide" BOOLEAN DEFAULT false, + "urlShortenerHistoryId" INTEGER NOT NULL, + CONSTRAINT "UrlForwardMeta_pkey" PRIMARY KEY ("id") +); +-- CreateIndex +CREATE UNIQUE INDEX "UrlShortenerRecord_ip_key" ON "UrlShortenerRecord"("ip"); +-- CreateIndex +CREATE UNIQUE INDEX "UrlShortenerHistory_hash_key" ON "UrlShortenerHistory"("hash"); +-- CreateIndex +CREATE UNIQUE INDEX "UrlForwardMeta_userAgent_ip_urlShortenerHistoryId_key" ON "UrlForwardMeta"("userAgent", "ip", "urlShortenerHistoryId"); +-- AddForeignKey +ALTER TABLE "UrlShortenerHistory" +ADD CONSTRAINT "UrlShortenerHistory_urlShortenerRecordId_fkey" FOREIGN KEY ("urlShortenerRecordId") REFERENCES "UrlShortenerRecord"("id") ON DELETE CASCADE ON UPDATE CASCADE; +-- AddForeignKey +ALTER TABLE "UrlForwardMeta" +ADD CONSTRAINT "UrlForwardMeta_urlShortenerHistoryId_fkey" FOREIGN KEY ("urlShortenerHistoryId") REFERENCES "UrlShortenerHistory"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index e5e5c470..fbffa92c 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually # It should be added in your version-control system (i.e. Git) -provider = "sqlite" \ No newline at end of file +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3c804d89..f6516e4d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -6,7 +6,7 @@ generator client { } datasource db { - provider = "sqlite" + provider = "postgresql" url = env("DATABASE_URL") } diff --git a/redis/client.ts b/redis/client.ts index ee35cf78..7d781ee0 100644 --- a/redis/client.ts +++ b/redis/client.ts @@ -1,8 +1,7 @@ import { Redis, RedisOptions } from 'ioredis'; -import { isProduction } from '../types/constants'; const redisConfig = { - host: isProduction ? 'cache' : '127.0.0.1', + host: process.env.REDIS_HOST, password: process.env.REDIS_AUTH, port: '6379', }; diff --git a/scripts/encrypt_secret.sh b/scripts/encrypt_secret.sh new file mode 100644 index 00000000..e76dd9ca --- /dev/null +++ b/scripts/encrypt_secret.sh @@ -0,0 +1,2 @@ +gpg --symmetric --cipher-algo AES256 .env.production +gpg --symmetric --cipher-algo AES256 .env.test diff --git a/test/shorten.test.ts b/test/shorten.test.ts index 983d2cbc..ceb230f2 100644 --- a/test/shorten.test.ts +++ b/test/shorten.test.ts @@ -78,10 +78,12 @@ describe('Test /api/shorten...', () => { }); it('Should shortened URL OK', async () => { - await redis.set(key, 0); + await redis.expire(key, 0); + const { req, res } = createMocks({ method: 'GET', query: { url: 'U2FsdGVkX19lPT7tc2v+EAQ+q+S+QmgedQXJPLAhhjZDskrGAPv+kdWEm624npUtHaEGmCTcJHbFaYeZAv+FQw==' }, + headers: { 'x-forwarded-for': ip }, }); await controller.shorten.handler(req, res); expect(res._getStatusCode()).toBe(HttpStatusCode.OK); diff --git a/types/constants.ts b/types/constants.ts index 72812408..8ad06131 100644 --- a/types/constants.ts +++ b/types/constants.ts @@ -3,6 +3,7 @@ export const brandUrl = 'https://clickdi.top'; export const brandUrlShort = 'https://clid.top'; export const brandUrlShortDomain = 'clid.top'; export const isProduction = process.env.NODE_ENV === 'production'; +export const isTest = process.env.NODE_ENV === 'test'; export const cdnUrl = 'https://cdn.jsdelivr.net/gh/thanhdanh27600/clickdi@production/public'; export const cdn = (file: string) => `${isProduction ? cdnUrl : ''}${file}`; export const isShortDomain = process.env.NEXT_PUBLIC_SHORT_DOMAIN === 'true'; diff --git a/utils/axios.ts b/utils/axios.ts index af0fb8a9..fb19dc9a 100644 --- a/utils/axios.ts +++ b/utils/axios.ts @@ -1,6 +1,7 @@ import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'; import { Response } from 'types/api'; import { z } from 'zod'; +import { isProduction } from '../types/constants'; import HttpStatusCode from './statusCode'; export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; @@ -17,10 +18,12 @@ export function errorHandler( } export const catchErrorHandler = (res: NextApiResponse, error?: any) => { - require('./loggerServer').error(error); + if (!isProduction) console.error('[Error]', error); if (error instanceof z.ZodError) { + require('./loggerServer').warn(error); return res.status(HttpStatusCode.BAD_REQUEST).json(error.issues); } + require('./loggerServer').error(error); return res .status(HttpStatusCode.INTERNAL_SERVER_ERROR) .json({ errorMessage: error.message || 'Something when wrong.' }); From 65f91cccee61063030ef0d1e2ddf1a9b7bfa009f Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Sat, 19 Aug 2023 17:17:07 +0700 Subject: [PATCH 2/6] fix ci cd --- .github/workflows/cd-short.yml | 2 +- .github/workflows/cd.yml | 2 +- .github/workflows/ci.yml | 2 +- scripts/decrypt_secret.sh | 16 +++++++++++----- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cd-short.yml b/.github/workflows/cd-short.yml index 97f0fbad..2afb5076 100644 --- a/.github/workflows/cd-short.yml +++ b/.github/workflows/cd-short.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Decrypt secret - run: ./scripts/decrypt_secret.sh + run: ./scripts/decrypt_secret.sh .env.production.gpg env: SECRET_PASSPHRASE: ${{ secrets.SECRET_PASSPHRASE }} - name: Login to GitHub Container Registry diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 817d76b1..d149b4f0 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -20,7 +20,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Decrypt secret - run: ./scripts/decrypt_secret.sh + run: ./scripts/decrypt_secret.sh .env.production.gpg env: SECRET_PASSPHRASE: ${{ secrets.SECRET_PASSPHRASE }} - name: Login to GitHub Container Registry diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3d7ca2c..5d09307f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: with: node-version: 16.x - name: Decrypt secret - run: ./scripts/decrypt_secret.sh + run: ./scripts/decrypt_secret.sh .env.test.gpg env: SECRET_PASSPHRASE: ${{ secrets.SECRET_PASSPHRASE }} - run: npm i diff --git a/scripts/decrypt_secret.sh b/scripts/decrypt_secret.sh index e3e2fdb8..451fe217 100755 --- a/scripts/decrypt_secret.sh +++ b/scripts/decrypt_secret.sh @@ -1,7 +1,13 @@ #!/bin/sh -# --batch to prevent interactive command -# --yes to assume "yes" for questions -gpg --quiet --batch --yes --decrypt --passphrase="$SECRET_PASSPHRASE" \ ---output ./.env.production .env.production.gpg -mv ./.env.production ./.env +if [ -z "$1" ] +then + echo "Decript failed. Host is empty!" +else + echo "Decript with host: $1..."; + # --batch to prevent interactive command + # --yes to assume "yes" for questions + gpg --quiet --batch --yes --decrypt --passphrase="$SECRET_PASSPHRASE" \ + --output ./.env $1 + echo "Decript successfully"; +fi From ef84afee432e4c39025dbfd44d3afed723c3cc87 Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Sat, 19 Aug 2023 17:26:22 +0700 Subject: [PATCH 3/6] fix ci cd --- test/shorten.test.ts | 1 - utils/loggerServer.ts | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/test/shorten.test.ts b/test/shorten.test.ts index ceb230f2..b47b3ae9 100644 --- a/test/shorten.test.ts +++ b/test/shorten.test.ts @@ -83,7 +83,6 @@ describe('Test /api/shorten...', () => { const { req, res } = createMocks({ method: 'GET', query: { url: 'U2FsdGVkX19lPT7tc2v+EAQ+q+S+QmgedQXJPLAhhjZDskrGAPv+kdWEm624npUtHaEGmCTcJHbFaYeZAv+FQw==' }, - headers: { 'x-forwarded-for': ip }, }); await controller.shorten.handler(req, res); expect(res._getStatusCode()).toBe(HttpStatusCode.OK); diff --git a/utils/loggerServer.ts b/utils/loggerServer.ts index f18228ba..17da337c 100644 --- a/utils/loggerServer.ts +++ b/utils/loggerServer.ts @@ -1,19 +1,29 @@ import pino from 'pino'; -import { isProduction } from '../types/constants'; +import { isProduction, isTest } from '../types/constants'; -const fileTransport = pino.transport({ - target: 'pino/file', - options: { destination: isProduction ? `pino.log` : `./logs/pino.log` }, -}); - -module.exports = pino( - { - formatters: { - level: (label: string) => { - return { level: label.toUpperCase() }; +module.exports = isTest + ? { + info(message: any) { + console.log('[INFO]: ', message); + }, + warn(message: any) { + console.warn('[WARN]: ', message); + }, + error(message: any) { + console.error('[WARN]: ', message); + }, + } + : pino( + { + formatters: { + level: (label: string) => { + return { level: label.toUpperCase() }; + }, + }, + timestamp: pino.stdTimeFunctions.isoTime, }, - }, - timestamp: pino.stdTimeFunctions.isoTime, - }, - fileTransport, -); + pino.transport({ + target: 'pino/file', + options: { destination: isProduction ? `pino.log` : `./logs/pino.log` }, + }), + ); From 8a3c98a13a5d3bdf6fea62a98c9c418a0df626c8 Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Sat, 19 Aug 2023 17:30:10 +0700 Subject: [PATCH 4/6] increase time out test to 60s --- test/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.ts b/test/index.ts index 85bfb1e4..aa9372ff 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,4 +1,4 @@ import path from 'path'; require('dotenv').config({ path: path.resolve(__dirname, '../.env.test') }); -jest.setTimeout(10000); +jest.setTimeout(60000); From 5daf5fdb69af25ce58fc7b03fc700d57036977f7 Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Sat, 19 Aug 2023 17:38:17 +0700 Subject: [PATCH 5/6] fix test --- test/shorten.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/shorten.test.ts b/test/shorten.test.ts index b47b3ae9..75b16f68 100644 --- a/test/shorten.test.ts +++ b/test/shorten.test.ts @@ -57,6 +57,7 @@ describe('Test /api/shorten...', () => { it('Should throw error when reached limit request', async () => { await redis.expire(key, 0); + const requests = []; for (let i = 0; i < 5; i++) { let { req, res } = createMocks({ @@ -66,8 +67,9 @@ describe('Test /api/shorten...', () => { }, headers: { 'x-forwarded-for': ip }, }); - await controller.shorten.handler(req, res); + requests.push(controller.shorten.handler(req, res)); } + await Promise.all(requests); const { req, res } = createMocks({ method: 'GET', query: { url: 'U2FsdGVkX19lPT7tc2v+EAQ+q+S+QmgedQXJPLAhhjZDskrGAPv+kdWEm624npUtHaEGmCTcJHbFaYeZAv+FQw==' }, @@ -83,6 +85,7 @@ describe('Test /api/shorten...', () => { const { req, res } = createMocks({ method: 'GET', query: { url: 'U2FsdGVkX19lPT7tc2v+EAQ+q+S+QmgedQXJPLAhhjZDskrGAPv+kdWEm624npUtHaEGmCTcJHbFaYeZAv+FQw==' }, + headers: { 'x-forwarded-for': ip }, }); await controller.shorten.handler(req, res); expect(res._getStatusCode()).toBe(HttpStatusCode.OK); From 338db1e52f8e1fb64ef0986a1d128f3b1f59a40e Mon Sep 17 00:00:00 2001 From: thanhdanh27600 Date: Sat, 19 Aug 2023 17:41:22 +0700 Subject: [PATCH 6/6] improve test --- .github/workflows/ci.yml | 2 +- test/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d09307f..a3193188 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: branches: [staging] jobs: - lint: + CI: runs-on: ubuntu-latest steps: diff --git a/test/index.ts b/test/index.ts index aa9372ff..084b3541 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,4 +1,4 @@ import path from 'path'; require('dotenv').config({ path: path.resolve(__dirname, '../.env.test') }); -jest.setTimeout(60000); +jest.setTimeout(20000);