diff --git a/.github/workflows/cd.yml b/.github/workflows/ci-cd.yml similarity index 67% rename from .github/workflows/cd.yml rename to .github/workflows/ci-cd.yml index 021110bd4..28baee64e 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,5 +1,4 @@ -name: CD - +name: CI_CD on: # push: # branches: @@ -8,7 +7,97 @@ on: workflow_dispatch: jobs: + build_image: + runs-on: ubuntu-latest + + env: + DOCKER_HUB: ${{ secrets.DOCKER_HUB }} + DOCKERFILE: ci/dockerfile + + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Get git short sha + id: git + run: | + echo "short_sha=$(git rev-parse --short $GITHUB_SHA)" >> "$GITHUB_OUTPUT" + + - name: Get latest version of package json + id: version + uses: martinbeentjes/npm-get-version-action@main + + - name: Git + run: | + echo Short sha: ${{ steps.git.outputs.short_sha }} + echo Version is: ${{ steps.version.outputs.current-version }} + + - name: Environment + run: | + echo DOCKER_HUB is: ${{ env.DOCKER_HUB }} + echo DOCKERFILE is: ${{ env.DOCKERFILE }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx for Builder + uses: docker/setup-buildx-action@v3 + id: builder + + - name: Set up Docker Buildx for Main + uses: docker/setup-buildx-action@v3 + id: main + + - name: Builder name + run: echo ${{ steps.builder.outputs.name }} + + - name: Main name + run: echo ${{ steps.main.outputs.name }} + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build builder + uses: docker/build-push-action@v4 + with: + builder: ${{ steps.builder.outputs.name }} + file: ${{ env.DOCKERFILE }} + target: builder + + - name: Build main and push + uses: docker/build-push-action@v4 + if: ${{ github.ref_name == 'main' }} + with: + builder: ${{ steps.main.outputs.name }} + file: ${{ env.DOCKERFILE }} + build-args: | + NODE_ENV=production + target: main + tags: | + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:latest + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:main_v${{ steps.version.outputs.current-version }} + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:main_v${{ steps.version.outputs.current-version }}_sha-${{ steps.git.outputs.short_sha }} + push: true + + - name: Build staging and push + uses: docker/build-push-action@v4 + if: ${{ github.ref_name == 'staging' }} + with: + builder: ${{ steps.main.outputs.name }} + file: ${{ env.DOCKERFILE }} + build-args: | + NODE_ENV=staging + target: main + tags: | + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:staging_v${{ steps.version.outputs.current-version }} + ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:staging_v${{ steps.version.outputs.current-version }}_sha-${{ steps.git.outputs.short_sha }} + push: true + deploy_production: + needs: [ build_image ] runs-on: ubuntu-latest if: ${{ github.ref_name == 'main' }} environment: production @@ -91,8 +180,8 @@ jobs: user: ${{ env.SSH_USER }} key: ${{ env.SSH_PRIVATE_KEY }} - deploy_staging: + needs: [ build_image ] runs-on: ubuntu-latest if: ${{ github.ref_name == 'staging' }} environment: staging diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 2ea2b5088..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: CI -on: - # pull_request: - # branches: - # - main - # - staging - workflow_dispatch: - -jobs: - build_image: - runs-on: ubuntu-latest - - env: - DOCKER_HUB: ${{ secrets.DOCKER_HUB }} - DOCKERFILE: ci/dockerfile - - steps: - - name: Git checkout - uses: actions/checkout@v3 - - - name: Get git short sha - id: git - run: | - echo "short_sha=$(git rev-parse --short $GITHUB_SHA)" >> "$GITHUB_OUTPUT" - - - name: Get latest version of package json - id: version - uses: martinbeentjes/npm-get-version-action@main - - - name: Git - run: | - echo Short sha: ${{ steps.git.outputs.short_sha }} - echo Version is: ${{ steps.version.outputs.current-version }} - - - name: Environment - run: | - echo DOCKER_HUB is: ${{ env.DOCKER_HUB }} - echo DOCKERFILE is: ${{ env.DOCKERFILE }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx for Builder - uses: docker/setup-buildx-action@v3 - id: builder - - - name: Set up Docker Buildx for Main - uses: docker/setup-buildx-action@v3 - id: main - - - name: Builder name - run: echo ${{ steps.builder.outputs.name }} - - - name: Main name - run: echo ${{ steps.main.outputs.name }} - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build builder - uses: docker/build-push-action@v4 - with: - builder: ${{ steps.builder.outputs.name }} - file: ${{ env.DOCKERFILE }} - target: builder - - - name: Build main and push - uses: docker/build-push-action@v4 - if: ${{ github.ref_name == 'main' }} - with: - builder: ${{ steps.main.outputs.name }} - file: ${{ env.DOCKERFILE }} - build-args: | - NODE_ENV=production - target: main - tags: | - ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:latest - ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:main_v${{ steps.version.outputs.current-version }} - ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:main_v${{ steps.version.outputs.current-version }}_sha-${{ steps.git.outputs.short_sha }} - push: true - - - name: Build staging and push - uses: docker/build-push-action@v4 - if: ${{ github.ref_name == 'staging' }} - with: - builder: ${{ steps.main.outputs.name }} - file: ${{ env.DOCKERFILE }} - build-args: | - NODE_ENV=staging - target: main - tags: | - ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:staging_v${{ steps.version.outputs.current-version }} - ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_HUB }}:staging_v${{ steps.version.outputs.current-version }}_sha-${{ steps.git.outputs.short_sha }} - push: true diff --git a/src/common/api-key/controllers/api-key.admin.controller.ts b/src/common/api-key/controllers/api-key.admin.controller.ts index 3ca8a6795..498218ef1 100644 --- a/src/common/api-key/controllers/api-key.admin.controller.ts +++ b/src/common/api-key/controllers/api-key.admin.controller.ts @@ -133,6 +133,7 @@ export class ApiKeyAdminController { offset: _offset, }, order: _order, + plainObject: true, }); const total: number = await this.apiKeyService.getTotal(find); const totalPage: number = this.paginationService.totalPage( diff --git a/src/common/dashboard/constants/dashboard.doc.constant.ts b/src/common/dashboard/constants/dashboard.doc.constant.ts index b0d4036cb..8331be0e7 100644 --- a/src/common/dashboard/constants/dashboard.doc.constant.ts +++ b/src/common/dashboard/constants/dashboard.doc.constant.ts @@ -6,7 +6,7 @@ export const DashboardDocQueryStartDate = [ allowEmptyValue: true, required: false, type: 'string', - example: faker.date.recent().toString(), + example: faker.date.past(), }, ]; @@ -16,6 +16,6 @@ export const DashboardDocQueryEndDate = [ allowEmptyValue: true, required: false, type: 'string', - example: faker.date.recent().toString(), + example: faker.date.recent(), }, ]; diff --git a/src/common/dashboard/services/dashboard.service.ts b/src/common/dashboard/services/dashboard.service.ts index 39f507d43..74f61492d 100644 --- a/src/common/dashboard/services/dashboard.service.ts +++ b/src/common/dashboard/services/dashboard.service.ts @@ -15,23 +15,27 @@ export class DashboardService implements IDashboardService { getStartAndEndDate(date?: DashboardDto): IDashboardStartAndEndDate { const today = this.helperDateService.create(); + if (!date) { + const startDate = this.helperDateService.startOfMonth(today); + const endDate = this.helperDateService.endOfMonth(today); + + return { + startDate, + endDate, + }; + } let { startDate, endDate } = date; - if (!startDate && !endDate) { - startDate = this.helperDateService.startOfYear(today); - endDate = this.helperDateService.endOfYear(today); + if (!startDate) { + startDate = this.helperDateService.startOfMonth(); + } else { + startDate = this.helperDateService.startOfDay(startDate); + } + + if (!endDate) { + endDate = this.helperDateService.endOfMonth(); } else { - if (!startDate) { - startDate = this.helperDateService.startOfYear(); - } else { - startDate = this.helperDateService.startOfDay(startDate); - } - - if (!endDate) { - endDate = this.helperDateService.endOfYear(); - } else { - endDate = this.helperDateService.endOfDay(endDate); - } + endDate = this.helperDateService.endOfDay(endDate); } return { diff --git a/src/common/response/interceptors/response.default.interceptor.ts b/src/common/response/interceptors/response.default.interceptor.ts index 94163ba49..39f523f5e 100644 --- a/src/common/response/interceptors/response.default.interceptor.ts +++ b/src/common/response/interceptors/response.default.interceptor.ts @@ -102,11 +102,7 @@ export class ResponseDefaultInterceptor if (responseData) { const { _metadata } = responseData; - data = responseData.data - ? JSON.parse( - JSON.stringify(responseData.data ?? {}) - ) - : undefined; + data = responseData.data; if (data && classSerialization) { data = plainToInstance( diff --git a/src/common/response/interceptors/response.paging.interceptor.ts b/src/common/response/interceptors/response.paging.interceptor.ts index 4979470a0..f5adfb71e 100644 --- a/src/common/response/interceptors/response.paging.interceptor.ts +++ b/src/common/response/interceptors/response.paging.interceptor.ts @@ -108,9 +108,7 @@ export class ResponsePagingInterceptor } const { _metadata } = responseData; - data = responseData.data - ? JSON.parse(JSON.stringify(responseData.data ?? {})) - : undefined; + data = responseData.data; if (classSerialization) { data = plainToInstance( diff --git a/src/modules/role/controllers/role.admin.controller.ts b/src/modules/role/controllers/role.admin.controller.ts index 75ce8f5b6..ac0db30b8 100644 --- a/src/modules/role/controllers/role.admin.controller.ts +++ b/src/modules/role/controllers/role.admin.controller.ts @@ -124,6 +124,7 @@ export class RoleAdminController { offset: _offset, }, order: _order, + plainObject: true, }); const total: number = await this.roleService.getTotal(find); diff --git a/src/modules/setting/controllers/setting.public.controller.ts b/src/modules/setting/controllers/setting.public.controller.ts index 3026ca613..f4aecb467 100644 --- a/src/modules/setting/controllers/setting.public.controller.ts +++ b/src/modules/setting/controllers/setting.public.controller.ts @@ -81,6 +81,7 @@ export class SettingPublicController { offset: _offset, }, order: _order, + plainObject: true, } ); const total: number = await this.settingService.getTotal(find); diff --git a/src/modules/user/controllers/user.admin.controller.ts b/src/modules/user/controllers/user.admin.controller.ts index b60c59bdb..3e9c2edb9 100644 --- a/src/modules/user/controllers/user.admin.controller.ts +++ b/src/modules/user/controllers/user.admin.controller.ts @@ -157,6 +157,7 @@ export class UserAdminController { offset: _offset, }, order: _order, + plainObject: true, }); const total: number = await this.userService.getTotal(find); const totalPage: number = this.paginationService.totalPage( @@ -186,7 +187,7 @@ export class UserAdminController { async get(@GetUser() user: UserDoc): Promise { const userWithRole: IUserDoc = await this.userService.joinWithRole(user); - return { data: userWithRole }; + return { data: userWithRole.toObject() }; } @UserAdminCreateDoc() @@ -398,7 +399,12 @@ export class UserAdminController { @HttpCode(HttpStatus.OK) @Post('/export') async export(): Promise { - const users: IUserEntity[] = await this.userService.findAll({}); + const users: IUserEntity[] = await this.userService.findAll( + {}, + { + plainObject: true, + } + ); return { data: users }; } diff --git a/src/modules/user/controllers/user.auth.controller.ts b/src/modules/user/controllers/user.auth.controller.ts index df709d823..b0dc49502 100644 --- a/src/modules/user/controllers/user.auth.controller.ts +++ b/src/modules/user/controllers/user.auth.controller.ts @@ -482,7 +482,7 @@ export class UserAuthController { async profile(@GetUser() user: UserDoc): Promise { const userWithRole: IUserDoc = await this.userService.joinWithRole(user); - return { data: userWithRole }; + return { data: userWithRole.toObject() }; } @UserAuthUpdateProfileDoc() diff --git a/test/dashboard/dashboard.service.spec.ts b/test/dashboard/dashboard.service.spec.ts index d20721581..45e0744cb 100644 --- a/test/dashboard/dashboard.service.spec.ts +++ b/test/dashboard/dashboard.service.spec.ts @@ -24,57 +24,115 @@ describe('DashboardService', () => { }); describe('getStartAndEndDate', () => { - it('should return current year start and end dates if no start and end dates are provided', async () => { - const startDate = new Date(new Date().setMonth(0, 1)); - const endDate = new Date(new Date().setMonth(11, 31)); - const expectedStartDate = new Date(startDate.setHours(0, 0, 0, 0)); - const expectedEndDate = new Date(endDate.setHours(23, 59, 59, 999)); - - const result = service.getStartAndEndDate({}); - - expect(result.startDate).toEqual(expectedStartDate); - expect(result.endDate).toEqual(expectedEndDate); + it('should return current month start and end dates if no start and end dates are provided', async () => { + const today = new Date(); + const startDate = new Date( + today.getFullYear(), + today.getMonth(), + 1, + 0, + 0, + 0, + 0 + ); + const endDate = new Date( + today.getFullYear(), + today.getMonth() + 1, + 0, + 23, + 59, + 59, + 999 + ); + + const result = service.getStartAndEndDate(); + + expect(result.startDate).toEqual(startDate); + expect(result.endDate).toEqual(endDate); }); it('should return start and end dates as provided', async () => { - const startDate = new Date(2022, 5, 15); - const endDate = new Date(2022, 5, 20); - const expectedStartDate = new Date(startDate.setHours(0, 0, 0, 0)); - const expectedEndDate = new Date(endDate.setHours(23, 59, 59, 999)); + const today = new Date(); + const startDate = new Date( + today.getFullYear(), + today.getMonth(), + 1, + 0, + 0, + 0, + 0 + ); + const endDate = new Date( + today.getFullYear(), + today.getMonth() + 1, + 0, + 23, + 59, + 59, + 999 + ); const result = service.getStartAndEndDate({ startDate, endDate, }); - expect(result.startDate).toEqual(expectedStartDate); - expect(result.endDate).toEqual(expectedEndDate); + expect(result.startDate).toEqual(startDate); + expect(result.endDate).toEqual(endDate); }); - it('should return start date as current day of year if not provided', async () => { + it('should return start date as current day of month if not provided', async () => { const today = new Date(); - const endDate = new Date(2022, 5, 15); - const startDate = new Date(today.getFullYear(), 0, 1); - const expectedStartDate = new Date(startDate.setHours(0, 0, 0, 0)); - const expectedEndDate = new Date(endDate.setHours(23, 59, 59, 999)); + const startDate = new Date( + today.getFullYear(), + today.getMonth(), + 1, + 0, + 0, + 0, + 0 + ); + const endDate = new Date( + today.getFullYear(), + today.getMonth() + 1, + 0, + 23, + 59, + 59, + 999 + ); const result = service.getStartAndEndDate({ endDate }); - expect(result.startDate).toEqual(expectedStartDate); - expect(result.endDate).toEqual(expectedEndDate); + expect(result.startDate).toEqual(startDate); + expect(result.endDate).toEqual(endDate); }); - it('should return end date as current day of year if not provided', async () => { + it('should return end date as current day of month if not provided', async () => { const today = new Date(); - const startDate = new Date(2022, 5, 15); - const endDate = new Date(today.getFullYear(), 11, 31); - const expectedStartDate = new Date(startDate.setHours(0, 0, 0, 0)); - const expectedEndDate = new Date(endDate.setHours(23, 59, 59, 999)); + const startDate = new Date( + today.getFullYear(), + today.getMonth(), + 1, + 0, + 0, + 0, + 0 + ); + const endDate = new Date( + today.getFullYear(), + today.getMonth() + 1, + 0, + 23, + 59, + 59, + 999 + ); const result = service.getStartAndEndDate({ startDate }); - expect(result.startDate).toEqual(expectedStartDate); - expect(result.endDate).toEqual(expectedEndDate); + expect(result.startDate).toEqual(startDate); + expect(result.endDate).toEqual(endDate); }); });