From fe069d1d698da3527459c498dcadb4c30e6d33e5 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 10:31:12 -0300 Subject: [PATCH 01/14] add husky --- .husky/pre-commit | 4 ++++ package.json | 6 ++++-- yarn.lock | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..6cdaab7 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn lint diff --git a/package.json b/package.json index 355ccce..2523d1f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "build": "turbo build", "lint": "turbo lint", "dev": "turbo dev", - "test": "turbo test" + "test": "turbo test", + "prepare": "husky install" }, "keywords": [], "author": "tknickman", @@ -22,6 +23,7 @@ "eslint-config-custom": "*", "prettier-config-custom": "*", "prettier": "^3.1.0", - "turbo": "^1.10.16" + "turbo": "^1.10.16", + "husky": "^8.0.0" } } diff --git a/yarn.lock b/yarn.lock index 2830ec4..fdf7d72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3696,6 +3696,11 @@ human-signals@^4.3.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== +husky@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" From 7b9cf65227f7f2771d322dd1f3edf0934dff0f4c Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 10:41:55 -0300 Subject: [PATCH 02/14] remove default files / add commits EP structure --- apps/server/src/app.controller.spec.ts | 22 ------------------- apps/server/src/app.controller.ts | 12 ---------- apps/server/src/app.module.ts | 9 ++++---- apps/server/src/app.service.ts | 8 ------- apps/server/src/commits/commits.controller.ts | 11 ++++++++++ apps/server/src/commits/commits.module.ts | 11 ++++++++++ apps/server/src/commits/commits.service.ts | 6 +++++ 7 files changed, 32 insertions(+), 47 deletions(-) delete mode 100644 apps/server/src/app.controller.spec.ts delete mode 100644 apps/server/src/app.controller.ts delete mode 100644 apps/server/src/app.service.ts create mode 100644 apps/server/src/commits/commits.controller.ts create mode 100644 apps/server/src/commits/commits.module.ts create mode 100644 apps/server/src/commits/commits.service.ts diff --git a/apps/server/src/app.controller.spec.ts b/apps/server/src/app.controller.spec.ts deleted file mode 100644 index 601b8d7..0000000 --- a/apps/server/src/app.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing' -import { AppController } from './app.controller' -import { AppService } from './app.service' - -describe('AppController', () => { - let appController: AppController - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService] - }).compile() - - appController = app.get(AppController) - }) - - describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!') - }) - }) -}) diff --git a/apps/server/src/app.controller.ts b/apps/server/src/app.controller.ts deleted file mode 100644 index 4e88eca..0000000 --- a/apps/server/src/app.controller.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Controller, Get } from '@nestjs/common' -import { AppService } from './app.service' - -@Controller() -export class AppController { - constructor(private readonly appService: AppService) {} - - @Get() - getHello(): string { - return this.appService.getHello() - } -} diff --git a/apps/server/src/app.module.ts b/apps/server/src/app.module.ts index c8408d0..fa175e5 100644 --- a/apps/server/src/app.module.ts +++ b/apps/server/src/app.module.ts @@ -1,10 +1,9 @@ import { Module } from '@nestjs/common' -import { AppController } from './app.controller' -import { AppService } from './app.service' +import { CommitsModule } from './commits/commits.module' @Module({ - imports: [], - controllers: [AppController], - providers: [AppService] + imports: [CommitsModule], + controllers: [], + providers: [] }) export class AppModule {} diff --git a/apps/server/src/app.service.ts b/apps/server/src/app.service.ts deleted file mode 100644 index bc13055..0000000 --- a/apps/server/src/app.service.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Injectable } from '@nestjs/common' - -@Injectable() -export class AppService { - getHello(): string { - return 'Hello World!' - } -} diff --git a/apps/server/src/commits/commits.controller.ts b/apps/server/src/commits/commits.controller.ts new file mode 100644 index 0000000..0f17680 --- /dev/null +++ b/apps/server/src/commits/commits.controller.ts @@ -0,0 +1,11 @@ +import { Controller, Get } from '@nestjs/common' +import { CommitsService } from './commits.service' + +@Controller('commits') +export class CommitsController { + constructor(private readonly service: CommitsService) {} + @Get() + async getAll() { + return await this.service.getAllCommits() + } +} diff --git a/apps/server/src/commits/commits.module.ts b/apps/server/src/commits/commits.module.ts new file mode 100644 index 0000000..5efef98 --- /dev/null +++ b/apps/server/src/commits/commits.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common' +import { CommitsController } from './commits.controller' +import { CommitsService } from './commits.service' + +@Module({ + imports: [], + controllers: [CommitsController], + providers: [CommitsService] +}) + +export class CommitsModule {} diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts new file mode 100644 index 0000000..f2ce053 --- /dev/null +++ b/apps/server/src/commits/commits.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@nestjs/common' + +@Injectable() +export class CommitsService { + async getAllCommits() {} +} From b6119a606739e62e528ad9d4414d9d3348bccb0e Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 10:43:09 -0300 Subject: [PATCH 03/14] add passWithNoTests jest opt --- apps/server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/package.json b/apps/server/package.json index 6403561..4276fa4 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -13,7 +13,7 @@ "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "test": "jest", + "test": "jest --passWithNoTests", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", From be8de58e17adb6beb20ef0c727dbafb008b5d19f Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 11:25:29 -0300 Subject: [PATCH 04/14] add configuration --- apps/server/config/config.ts | 3 +++ apps/server/package.json | 1 + apps/server/src/app.module.ts | 10 +++++++++- yarn.lock | 25 +++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 apps/server/config/config.ts diff --git a/apps/server/config/config.ts b/apps/server/config/config.ts new file mode 100644 index 0000000..23c121f --- /dev/null +++ b/apps/server/config/config.ts @@ -0,0 +1,3 @@ +export default () => ({ + githubToken: process.env.GITHUB_TOKEN +}) diff --git a/apps/server/package.json b/apps/server/package.json index 4276fa4..76e8fa6 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@nestjs/common": "^10.0.0", + "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", diff --git a/apps/server/src/app.module.ts b/apps/server/src/app.module.ts index fa175e5..f838667 100644 --- a/apps/server/src/app.module.ts +++ b/apps/server/src/app.module.ts @@ -1,8 +1,16 @@ import { Module } from '@nestjs/common' +import { ConfigModule } from '@nestjs/config' import { CommitsModule } from './commits/commits.module' +import config from 'config/config' @Module({ - imports: [CommitsModule], + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [config] + }), + CommitsModule + ], controllers: [], providers: [] }) diff --git a/yarn.lock b/yarn.lock index fdf7d72..a55d523 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,6 +847,16 @@ iterare "1.2.1" tslib "2.6.2" +"@nestjs/config@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@nestjs/config/-/config-3.1.1.tgz#51e23ed84debd08afb86acf7b92bc4bf341797da" + integrity sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ== + dependencies: + dotenv "16.3.1" + dotenv-expand "10.0.0" + lodash "4.17.21" + uuid "9.0.0" + "@nestjs/core@^10.0.0": version "10.2.10" resolved "https://registry.yarnpkg.com/@nestjs/core/-/core-10.2.10.tgz#96b6fda7785402b0a3b819c15103675990b75290" @@ -2548,11 +2558,21 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dotenv-expand@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" + integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== + dotenv@16.0.3: version "16.0.3" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== +dotenv@16.3.1: + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -6520,6 +6540,11 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" From 99660eebf5f8322365d521a30d48ce70c4bec914 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 11:43:10 -0300 Subject: [PATCH 05/14] add octokit and implement basic fetch --- apps/server/package.json | 1 + apps/server/src/commits/commits.controller.ts | 2 + apps/server/src/commits/commits.module.ts | 3 +- apps/server/src/commits/commits.service.ts | 9 +- apps/server/src/main.ts | 2 +- apps/server/src/octokit/octokitClient.ts | 17 + yarn.lock | 399 +++++++++++++++++- 7 files changed, 424 insertions(+), 9 deletions(-) create mode 100644 apps/server/src/octokit/octokitClient.ts diff --git a/apps/server/package.json b/apps/server/package.json index 76e8fa6..41a6a13 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -25,6 +25,7 @@ "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", + "octokit": "^3.1.2", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1" }, diff --git a/apps/server/src/commits/commits.controller.ts b/apps/server/src/commits/commits.controller.ts index 0f17680..9791728 100644 --- a/apps/server/src/commits/commits.controller.ts +++ b/apps/server/src/commits/commits.controller.ts @@ -1,6 +1,8 @@ import { Controller, Get } from '@nestjs/common' +import { ApiTags } from '@nestjs/swagger' import { CommitsService } from './commits.service' +@ApiTags('commits') @Controller('commits') export class CommitsController { constructor(private readonly service: CommitsService) {} diff --git a/apps/server/src/commits/commits.module.ts b/apps/server/src/commits/commits.module.ts index 5efef98..f892aa2 100644 --- a/apps/server/src/commits/commits.module.ts +++ b/apps/server/src/commits/commits.module.ts @@ -1,11 +1,12 @@ import { Module } from '@nestjs/common' import { CommitsController } from './commits.controller' import { CommitsService } from './commits.service' +import { OctokitClient } from 'src/octokit/octokitClient' @Module({ imports: [], controllers: [CommitsController], - providers: [CommitsService] + providers: [CommitsService, OctokitClient] }) export class CommitsModule {} diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index f2ce053..e128244 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -1,6 +1,13 @@ import { Injectable } from '@nestjs/common' +import { OctokitClient } from 'src/octokit/octokitClient' @Injectable() export class CommitsService { - async getAllCommits() {} + constructor(private readonly octokit: OctokitClient) {} + async getAllCommits() { + return this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits', { + owner: 'SantiagoJavierRubio', + repo: 'git-commit-history' + }) + } } diff --git a/apps/server/src/main.ts b/apps/server/src/main.ts index 03ba637..8e514aa 100644 --- a/apps/server/src/main.ts +++ b/apps/server/src/main.ts @@ -3,7 +3,7 @@ import { AppModule } from './app.module' import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger/dist' async function bootstrap() { - const app = await NestFactory.create(AppModule) + const app = await NestFactory.create(AppModule, { cors: true }) const swaggerConfig = new DocumentBuilder() .setTitle('Git commit history API') .setVersion('1.0') diff --git a/apps/server/src/octokit/octokitClient.ts b/apps/server/src/octokit/octokitClient.ts new file mode 100644 index 0000000..47db366 --- /dev/null +++ b/apps/server/src/octokit/octokitClient.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common' +import { Octokit } from 'octokit' +import { ConfigService } from '@nestjs/config' + +@Injectable() +export class OctokitClient { + private client: Octokit + constructor(private readonly configService: ConfigService) { + this.client = new Octokit({ + auth: this.configService.get('githubToken') + }) + } + + getClient() { + return this.client + } +} diff --git a/yarn.lock b/yarn.lock index a55d523..c88c3be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -951,6 +951,229 @@ consola "^2.15.0" node-fetch "^2.6.1" +"@octokit/app@^14.0.2": + version "14.0.2" + resolved "https://registry.yarnpkg.com/@octokit/app/-/app-14.0.2.tgz#b47c52020221351fb58640f113eb38b2ad3998fe" + integrity sha512-NCSCktSx+XmjuSUVn2dLfqQ9WIYePGP95SDJs4I9cn/0ZkeXcPkaoCLl64Us3dRKL2ozC7hArwze5Eu+/qt1tg== + dependencies: + "@octokit/auth-app" "^6.0.0" + "@octokit/auth-unauthenticated" "^5.0.0" + "@octokit/core" "^5.0.0" + "@octokit/oauth-app" "^6.0.0" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/types" "^12.0.0" + "@octokit/webhooks" "^12.0.4" + +"@octokit/auth-app@^6.0.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-6.0.1.tgz#7137b1af124189a979de6053da5d4c8cdb1fa4e9" + integrity sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA== + dependencies: + "@octokit/auth-oauth-app" "^7.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + deprecation "^2.3.1" + lru-cache "^10.0.0" + universal-github-app-jwt "^1.1.1" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-app@^7.0.0": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-7.0.1.tgz#30fd8fcb4608ca52c29c265a3fc7032897796c8e" + integrity sha512-RE0KK0DCjCHXHlQBoubwlLijXEKfhMhKm9gO56xYvFmP1QTMb+vvwRPmQLLx0V+5AvV9N9I3lr1WyTzwL3rMDg== + dependencies: + "@octokit/auth-oauth-device" "^6.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/types" "^12.0.0" + "@types/btoa-lite" "^1.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-device@^6.0.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-6.0.1.tgz#38e5f7f8997c5e8b774f283463ecf4a7e42d7cee" + integrity sha512-yxU0rkL65QkjbqQedgVx3gmW7YM5fF+r5uaSj9tM/cQGVqloXcqP2xK90eTyYvl29arFVCW8Vz4H/t47mL0ELw== + dependencies: + "@octokit/oauth-methods" "^4.0.0" + "@octokit/request" "^8.0.0" + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-user@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-4.0.1.tgz#c8267883935c83f78318c726ff91d7e98de05517" + integrity sha512-N94wWW09d0hleCnrO5wt5MxekatqEJ4zf+1vSe8MKMrhZ7gAXKFOKrDEZW2INltvBWJCyDUELgGRv8gfErH1Iw== + dependencies: + "@octokit/auth-oauth-device" "^6.0.0" + "@octokit/oauth-methods" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/types" "^12.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-token@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" + integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== + +"@octokit/auth-unauthenticated@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz#d8032211728333068b2e07b53997c29e59a03507" + integrity sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + +"@octokit/core@^5.0.0": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.0.2.tgz#ae7c5d61fdd98ba348a27c3cc510879a130b1234" + integrity sha512-cZUy1gUvd4vttMic7C0lwPed8IYXWYp8kHIMatyhY8t8n3Cpw2ILczkV5pGMPqef7v0bLo0pOHrEHarsau2Ydg== + dependencies: + "@octokit/auth-token" "^4.0.0" + "@octokit/graphql" "^7.0.0" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + +"@octokit/endpoint@^9.0.0": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.4.tgz#8afda5ad1ffc3073d08f2b450964c610b821d1ea" + integrity sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw== + dependencies: + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^7.0.0": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-7.0.2.tgz#3df14b9968192f9060d94ed9e3aa9780a76e7f99" + integrity sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q== + dependencies: + "@octokit/request" "^8.0.1" + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/oauth-app@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@octokit/oauth-app/-/oauth-app-6.0.0.tgz#a5c3b7794df4280c6aadbadd843119059d70a2c4" + integrity sha512-bNMkS+vJ6oz2hCyraT9ZfTpAQ8dZNqJJQVNaKjPLx4ue5RZiFdU1YWXguOPR8AaSHS+lKe+lR3abn2siGd+zow== + dependencies: + "@octokit/auth-oauth-app" "^7.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/auth-unauthenticated" "^5.0.0" + "@octokit/core" "^5.0.0" + "@octokit/oauth-authorization-url" "^6.0.2" + "@octokit/oauth-methods" "^4.0.0" + "@types/aws-lambda" "^8.10.83" + universal-user-agent "^6.0.0" + +"@octokit/oauth-authorization-url@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz#cc82ca29cc5e339c9921672f39f2b3f5c8eb6ef2" + integrity sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA== + +"@octokit/oauth-methods@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-4.0.1.tgz#90d22c662387056307778d7e5c4763ff559636c4" + integrity sha512-1NdTGCoBHyD6J0n2WGXg9+yDLZrRNZ0moTEex/LSPr49m530WNKcCfXDghofYptr3st3eTii+EHoG5k/o+vbtw== + dependencies: + "@octokit/oauth-authorization-url" "^6.0.2" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + btoa-lite "^1.0.0" + +"@octokit/openapi-types@^19.0.2": + version "19.1.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-19.1.0.tgz#75ec7e64743870fc73e1ab4bc6ec252ecdd624dc" + integrity sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw== + +"@octokit/plugin-paginate-graphql@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-4.0.0.tgz#b26024fa454039c18b948f13bf754ff86b89e8b9" + integrity sha512-7HcYW5tP7/Z6AETAPU14gp5H5KmCPT3hmJrS/5tO7HIgbwenYmgw4OY9Ma54FDySuxMwD+wsJlxtuGWwuZuItA== + +"@octokit/plugin-paginate-rest@^9.0.0": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.4.tgz#9eca55e3e88f15b574e072732769e933bfa88d8b" + integrity sha512-MvZx4WvfhBnt7PtH5XE7HORsO7bBk4er1FgRIUr1qJ89NR2I6bWjGyKsxk8z42FPQ34hFQm0Baanh4gzdZR4gQ== + dependencies: + "@octokit/types" "^12.3.0" + +"@octokit/plugin-rest-endpoint-methods@^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.2.0.tgz#eeaa4de97a2ae26404dea30ce3e17b11928e027c" + integrity sha512-ePbgBMYtGoRNXDyKGvr9cyHjQ163PbwD0y1MkDJCpkO2YH4OeXX40c4wYHKikHGZcpGPbcRLuy0unPUuafco8Q== + dependencies: + "@octokit/types" "^12.3.0" + +"@octokit/plugin-retry@^6.0.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz#3257404f7cc418e1c1f13a7f2012c1db848b7693" + integrity sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + bottleneck "^2.15.3" + +"@octokit/plugin-throttling@^8.0.0": + version "8.1.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-8.1.3.tgz#7fb0e001c0cb9383c6be07740b8ec326ed990f6b" + integrity sha512-pfyqaqpc0EXh5Cn4HX9lWYsZ4gGbjnSmUILeu4u2gnuM50K/wIk9s1Pxt3lVeVwekmITgN/nJdoh43Ka+vye8A== + dependencies: + "@octokit/types" "^12.2.0" + bottleneck "^2.15.3" + +"@octokit/request-error@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.0.1.tgz#277e3ce3b540b41525e07ba24c5ef5e868a72db9" + integrity sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ== + dependencies: + "@octokit/types" "^12.0.0" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^8.0.0", "@octokit/request@^8.0.1", "@octokit/request@^8.0.2": + version "8.1.6" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-8.1.6.tgz#a76a859c30421737a3918b40973c2ff369009571" + integrity sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ== + dependencies: + "@octokit/endpoint" "^9.0.0" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/types@^12.0.0", "@octokit/types@^12.2.0", "@octokit/types@^12.3.0": + version "12.3.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-12.3.0.tgz#e3f8bc53f65ef551e19cc1a0fea15adadec17d2d" + integrity sha512-nJ8X2HRr234q3w/FcovDlA+ttUU4m1eJAourvfUUtwAWeqL8AsyRqfnLvVnYn3NFbUnsmzQCzLNdFerPwdmcDQ== + dependencies: + "@octokit/openapi-types" "^19.0.2" + +"@octokit/webhooks-methods@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-4.0.0.tgz#d1697930ba3d8e6b6d0f8a2c996bb440d2e1df1b" + integrity sha512-M8mwmTXp+VeolOS/kfRvsDdW+IO0qJ8kYodM/sAysk093q6ApgmBXwK1ZlUvAwXVrp/YVHp6aArj4auAxUAOFw== + +"@octokit/webhooks-types@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-types/-/webhooks-types-7.1.0.tgz#d533dea253416e02dd6c2bfab25e533295bd5d3f" + integrity sha512-y92CpG4kFFtBBjni8LHoV12IegJ+KFxLgKRengrVjKmGE5XMeCuGvlfRe75lTRrgXaG6XIWJlFpIDTlkoJsU8w== + +"@octokit/webhooks@^12.0.4": + version "12.0.8" + resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-12.0.8.tgz#72d01f2ab08f11bcd91b8e8e4e18018018169094" + integrity sha512-IndolsepJQtsGo7pyNRnftla/6Gn6Vejk6iV/RmKP76Z7QNFLanZvoJkU8CLMcOjmJk/6X8T2TfpCXVw68RenQ== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/webhooks-methods" "^4.0.0" + "@octokit/webhooks-types" "7.1.0" + aggregate-error "^3.1.0" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -1084,6 +1307,11 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@types/aws-lambda@^8.10.83": + version "8.10.129" + resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.129.tgz#c4e040778a13b70a9cdf8ad54c1b853c94e2a44d" + integrity sha512-0Rl7CpTPVws5cp0Ui1gZh4Q+TXC65bXVwTOGoI2RKW45dxWzyZGbjIX0uFjFYdIJ8vnD45y584rIIqvD2vBBfQ== + "@types/babel__core@^7.1.14", "@types/babel__core@^7.20.4": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -1125,6 +1353,11 @@ "@types/connect" "*" "@types/node" "*" +"@types/btoa-lite@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/btoa-lite/-/btoa-lite-1.0.2.tgz#82bb6aab00abf7cff3ca2825abe010c0cd536ae5" + integrity sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg== + "@types/connect@*": version "3.4.38" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" @@ -1227,6 +1460,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/jsonwebtoken@^9.0.0": + version "9.0.5" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz#0bd9b841c9e6c5a937c17656e2368f65da025588" + integrity sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA== + dependencies: + "@types/node" "*" + "@types/mime@*": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" @@ -1594,6 +1834,14 @@ acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== +aggregate-error@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv-formats@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -1938,6 +2186,11 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +before-after-hook@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== + big-integer@^1.6.44: version "1.6.52" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" @@ -1993,6 +2246,11 @@ body-parser@1.20.2: type-is "~1.6.18" unpipe "1.0.0" +bottleneck@^2.15.3: + version "2.19.5" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" + integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== + bplist-parser@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" @@ -2046,6 +2304,16 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +btoa-lite@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" + integrity sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA== + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2176,6 +2444,11 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -2494,6 +2767,11 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +deprecation@^2.0.0, deprecation@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -2578,6 +2856,13 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3759,6 +4044,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -4604,6 +4894,22 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -4614,6 +4920,23 @@ jsonfile@^6.0.1: object.assign "^4.1.4" object.values "^1.1.6" +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -4685,6 +5008,36 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -4695,6 +5048,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + lodash@4.17.21, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -4715,6 +5073,11 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.0.0, "lru-cache@^9.1.1 || ^10.0.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -4729,11 +5092,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -"lru-cache@^9.1.1 || ^10.0.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" - integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== - macos-release@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.1.tgz#bccac4a8f7b93163a8d163b8ebf385b3c5f55bf9" @@ -5070,6 +5428,22 @@ object.values@^1.1.6, object.values@^1.1.7: define-properties "^1.2.0" es-abstract "^1.22.1" +octokit@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/octokit/-/octokit-3.1.2.tgz#e574e4f2f5f8712e10412ce81fb56a74c93d4cfa" + integrity sha512-MG5qmrTL5y8KYwFgE1A4JWmgfQBaIETE/lOlfwNYx1QOtCQHGVxkRJmdUJltFc1HVn73d61TlMhMyNTOtMl+ng== + dependencies: + "@octokit/app" "^14.0.2" + "@octokit/core" "^5.0.0" + "@octokit/oauth-app" "^6.0.0" + "@octokit/plugin-paginate-graphql" "^4.0.0" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/plugin-rest-endpoint-methods" "^10.0.0" + "@octokit/plugin-retry" "^6.0.0" + "@octokit/plugin-throttling" "^8.0.0" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -5717,7 +6091,7 @@ safe-array-concat@^1.0.1: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -6500,6 +6874,19 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +universal-github-app-jwt@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz#d57cee49020662a95ca750a057e758a1a7190e6e" + integrity sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w== + dependencies: + "@types/jsonwebtoken" "^9.0.0" + jsonwebtoken "^9.0.0" + +universal-user-agent@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" + integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" From b519f34a137471eba0ca52c043bf9e5d2d50ff88 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 11:50:08 -0300 Subject: [PATCH 06/14] add option to pass custom repo data --- apps/server/config/config.ts | 6 +++++- apps/server/src/commits/commits.service.ts | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/server/config/config.ts b/apps/server/config/config.ts index 23c121f..00e223b 100644 --- a/apps/server/config/config.ts +++ b/apps/server/config/config.ts @@ -1,3 +1,7 @@ export default () => ({ - githubToken: process.env.GITHUB_TOKEN + githubToken: process.env.GITHUB_TOKEN, + repo: { + owner: process.env.REPO_OWNER ?? 'SantiagoJavierRubio', + name: process.env.REPO_NAME ?? 'git-commit-history' + } }) diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index e128244..e662a0b 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -1,13 +1,14 @@ import { Injectable } from '@nestjs/common' +import { ConfigService } from '@nestjs/config' import { OctokitClient } from 'src/octokit/octokitClient' @Injectable() export class CommitsService { - constructor(private readonly octokit: OctokitClient) {} + constructor(private readonly octokit: OctokitClient, private readonly configService: ConfigService) {} async getAllCommits() { return this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits', { - owner: 'SantiagoJavierRubio', - repo: 'git-commit-history' + owner: this.configService.get('repo.owner'), + repo: this.configService.get('repo.name') }) } } From 82927c1695e665475e01d91be581982c2654ab9d Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 12:01:22 -0300 Subject: [PATCH 07/14] add getOneCommit ep --- apps/server/src/commits/commits.controller.ts | 16 +++++++++++++--- apps/server/src/commits/commits.service.ts | 9 +++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/server/src/commits/commits.controller.ts b/apps/server/src/commits/commits.controller.ts index 9791728..ea51705 100644 --- a/apps/server/src/commits/commits.controller.ts +++ b/apps/server/src/commits/commits.controller.ts @@ -1,13 +1,23 @@ -import { Controller, Get } from '@nestjs/common' -import { ApiTags } from '@nestjs/swagger' +import { Controller, Get, Param } from '@nestjs/common' +import { ApiTags, ApiParam } from '@nestjs/swagger' import { CommitsService } from './commits.service' @ApiTags('commits') @Controller('commits') export class CommitsController { constructor(private readonly service: CommitsService) {} - @Get() + + @Get() async getAll() { return await this.service.getAllCommits() } + + @ApiParam({ + name: 'ref', + description: 'The commit reference. Can be a commit SHA, branch name, or tag name.' + }) + @Get('/:ref') + async getOne(@Param('ref') ref: string) { + return await this.service.getById(ref) + } } diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index e662a0b..80f9e09 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -5,10 +5,19 @@ import { OctokitClient } from 'src/octokit/octokitClient' @Injectable() export class CommitsService { constructor(private readonly octokit: OctokitClient, private readonly configService: ConfigService) {} + async getAllCommits() { return this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits', { owner: this.configService.get('repo.owner'), repo: this.configService.get('repo.name') }) } + + async getById(ref: string) { + return this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits/{ref}', { + owner: this.configService.get('repo.owner'), + repo: this.configService.get('repo.name'), + ref + }) + } } From cf670c34a5d720567e49a823c92cc45fff1e1dc4 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 13:17:28 -0300 Subject: [PATCH 08/14] add ep test --- apps/server/package.json | 3 +- .../test/commits/__mocks__/commits.mocks.ts | 87 +++++++++++++++++++ .../test/commits/commits.controller.spec.ts | 26 ++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 apps/server/test/commits/__mocks__/commits.mocks.ts create mode 100644 apps/server/test/commits/commits.controller.spec.ts diff --git a/apps/server/package.json b/apps/server/package.json index 41a6a13..d0fe1f2 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -58,7 +58,8 @@ "json", "ts" ], - "rootDir": "src", + "modulePaths": [""], + "moduleDirectories": ["node_modules", "src"], "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" diff --git a/apps/server/test/commits/__mocks__/commits.mocks.ts b/apps/server/test/commits/__mocks__/commits.mocks.ts new file mode 100644 index 0000000..9b4fe0e --- /dev/null +++ b/apps/server/test/commits/__mocks__/commits.mocks.ts @@ -0,0 +1,87 @@ +export const commitListMock = new Promise((resolve, reject) => resolve({ + data: [{ + sha: 'bd75cf8acc664414df895ed5d623c3426b167321', + node_id: 'C_kwDOKy00BNoAKGJkNzVjZjhhY2M2NjQ0MTRkZjg5NWVkNWQ2MjNjMzQyNmIxNjczMjE', + commit: { + author: { + name: 'Santiago Javier Rubio', + email: 's.rubio91@gmail.com', + date: '2023-11-29T13:27:48Z' + }, + committer: { + name: 'GitHub', + email: 'noreply@github.com', + date: '2023-11-29T13:27:48Z' + }, + message: 'Merge pull request #2 from SantiagoJavierRubio/dev-client\n\nClient cleanup & setup', + tree: { + sha: 'f91a62c5a9498af36d8b66d1ab26d8d6c43482f7', + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/git/trees/f91a62c5a9498af36d8b66d1ab26d8d6c43482f7' + }, + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/git/commits/bd75cf8acc664414df895ed5d623c3426b167321', + comment_count: 0, + verification: { + verified: true, + reason: 'valid', + signature: '-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJlZzxUCRBK7hj4Ov3rIwAATzgIAHw91oJl2TzvR6UGl+mJvjlW\nApSrRmoNMdlYApdIitgWa6NzSMd/X4gkAdXtdmX8MlMemorpz3MO+BxAoirEb9oX\nflh3+y/gelIrDy72hlE2PZjyzcCAPxeF4APa1tu3cqeVlkAWlYsUv+mgpzlc/2s6\n9auj6xYIo13qunedVSV0Gby2qneQWf15xb4AaDxb8GTwHWi3U3Dgag7QhBSP4AgJ\nTePyjYKYs85x6ACtgW86e8o7K3Mpzg1ZFrCm61hbC77Mnj9h7F4HtZXIlzuHh4j0\ndngW2ecXDC/cJI+V2yFJUIO3o0RTEXdiyBX46scwVo3XqKlopkwvk91tcZE8bgs=\n=Fhc8\n-----END PGP SIGNATURE-----\n', + payload: 'tree f91a62c5a9498af36d8b66d1ab26d8d6c43482f7\nparent 5336e9079a916c32f41e04523bd5b9b08de9e55d\nparent aee9d11a05bcda6f30ba202eda0d5532e699ea92\nauthor Santiago Javier Rubio 1701264468 -0300\ncommitter GitHub 1701264468 -0300\n\nMerge pull request #2 from SantiagoJavierRubio/dev-client\n\nClient cleanup & setup' + } + }, + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/bd75cf8acc664414df895ed5d623c3426b167321', + html_url: 'https://github.com/SantiagoJavierRubio/git-commit-history/commit/bd75cf8acc664414df895ed5d623c3426b167321', + comments_url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/bd75cf8acc664414df895ed5d623c3426b167321/comments', + author: { + login: 'SantiagoJavierRubio', + id: 62577814, + node_id: 'MDQ6VXNlcjYyNTc3ODE0', + avatar_url: 'https://avatars.githubusercontent.com/u/62577814?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/SantiagoJavierRubio', + html_url: 'https://github.com/SantiagoJavierRubio', + followers_url: 'https://api.github.com/users/SantiagoJavierRubio/followers', + following_url: 'https://api.github.com/users/SantiagoJavierRubio/following{/other_user}', + gists_url: 'https://api.github.com/users/SantiagoJavierRubio/gists{/gist_id}', + starred_url: 'https://api.github.com/users/SantiagoJavierRubio/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/SantiagoJavierRubio/subscriptions', + organizations_url: 'https://api.github.com/users/SantiagoJavierRubio/orgs', + repos_url: 'https://api.github.com/users/SantiagoJavierRubio/repos', + events_url: 'https://api.github.com/users/SantiagoJavierRubio/events{/privacy}', + received_events_url: 'https://api.github.com/users/SantiagoJavierRubio/received_events', + type: 'User', + site_admin: false + }, + committer: { + login: 'web-flow', + id: 19864447, + node_id: 'MDQ6VXNlcjE5ODY0NDQ3', + avatar_url: 'https://avatars.githubusercontent.com/u/19864447?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/web-flow', + html_url: 'https://github.com/web-flow', + followers_url: 'https://api.github.com/users/web-flow/followers', + following_url: 'https://api.github.com/users/web-flow/following{/other_user}', + gists_url: 'https://api.github.com/users/web-flow/gists{/gist_id}', + starred_url: 'https://api.github.com/users/web-flow/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/web-flow/subscriptions', + organizations_url: 'https://api.github.com/users/web-flow/orgs', + repos_url: 'https://api.github.com/users/web-flow/repos', + events_url: 'https://api.github.com/users/web-flow/events{/privacy}', + received_events_url: 'https://api.github.com/users/web-flow/received_events', + type: 'User', + site_admin: false + }, + parents: [ + { + sha: '5336e9079a916c32f41e04523bd5b9b08de9e55d', + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/5336e9079a916c32f41e04523bd5b9b08de9e55d', + html_url: 'https://github.com/SantiagoJavierRubio/git-commit-history/commit/5336e9079a916c32f41e04523bd5b9b08de9e55d' + }, + { + sha: 'aee9d11a05bcda6f30ba202eda0d5532e699ea92', + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/aee9d11a05bcda6f30ba202eda0d5532e699ea92', + html_url: 'https://github.com/SantiagoJavierRubio/git-commit-history/commit/aee9d11a05bcda6f30ba202eda0d5532e699ea92' + } + ] + }] +}) +) diff --git a/apps/server/test/commits/commits.controller.spec.ts b/apps/server/test/commits/commits.controller.spec.ts new file mode 100644 index 0000000..ff09193 --- /dev/null +++ b/apps/server/test/commits/commits.controller.spec.ts @@ -0,0 +1,26 @@ +import { CommitsController } from '../../src/commits/commits.controller' +import { OctokitClient } from '../../src/octokit/octokitClient' +import { ConfigService } from '@nestjs/config' +import { CommitsService } from '../../src/commits/commits.service' +import { commitListMock } from './__mocks__/commits.mocks' + +describe('Commits controller', () => { + let octokit: OctokitClient + let configService: ConfigService + let commitsController: CommitsController + let commitsService: CommitsService + + beforeEach(() => { + configService = new ConfigService() + octokit = new OctokitClient(configService) + commitsService = new CommitsService(octokit, configService) + commitsController = new CommitsController(commitsService) + }) + + describe('getAll', () => { + it('Should return array of commits', async () => { + jest.spyOn(commitsService, 'getAllCommits').mockImplementation(() => commitListMock as ReturnType) + expect((await commitsController.getAll())).toBe(await commitListMock) + }) + }) +}) From 67742f0ac3da31f9f21d6de66df8345c93fa4836 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 13:41:57 -0300 Subject: [PATCH 09/14] change commits ep to return data only --- apps/server/src/commits/commits.service.ts | 6 ++++-- apps/server/test/commits/__mocks__/commits.mocks.ts | 6 ++---- apps/server/test/commits/commits.controller.spec.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index 80f9e09..c42a197 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -7,17 +7,19 @@ export class CommitsService { constructor(private readonly octokit: OctokitClient, private readonly configService: ConfigService) {} async getAllCommits() { - return this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits', { + const response = await this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits', { owner: this.configService.get('repo.owner'), repo: this.configService.get('repo.name') }) + return response.data } async getById(ref: string) { - return this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits/{ref}', { + const response = await this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits/{ref}', { owner: this.configService.get('repo.owner'), repo: this.configService.get('repo.name'), ref }) + return response.data } } diff --git a/apps/server/test/commits/__mocks__/commits.mocks.ts b/apps/server/test/commits/__mocks__/commits.mocks.ts index 9b4fe0e..d6c7712 100644 --- a/apps/server/test/commits/__mocks__/commits.mocks.ts +++ b/apps/server/test/commits/__mocks__/commits.mocks.ts @@ -1,5 +1,5 @@ -export const commitListMock = new Promise((resolve, reject) => resolve({ - data: [{ +export const commitListMock = + [{ sha: 'bd75cf8acc664414df895ed5d623c3426b167321', node_id: 'C_kwDOKy00BNoAKGJkNzVjZjhhY2M2NjQ0MTRkZjg5NWVkNWQ2MjNjMzQyNmIxNjczMjE', commit: { @@ -83,5 +83,3 @@ export const commitListMock = new Promise((resolve, reject) => resolve({ } ] }] -}) -) diff --git a/apps/server/test/commits/commits.controller.spec.ts b/apps/server/test/commits/commits.controller.spec.ts index ff09193..0c68ba9 100644 --- a/apps/server/test/commits/commits.controller.spec.ts +++ b/apps/server/test/commits/commits.controller.spec.ts @@ -19,8 +19,8 @@ describe('Commits controller', () => { describe('getAll', () => { it('Should return array of commits', async () => { - jest.spyOn(commitsService, 'getAllCommits').mockImplementation(() => commitListMock as ReturnType) - expect((await commitsController.getAll())).toBe(await commitListMock) + jest.spyOn(commitsService, 'getAllCommits').mockImplementation(async () => commitListMock) + expect((await commitsController.getAll())).toBe(commitListMock) }) }) }) From 07e016267f18b402d862b6948179aa89e67ba1fb Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 19:51:00 -0300 Subject: [PATCH 10/14] infer types, check and share to client for end-to-end type safety --- apps/client/package.json | 3 +- apps/client/src/api/getCommits.ts | 2 + apps/client/src/pages/Home/index.tsx | 7 +- apps/server/config/config.ts | 1 + apps/server/package.json | 12 +++- apps/server/src/commits/commit.entity.ts | 35 ++++++++++ apps/server/src/commits/commits.controller.ts | 7 +- apps/server/src/commits/commits.service.ts | 8 ++- .../test/commits/__mocks__/commits.mocks.ts | 66 ++----------------- packages/types/index.ts | 1 + packages/types/package.json | 8 +++ packages/types/src/server.types.ts | 1 + yarn.lock | 19 +++++- 13 files changed, 99 insertions(+), 71 deletions(-) create mode 100644 apps/server/src/commits/commit.entity.ts create mode 100644 packages/types/index.ts create mode 100644 packages/types/package.json create mode 100644 packages/types/src/server.types.ts diff --git a/apps/client/package.json b/apps/client/package.json index ca76394..0178a4c 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -29,6 +29,7 @@ "postcss": "^8.4.31", "tailwindcss": "^3.3.5", "typescript": "^5.2.2", - "vite": "^5.0.0" + "vite": "^5.0.0", + "types": "*" } } diff --git a/apps/client/src/api/getCommits.ts b/apps/client/src/api/getCommits.ts index ce0700b..28089dd 100644 --- a/apps/client/src/api/getCommits.ts +++ b/apps/client/src/api/getCommits.ts @@ -1,4 +1,6 @@ import axios from 'axios' +import type {} from 'types' + export default function getCommits() { return axios.get('http://localhost:3000/commits').then(res => res.data) } diff --git a/apps/client/src/pages/Home/index.tsx b/apps/client/src/pages/Home/index.tsx index 8058d37..891c23c 100644 --- a/apps/client/src/pages/Home/index.tsx +++ b/apps/client/src/pages/Home/index.tsx @@ -1,15 +1,14 @@ import getCommits from '@/api/getCommits' import { useQuery } from '@tanstack/react-query' +import { CommitList } from 'types' export default function Home() { - const { isLoading, error, data, isFetching } = useQuery({ + const commitQuery = useQuery({ queryKey: ['commits'], queryFn: getCommits }) - // eslint-disable-next-line no-console - console.log(isLoading, error, data, isFetching) return ( -
Home
+
Home {commitQuery.isSuccess ? commitQuery.data[0].url : ''}
) } diff --git a/apps/server/config/config.ts b/apps/server/config/config.ts index 00e223b..80e211a 100644 --- a/apps/server/config/config.ts +++ b/apps/server/config/config.ts @@ -1,4 +1,5 @@ export default () => ({ + NODE_ENV: process.env.NODE_ENV || 'development', githubToken: process.env.GITHUB_TOKEN, repo: { owner: process.env.REPO_OWNER ?? 'SantiagoJavierRubio', diff --git a/apps/server/package.json b/apps/server/package.json index d0fe1f2..354764d 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -20,6 +20,7 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { + "@anatine/zod-openapi": "^2.2.1", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", @@ -27,7 +28,7 @@ "@nestjs/swagger": "^7.1.16", "octokit": "^3.1.2", "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1" + "zod": "^3.22.4" }, "devDependencies": { "@nestjs/cli": "^10.0.0", @@ -58,8 +59,13 @@ "json", "ts" ], - "modulePaths": [""], - "moduleDirectories": ["node_modules", "src"], + "modulePaths": [ + "" + ], + "moduleDirectories": [ + "node_modules", + "src" + ], "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" diff --git a/apps/server/src/commits/commit.entity.ts b/apps/server/src/commits/commit.entity.ts new file mode 100644 index 0000000..68fb719 --- /dev/null +++ b/apps/server/src/commits/commit.entity.ts @@ -0,0 +1,35 @@ +import { z } from 'zod' +import { generateSchema } from '@anatine/zod-openapi' + +export const basicCommitSchema = z.object({ + sha: z.string(), + node_id: z.string(), + commit: z.object({ + author: z.object({ + name: z.string(), + email: z.string(), + date: z.string() + }), + message: z.string(), + tree: z.object({ + sha: z.string(), + url: z.string() + }) + }), + url: z.string(), + html_url: z.string(), + parents: z.object({ + sha: z.string(), + url: z.string() + }).array(), + author: z.object({ + avatar_url: z.string(), + html_url: z.string() + }) +}) + +export const commitList = z.array(basicCommitSchema) + +export type CommitList = z.infer + +export const commitApiSchema = generateSchema(basicCommitSchema) diff --git a/apps/server/src/commits/commits.controller.ts b/apps/server/src/commits/commits.controller.ts index ea51705..c2e5d91 100644 --- a/apps/server/src/commits/commits.controller.ts +++ b/apps/server/src/commits/commits.controller.ts @@ -1,12 +1,17 @@ import { Controller, Get, Param } from '@nestjs/common' -import { ApiTags, ApiParam } from '@nestjs/swagger' +import { ApiTags, ApiParam, ApiOkResponse } from '@nestjs/swagger' import { CommitsService } from './commits.service' +import { commitApiSchema } from './commit.entity' @ApiTags('commits') @Controller('commits') export class CommitsController { constructor(private readonly service: CommitsService) {} + @ApiOkResponse({ + schema: commitApiSchema, + isArray: true + }) @Get() async getAll() { return await this.service.getAllCommits() diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index c42a197..74a5f3e 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -1,6 +1,7 @@ -import { Injectable } from '@nestjs/common' +import { HttpException, Injectable, InternalServerErrorException } from '@nestjs/common' import { ConfigService } from '@nestjs/config' import { OctokitClient } from 'src/octokit/octokitClient' +import { commitList } from './commit.entity' @Injectable() export class CommitsService { @@ -11,7 +12,10 @@ export class CommitsService { owner: this.configService.get('repo.owner'), repo: this.configService.get('repo.name') }) - return response.data + if (response.status !== 200) throw new HttpException('Github client error', response.status) + const parsed = commitList.safeParse(response.data) + if (parsed.success) return parsed.data + else throw new InternalServerErrorException('Github response did not match parameters') } async getById(ref: string) { diff --git a/apps/server/test/commits/__mocks__/commits.mocks.ts b/apps/server/test/commits/__mocks__/commits.mocks.ts index d6c7712..5c34790 100644 --- a/apps/server/test/commits/__mocks__/commits.mocks.ts +++ b/apps/server/test/commits/__mocks__/commits.mocks.ts @@ -8,78 +8,26 @@ export const commitListMock = email: 's.rubio91@gmail.com', date: '2023-11-29T13:27:48Z' }, - committer: { - name: 'GitHub', - email: 'noreply@github.com', - date: '2023-11-29T13:27:48Z' - }, message: 'Merge pull request #2 from SantiagoJavierRubio/dev-client\n\nClient cleanup & setup', tree: { sha: 'f91a62c5a9498af36d8b66d1ab26d8d6c43482f7', url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/git/trees/f91a62c5a9498af36d8b66d1ab26d8d6c43482f7' - }, - url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/git/commits/bd75cf8acc664414df895ed5d623c3426b167321', - comment_count: 0, - verification: { - verified: true, - reason: 'valid', - signature: '-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJlZzxUCRBK7hj4Ov3rIwAATzgIAHw91oJl2TzvR6UGl+mJvjlW\nApSrRmoNMdlYApdIitgWa6NzSMd/X4gkAdXtdmX8MlMemorpz3MO+BxAoirEb9oX\nflh3+y/gelIrDy72hlE2PZjyzcCAPxeF4APa1tu3cqeVlkAWlYsUv+mgpzlc/2s6\n9auj6xYIo13qunedVSV0Gby2qneQWf15xb4AaDxb8GTwHWi3U3Dgag7QhBSP4AgJ\nTePyjYKYs85x6ACtgW86e8o7K3Mpzg1ZFrCm61hbC77Mnj9h7F4HtZXIlzuHh4j0\ndngW2ecXDC/cJI+V2yFJUIO3o0RTEXdiyBX46scwVo3XqKlopkwvk91tcZE8bgs=\n=Fhc8\n-----END PGP SIGNATURE-----\n', - payload: 'tree f91a62c5a9498af36d8b66d1ab26d8d6c43482f7\nparent 5336e9079a916c32f41e04523bd5b9b08de9e55d\nparent aee9d11a05bcda6f30ba202eda0d5532e699ea92\nauthor Santiago Javier Rubio 1701264468 -0300\ncommitter GitHub 1701264468 -0300\n\nMerge pull request #2 from SantiagoJavierRubio/dev-client\n\nClient cleanup & setup' } }, url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/bd75cf8acc664414df895ed5d623c3426b167321', html_url: 'https://github.com/SantiagoJavierRubio/git-commit-history/commit/bd75cf8acc664414df895ed5d623c3426b167321', - comments_url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/bd75cf8acc664414df895ed5d623c3426b167321/comments', - author: { - login: 'SantiagoJavierRubio', - id: 62577814, - node_id: 'MDQ6VXNlcjYyNTc3ODE0', - avatar_url: 'https://avatars.githubusercontent.com/u/62577814?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/SantiagoJavierRubio', - html_url: 'https://github.com/SantiagoJavierRubio', - followers_url: 'https://api.github.com/users/SantiagoJavierRubio/followers', - following_url: 'https://api.github.com/users/SantiagoJavierRubio/following{/other_user}', - gists_url: 'https://api.github.com/users/SantiagoJavierRubio/gists{/gist_id}', - starred_url: 'https://api.github.com/users/SantiagoJavierRubio/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/SantiagoJavierRubio/subscriptions', - organizations_url: 'https://api.github.com/users/SantiagoJavierRubio/orgs', - repos_url: 'https://api.github.com/users/SantiagoJavierRubio/repos', - events_url: 'https://api.github.com/users/SantiagoJavierRubio/events{/privacy}', - received_events_url: 'https://api.github.com/users/SantiagoJavierRubio/received_events', - type: 'User', - site_admin: false - }, - committer: { - login: 'web-flow', - id: 19864447, - node_id: 'MDQ6VXNlcjE5ODY0NDQ3', - avatar_url: 'https://avatars.githubusercontent.com/u/19864447?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/web-flow', - html_url: 'https://github.com/web-flow', - followers_url: 'https://api.github.com/users/web-flow/followers', - following_url: 'https://api.github.com/users/web-flow/following{/other_user}', - gists_url: 'https://api.github.com/users/web-flow/gists{/gist_id}', - starred_url: 'https://api.github.com/users/web-flow/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/web-flow/subscriptions', - organizations_url: 'https://api.github.com/users/web-flow/orgs', - repos_url: 'https://api.github.com/users/web-flow/repos', - events_url: 'https://api.github.com/users/web-flow/events{/privacy}', - received_events_url: 'https://api.github.com/users/web-flow/received_events', - type: 'User', - site_admin: false - }, parents: [ { sha: '5336e9079a916c32f41e04523bd5b9b08de9e55d', - url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/5336e9079a916c32f41e04523bd5b9b08de9e55d', - html_url: 'https://github.com/SantiagoJavierRubio/git-commit-history/commit/5336e9079a916c32f41e04523bd5b9b08de9e55d' + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/5336e9079a916c32f41e04523bd5b9b08de9e55d' }, { sha: 'aee9d11a05bcda6f30ba202eda0d5532e699ea92', - url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/aee9d11a05bcda6f30ba202eda0d5532e699ea92', - html_url: 'https://github.com/SantiagoJavierRubio/git-commit-history/commit/aee9d11a05bcda6f30ba202eda0d5532e699ea92' + url: 'https://api.github.com/repos/SantiagoJavierRubio/git-commit-history/commits/aee9d11a05bcda6f30ba202eda0d5532e699ea92' } - ] + ], + author: { + avatar_url: 'https://avatars.githubusercontent.com/u/62577814?v=4', + html_url: 'https://github.com/SantiagoJavierRubio' + } }] diff --git a/packages/types/index.ts b/packages/types/index.ts new file mode 100644 index 0000000..d324450 --- /dev/null +++ b/packages/types/index.ts @@ -0,0 +1 @@ +export * from './src/server.types' diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..d6f3992 --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,8 @@ +{ + "name": "types", + "version": "1.0.0", + "main": "./index.ts", + "types": "./index.ts", + "license": "MIT", + "private": true +} \ No newline at end of file diff --git a/packages/types/src/server.types.ts b/packages/types/src/server.types.ts new file mode 100644 index 0000000..92a4bd6 --- /dev/null +++ b/packages/types/src/server.types.ts @@ -0,0 +1 @@ +export type { CommitList } from '../../../apps/server/src/commits/commit.entity' diff --git a/yarn.lock b/yarn.lock index c88c3be..85ea49c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20,6 +20,13 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@anatine/zod-openapi@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@anatine/zod-openapi/-/zod-openapi-2.2.1.tgz#1a45903b47d396a0a2c890413694dd91b523f479" + integrity sha512-tYWsCc82II3XMR8lJgg8+AHgCbfsKpgzDmcceLW1SRpqiueqYVGW5AE33W4LJTl+WJ2/mET0DWD17biFO7k/Qg== + dependencies: + ts-deepmerge "^6.0.3" + "@angular-devkit/core@16.2.8": version "16.2.8" resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-16.2.8.tgz#db74f3063e7fd573be7dafd022e8dc10e43140c0" @@ -6074,7 +6081,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@7.8.1, rxjs@^7.5.5, rxjs@^7.8.1: +rxjs@7.8.1, rxjs@^7.5.5: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -6644,6 +6651,11 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-deepmerge@^6.0.3: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-6.2.0.tgz#77554381a4884d66cab799470bc2620a1c9d84e8" + integrity sha512-2qxI/FZVDPbzh63GwWIZYE7daWKtwXZYuyc8YNq0iTmMUwn4mL0jRLsp6hfFlgbdRSR4x2ppe+E86FnvEpN7Nw== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" @@ -7193,3 +7205,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@^3.22.4: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== From 1399b0193e87504367336659363a975be8f23e20 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 20:31:29 -0300 Subject: [PATCH 11/14] add pre-push test to husky --- .husky/pre-push | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .husky/pre-push diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 0000000..a9d3da0 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn test From 2e6e8c8cfad63eb716fb5d064290410d9c9cc957 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 21:00:10 -0300 Subject: [PATCH 12/14] change octokit request to getall commits at once --- apps/server/src/commits/commits.service.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index 74a5f3e..296ff46 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -8,12 +8,11 @@ export class CommitsService { constructor(private readonly octokit: OctokitClient, private readonly configService: ConfigService) {} async getAllCommits() { - const response = await this.octokit.getClient().request('GET /repos/{owner}/{repo}/commits', { + const response = await this.octokit.getClient().paginate('GET /repos/{owner}/{repo}/commits', { owner: this.configService.get('repo.owner'), repo: this.configService.get('repo.name') - }) - if (response.status !== 200) throw new HttpException('Github client error', response.status) - const parsed = commitList.safeParse(response.data) + }).catch(err => { throw new InternalServerErrorException(err) }) + const parsed = commitList.safeParse(response) if (parsed.success) return parsed.data else throw new InternalServerErrorException('Github response did not match parameters') } From aa4225304bea7f8a9c88b4592fe8175e6a92fa19 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Wed, 29 Nov 2023 22:35:05 -0300 Subject: [PATCH 13/14] implement react-table to display commit data --- apps/client/package.json | 5 +- .../pages/Home/CommitTable/CommitTable.tsx | 52 +++++++++++++++++++ apps/client/src/pages/Home/index.tsx | 7 +-- apps/server/src/commits/commit.entity.ts | 1 + apps/server/src/commits/commits.service.ts | 2 +- packages/types/src/server.types.ts | 2 +- yarn.lock | 12 +++++ 7 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 apps/client/src/pages/Home/CommitTable/CommitTable.tsx diff --git a/apps/client/package.json b/apps/client/package.json index 0178a4c..0a44c71 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@tanstack/react-query": "^5.9.0", + "@tanstack/react-table": "^8.10.7", "axios": "^1.6.2", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -28,8 +29,8 @@ "eslint-plugin-tailwindcss": "^3.13.0", "postcss": "^8.4.31", "tailwindcss": "^3.3.5", + "types": "*", "typescript": "^5.2.2", - "vite": "^5.0.0", - "types": "*" + "vite": "^5.0.0" } } diff --git a/apps/client/src/pages/Home/CommitTable/CommitTable.tsx b/apps/client/src/pages/Home/CommitTable/CommitTable.tsx new file mode 100644 index 0000000..c0e0238 --- /dev/null +++ b/apps/client/src/pages/Home/CommitTable/CommitTable.tsx @@ -0,0 +1,52 @@ +/* eslint-disable no-console */ +import { CommitListElement } from 'types' +import { createColumnHelper, useReactTable, getCoreRowModel, flexRender, getPaginationRowModel } from '@tanstack/react-table' + +const columnHelper = createColumnHelper() +const columns = [ + columnHelper.accessor('sha', { header: () => Id, cell: props => {props.getValue().substring(0, 7)} }), + columnHelper.accessor('commit.author.email', { id: 'author', header: () => Author, cell: props => {props.row.original.commit.author.name} }), + columnHelper.display({ id: 'message', header: () => Message, cell: props => {props.row.original.commit.message} }), + columnHelper.accessor('commit.author.date', { id: 'date', header: () => Date, cell: props => {new Date(props.getValue()).toLocaleDateString()} }) +] +export default function CommitTable({ commits }: { commits: CommitListElement[] }) { + const table = useReactTable({ data: commits, columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel() }) + return ( + <> + + + {table.getHeaderGroups().map(hGroup => ( + + {hGroup.headers.map(header => ( + + ))} + + ))} + + + {table.getRowModel().rows.map(row => ( + console.log(row.getValue('sha'))} > + {row.getVisibleCells().map(cell => ( + + ))} + + ))} + +
+ {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} +
+ {flexRender(cell.column.columnDef.cell, cell.getContext())} +
+
+ + + + +
+ + ) +} diff --git a/apps/client/src/pages/Home/index.tsx b/apps/client/src/pages/Home/index.tsx index 891c23c..dcea808 100644 --- a/apps/client/src/pages/Home/index.tsx +++ b/apps/client/src/pages/Home/index.tsx @@ -1,14 +1,15 @@ import getCommits from '@/api/getCommits' import { useQuery } from '@tanstack/react-query' -import { CommitList } from 'types' +import { CommitListElement } from 'types' +import CommitTable from './CommitTable/CommitTable' export default function Home() { - const commitQuery = useQuery({ + const commitQuery = useQuery({ queryKey: ['commits'], queryFn: getCommits }) return ( -
Home {commitQuery.isSuccess ? commitQuery.data[0].url : ''}
+
{commitQuery.isSuccess ? :

loadin

}
) } diff --git a/apps/server/src/commits/commit.entity.ts b/apps/server/src/commits/commit.entity.ts index 68fb719..6abe26f 100644 --- a/apps/server/src/commits/commit.entity.ts +++ b/apps/server/src/commits/commit.entity.ts @@ -30,6 +30,7 @@ export const basicCommitSchema = z.object({ export const commitList = z.array(basicCommitSchema) +export type CommitListElement = z.infer export type CommitList = z.infer export const commitApiSchema = generateSchema(basicCommitSchema) diff --git a/apps/server/src/commits/commits.service.ts b/apps/server/src/commits/commits.service.ts index 296ff46..f69cb96 100644 --- a/apps/server/src/commits/commits.service.ts +++ b/apps/server/src/commits/commits.service.ts @@ -1,4 +1,4 @@ -import { HttpException, Injectable, InternalServerErrorException } from '@nestjs/common' +import { Injectable, InternalServerErrorException } from '@nestjs/common' import { ConfigService } from '@nestjs/config' import { OctokitClient } from 'src/octokit/octokitClient' import { commitList } from './commit.entity' diff --git a/packages/types/src/server.types.ts b/packages/types/src/server.types.ts index 92a4bd6..b23b63e 100644 --- a/packages/types/src/server.types.ts +++ b/packages/types/src/server.types.ts @@ -1 +1 @@ -export type { CommitList } from '../../../apps/server/src/commits/commit.entity' +export type { CommitList, CommitListElement } from '../../../apps/server/src/commits/commit.entity' diff --git a/yarn.lock b/yarn.lock index 85ea49c..fa8cd54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1294,6 +1294,18 @@ dependencies: "@tanstack/query-core" "5.8.7" +"@tanstack/react-table@^8.10.7": + version "8.10.7" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.10.7.tgz#733f4bee8cf5aa19582f944dd0fd3224b21e8c94" + integrity sha512-bXhjA7xsTcsW8JPTTYlUg/FuBpn8MNjiEPhkNhIGCUR6iRQM2+WEco4OBpvDeVcR9SE+bmWLzdfiY7bCbCSVuA== + dependencies: + "@tanstack/table-core" "8.10.7" + +"@tanstack/table-core@8.10.7": + version "8.10.7" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.10.7.tgz#577e8a635048875de4c9d6d6a3c21d26ff9f9d08" + integrity sha512-KQk5OMg5OH6rmbHZxuNROvdI+hKDIUxANaHlV+dPlNN7ED3qYQ/WkpY2qlXww1SIdeMlkIhpN/2L00rof0fXFw== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" From 8e6beae1b5b76d335250a2b661f50a258ace2b27 Mon Sep 17 00:00:00 2001 From: Santiago Javier Rubio Date: Thu, 30 Nov 2023 00:41:58 -0300 Subject: [PATCH 14/14] add sorting and filtering to commit tables @client --- apps/client/src/hooks/useDebounce.tsx | 14 +++++ .../pages/Home/CommitTable/CommitTable.tsx | 58 +++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 apps/client/src/hooks/useDebounce.tsx diff --git a/apps/client/src/hooks/useDebounce.tsx b/apps/client/src/hooks/useDebounce.tsx new file mode 100644 index 0000000..1f4660c --- /dev/null +++ b/apps/client/src/hooks/useDebounce.tsx @@ -0,0 +1,14 @@ +import { useState, useEffect } from 'react' + +export default function useDebounce(value: T, delay: number) { + const [debouncedValue, setDebouncedValue] = useState(value) + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value) + }, delay) + return () => { + clearTimeout(handler) + } + }, [value, delay]) + return debouncedValue +} diff --git a/apps/client/src/pages/Home/CommitTable/CommitTable.tsx b/apps/client/src/pages/Home/CommitTable/CommitTable.tsx index c0e0238..503fe47 100644 --- a/apps/client/src/pages/Home/CommitTable/CommitTable.tsx +++ b/apps/client/src/pages/Home/CommitTable/CommitTable.tsx @@ -1,25 +1,73 @@ /* eslint-disable no-console */ +import { ChangeEvent, useState } from 'react' import { CommitListElement } from 'types' -import { createColumnHelper, useReactTable, getCoreRowModel, flexRender, getPaginationRowModel } from '@tanstack/react-table' +import { + createColumnHelper, + useReactTable, + getCoreRowModel, + flexRender, + getPaginationRowModel, + getSortedRowModel, + getFilteredRowModel, + type SortingState +} from '@tanstack/react-table' + +import useDebounce from '@/hooks/useDebounce' const columnHelper = createColumnHelper() const columns = [ columnHelper.accessor('sha', { header: () => Id, cell: props => {props.getValue().substring(0, 7)} }), - columnHelper.accessor('commit.author.email', { id: 'author', header: () => Author, cell: props => {props.row.original.commit.author.name} }), - columnHelper.display({ id: 'message', header: () => Message, cell: props => {props.row.original.commit.message} }), + columnHelper.group({ + id: 'author', + columns: [ + columnHelper.display({ id: 'avatar', cell: props => {`${props.row.original.commit.author.name}'s }), + columnHelper.accessor('commit.author.name', { id: 'name', header: () => Author, cell: props => {props.getValue()} }), + columnHelper.accessor('commit.author.email', { id: 'email', header: () => null, cell: () => null }) + ] + }), + columnHelper.accessor('commit.message', { id: 'message', enableSorting: false, header: () => Message, cell: props => {props.row.original.commit.message} }), columnHelper.accessor('commit.author.date', { id: 'date', header: () => Date, cell: props => {new Date(props.getValue()).toLocaleDateString()} }) ] export default function CommitTable({ commits }: { commits: CommitListElement[] }) { - const table = useReactTable({ data: commits, columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel() }) + const [sorting, setSorting] = useState([]) + const [filtering, setFiltering] = useState('') + + const filter = useDebounce(filtering, 250) + + const table = useReactTable({ + data: commits, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + state: { + sorting, + globalFilter: filter + }, + onSortingChange: setSorting, + onGlobalFilterChange: setFiltering + }) + + const handleSortInput = (e: ChangeEvent) => { + setFiltering(e.target.value) + } + return ( <> + +

{table.getState().pagination.pageIndex + 1} of {table.getPageCount()}

{table.getHeaderGroups().map(hGroup => ( {hGroup.headers.map(header => ( ))}
- {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} + {header.isPlaceholder ? null : ( +
+ {flexRender(header.column.columnDef.header, header.getContext())} +
+ )}