From df0023704575e436cec2ec3d4b0f58e22f441a2c Mon Sep 17 00:00:00 2001 From: Chiyoung Jeong Date: Fri, 22 Sep 2023 19:19:20 +0900 Subject: [PATCH 01/13] feat: sign in callback (#51) * chore: remove redundant code * feat: add callback url when users sign in * feat: update openapi.type, remove callback for signIn function * chore: remove openapi.type in eslintignore --- .eslintignore | 1 - .prettierignore | 2 +- apps/api/src/domains/auth/auth.controller.ts | 6 +- apps/api/src/domains/auth/auth.service.ts | 5 +- apps/web/.eslintrc.js | 2 +- apps/web/next.config.js | 1 + .../templates/MainTemplate/MainTemplate.tsx | 1 - apps/web/src/contexts/user.context.tsx | 21 +- apps/web/src/middleware.ts | 12 +- apps/web/src/pages/auth/sign-in.tsx | 7 + apps/web/src/types/api.type.ts | 10 +- apps/web/src/types/openapi.type.ts | 52 ++--- .../src/components/components.css | 8 +- .../ufb-tailwind/src/components/drawer.css | 190 ------------------ .../ufb-tailwind/src/components/dropdown.css | 57 ------ .../ufb-tailwind/src/components/header.css | 3 - 16 files changed, 77 insertions(+), 301 deletions(-) delete mode 100644 packages/ufb-tailwind/src/components/drawer.css delete mode 100644 packages/ufb-tailwind/src/components/dropdown.css delete mode 100644 packages/ufb-tailwind/src/components/header.css diff --git a/.eslintignore b/.eslintignore index b5f9ae21c..ec0c01863 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,2 @@ jest.config.* -openapi.type.ts api.type.ts \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 0f9ac9875..af41fa5aa 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,6 @@ migrations -openapi.type.ts + api.type.ts dist diff --git a/apps/api/src/domains/auth/auth.controller.ts b/apps/api/src/domains/auth/auth.controller.ts index fb8e6ccf7..27ddedb12 100644 --- a/apps/api/src/domains/auth/auth.controller.ts +++ b/apps/api/src/domains/auth/auth.controller.ts @@ -28,6 +28,7 @@ import { ApiBody, ApiCreatedResponse, ApiOkResponse, + ApiQuery, ApiTags, } from '@nestjs/swagger'; @@ -95,10 +96,11 @@ export class AuthController { } @UseGuards(UseOAuthGuard) + @ApiQuery({ name: 'callback_url', type: String, required: false }) @ApiOkResponse({ type: OAuthLoginUrlResponseDto }) @Get('signIn/oauth/loginURL') - async redirectToLoginURL() { - return { url: await this.authService.getOAuthLoginURL() }; + async redirectToLoginURL(@Query('callback_url') callback_url?: string) { + return { url: await this.authService.getOAuthLoginURL(callback_url) }; } @UseGuards(UseOAuthGuard) diff --git a/apps/api/src/domains/auth/auth.service.ts b/apps/api/src/domains/auth/auth.service.ts index 91fb9b627..c541a8b38 100644 --- a/apps/api/src/domains/auth/auth.service.ts +++ b/apps/api/src/domains/auth/auth.service.ts @@ -203,7 +203,7 @@ export class AuthService { return false; } - async getOAuthLoginURL() { + async getOAuthLoginURL(callback_url?: string) { const { useOAuth, oauthConfig } = await this.tenantService.findOne(); if (!useOAuth) { @@ -214,7 +214,8 @@ export class AuthService { } const params = new URLSearchParams({ - redirect_uri: this.REDIRECT_URI, + redirect_uri: + this.REDIRECT_URI + callback_url ? '?callback_url=' + callback_url : '', client_id: oauthConfig.clientId, response_type: 'code', state: crypto.randomBytes(10).toString('hex'), diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js index b29d25037..bb2cfaf6a 100644 --- a/apps/web/.eslintrc.js +++ b/apps/web/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { root: true, extends: ['next', 'ufb'], - ignorePatterns: ['.next', '.turbo', 'openapi.type.ts', 'api.type.ts'], + ignorePatterns: ['.next', '.turbo', 'api.type.ts'], rules: { '@next/next/no-html-link-for-pages': 'off', 'react-hooks/exhaustive-deps': 'off', diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 356a44a2d..1717ac9be 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -29,6 +29,7 @@ const nextConfig = { ignoreDuringBuilds: true, }, transpilePackages: ['@ufb/ui'], + compiler: { removeConsole: true }, }; module.exports = nextConfig; diff --git a/apps/web/src/components/templates/MainTemplate/MainTemplate.tsx b/apps/web/src/components/templates/MainTemplate/MainTemplate.tsx index 40ba184dc..d00a157de 100644 --- a/apps/web/src/components/templates/MainTemplate/MainTemplate.tsx +++ b/apps/web/src/components/templates/MainTemplate/MainTemplate.tsx @@ -28,7 +28,6 @@ const MainTemplate: React.FC = ({ children }) => {
{Path.hasSideNav(router.pathname) && } - {/*
*/}
= ({ })(); }, []); - const signIn = useCallback(async (body: ISignInInput) => { + const signIn = async (body: ISignInInput) => { try { const { data } = await axios.post('/api/login', body); setJwt(data); - router.push({ pathname: Path.MAIN }); + if (router.query.callback_url) { + router.push(router.query.callback_url as string); + } else { + router.push({ pathname: Path.MAIN }); + } } catch (error) { throw (error as AxiosError).response?.data as IFetchError; } - }, []); - const signInOAuth = useCallback(async ({ code }: ISignInOAuthInput) => { + }; + + const signInOAuth = async ({ code }: ISignInOAuthInput) => { try { const { data } = await axios.post('/api/oauth', { code }); setJwt(data); - router.push({ pathname: Path.MAIN }); + if (router.query.callback_url) { + router.push(router.query.callback_url as string); + } else { + router.push({ pathname: Path.MAIN }); + } } catch (error) { throw (error as AxiosError).response?.data as IFetchError; } - }, []); + }; const signUp = useCallback(async ({ email, password }: ISignUpInput) => { await client.post({ diff --git a/apps/web/src/middleware.ts b/apps/web/src/middleware.ts index 4c8152be8..87e8ec744 100644 --- a/apps/web/src/middleware.ts +++ b/apps/web/src/middleware.ts @@ -34,18 +34,16 @@ export async function middleware(req: NextRequest) { return NextResponse.redirect(new URL(Path.MAIN, req.url)); } + const requestPath = `${req.nextUrl.pathname}${req.nextUrl.search}`; if (!session.jwt && isProtected) { - return NextResponse.redirect(new URL(Path.SIGN_IN, req.url)); + return NextResponse.redirect( + new URL(Path.SIGN_IN + '?callback_url=' + requestPath, req.url), + ); } if (req.nextUrl.locale === 'default') { const locale = req.cookies.get('NEXT_LOCALE')?.value || DEFAULT_LOCALE; - return NextResponse.redirect( - new URL( - `/${locale}${req.nextUrl.pathname}${req.nextUrl.search}`, - req.url, - ), - ); + return NextResponse.redirect(new URL(`/${locale}${requestPath}`, req.url)); } return res; diff --git a/apps/web/src/pages/auth/sign-in.tsx b/apps/web/src/pages/auth/sign-in.tsx index b7a84f34d..d373101de 100644 --- a/apps/web/src/pages/auth/sign-in.tsx +++ b/apps/web/src/pages/auth/sign-in.tsx @@ -20,6 +20,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import Image from 'next/image'; import Link from 'next/link'; import { useRouter } from 'next/router'; +import { useMemo } from 'react'; import { useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { z } from 'zod'; @@ -49,6 +50,11 @@ const SignInPage: NextPageWithLayout = () => { const router = useRouter(); const { signIn } = useUser(); const { tenant } = useTenant(); + const callback_url = useMemo(() => { + return router.query.callback_url + ? (router.query.callback_url as string) + : undefined; + }, [router.query]); const { handleSubmit, register, formState, setError } = useForm({ resolver: zodResolver(schema), @@ -72,6 +78,7 @@ const SignInPage: NextPageWithLayout = () => { const { data } = useOAIQuery({ path: '/api/auth/signIn/oauth/loginURL', queryOptions: { enabled: tenant?.useOAuth ?? false }, + variables: { callback_url }, }); return ( diff --git a/apps/web/src/types/api.type.ts b/apps/web/src/types/api.type.ts index 4bcb03ae0..151e27dc0 100644 --- a/apps/web/src/types/api.type.ts +++ b/apps/web/src/types/api.type.ts @@ -165,7 +165,7 @@ export interface paths { get: operations["HealthController_check"]; }; "/api/channels/{channelId}/migration": { - post: operations["MigrationController_createOption"]; + post: operations["MigrationController_migrate"]; }; "/api/projects/{projectId}/issue-tracker": { get: operations["IssueTrackerController_findOne"]; @@ -372,6 +372,7 @@ export interface components { isPrivate: boolean; isRestrictDomain: boolean; allowDomains: (string)[]; + useEmailVerification: boolean; oauthConfig: components["schemas"]["OAuthConfigResponseDto"] | null; }; CountFeedbacksByTenantIdResponseDto: { @@ -751,6 +752,11 @@ export interface operations { }; }; AuthController_redirectToLoginURL: { + parameters: { + query?: { + callback_url?: string; + }; + }; responses: { 200: { content: { @@ -1654,7 +1660,7 @@ export interface operations { }; }; }; - MigrationController_createOption: { + MigrationController_migrate: { parameters: { path: { channelId: number; diff --git a/apps/web/src/types/openapi.type.ts b/apps/web/src/types/openapi.type.ts index 314496b09..b6eccc1df 100644 --- a/apps/web/src/types/openapi.type.ts +++ b/apps/web/src/types/openapi.type.ts @@ -1,8 +1,23 @@ +/** + * Copyright 2023 LINE Corporation + * + * LINE Corporation licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ import type { O } from 'ts-toolbelt'; import type { paths } from '@/types/api.type'; -export type OAIPathKeys = keyof paths; +export type OAIPathKeys = keyof paths; export type OAIMethods = 'get' | 'put' | 'post' | 'delete' | 'patch'; export type OAIMethodPathKeys = O.SelectKeys< @@ -10,28 +25,15 @@ export type OAIMethodPathKeys = O.SelectKeys< Record >; - export type OAIPathParameters< TPath extends OAIPathKeys, TMethod extends OAIMethods, -> = O.Path extends Record< - string, - unknown -> - ? O.Path - : undefined; - +> = O.Path; export type OAIQueryParameters< TPath extends OAIPathKeys, TMethod extends OAIMethods, -> = O.Path extends Record< - string, - unknown -> - ? O.Path - : undefined; - +> = O.Path; export type OAIRequestBody< TPath extends OAIPathKeys, @@ -41,7 +43,6 @@ export type OAIRequestBody< [TPath, TMethod, 'requestBody', 'content', 'application/json'] >; - export type OAIParameters< TPath extends OAIPathKeys, TMethod extends OAIMethods, @@ -52,16 +53,19 @@ export type OAIParameters< OAIQueryParameters > : OAIPathParameters - : OAIQueryParameters extends Record + : OAIQueryParameters extends + | Record + | undefined ? OAIQueryParameters : undefined; - -export type OAIResponse = - O.Path< - paths, - [TPath, TMethod, 'responses', 200, 'content', 'application/json'] - >; +export type OAIResponse< + TPath extends keyof paths, + TMethod extends OAIMethods, +> = O.Path< + paths, + [TPath, TMethod, 'responses', 200, 'content', 'application/json'] +>; export type OAIMutationResponse< TPath extends keyof paths, diff --git a/packages/ufb-tailwind/src/components/components.css b/packages/ufb-tailwind/src/components/components.css index 38073ee37..cf285ddd3 100644 --- a/packages/ufb-tailwind/src/components/components.css +++ b/packages/ufb-tailwind/src/components/components.css @@ -1,10 +1,10 @@ @import 'tailwindcss/utilities'; @import './button.css'; -@import './icon-button.css'; @import './checkbox.css'; +@import './icon-button.css'; @import './input.css'; -@import './table.css'; -@import './typography.css'; @import './radio.css'; -@import './toggle.css'; \ No newline at end of file +@import './table.css'; +@import './toggle.css'; +@import './typography.css'; \ No newline at end of file diff --git a/packages/ufb-tailwind/src/components/drawer.css b/packages/ufb-tailwind/src/components/drawer.css deleted file mode 100644 index f34290ae8..000000000 --- a/packages/ufb-tailwind/src/components/drawer.css +++ /dev/null @@ -1,190 +0,0 @@ -.drawer { - --header-height: 48px; - @apply grid overflow-hidden w-full; - - height: calc(100vh - var(--header-height)); - height: calc(100dvh - var(--header-height)); - - &.drawer-end { - direction: rtl; - } - &.drawer-end > * { - direction: ltr; - } - &.drawer-end > .drawer-toggle { - & ~ .drawer-side > .drawer-overlay + * { - @apply translate-x-full justify-self-end; - } - &:checked ~ .drawer-side > .drawer-overlay + * { - @apply translate-x-0; - } - } -} -:where(.drawer-toggle ~ .drawer-content) { - height: inherit; -} -.drawer-toggle { - @apply absolute h-0 w-0 appearance-none opacity-0; - & ~ .drawer-content { - @apply z-0 col-start-1 row-start-1 overflow-y-auto; - } - & ~ .drawer-side { - @apply col-start-1 row-start-1 grid max-h-screen overflow-x-hidden; - & > .drawer-overlay { - @apply invisible col-start-1 row-start-1 opacity-0; - } - & > .drawer-overlay + * { - @apply z-10 col-start-1 row-start-1 -translate-x-full transform; - } - } - &:checked { - & ~ .drawer-side { - @apply overflow-y-auto overflow-x-hidden isolate; - & > .drawer-overlay { - @apply visible; - } - & > .drawer-overlay + * { - @apply translate-x-0; - } - } - } -} - -[dir='rtl'] .drawer-toggle ~ .drawer-side > .drawer-overlay + * { - @apply translate-x-full; -} -[dir='rtl'] .drawer-toggle:checked ~ .drawer-side > .drawer-overlay + * { - @apply translate-x-0; -} -[dir='rtl'] - .drawer.drawer-end - > .drawer-toggle - ~ .drawer-side - > .drawer-overlay - + * { - --tw-translate-x: -100%; -} -[dir='rtl'] - .drawer.drawer-end - > .drawer-toggle:checked - ~ .drawer-side - > .drawer-overlay - + * { - --tw-translate-x: 0px; -} -[dir='rtl'] .drawer.drawer-end > .drawer-toggle:checked ~ .drawer-content { - --tw-translate-x: 0.5rem; -} - -@media (min-width: 1024px) { - .drawer-mobile { - grid-auto-columns: max-content auto; - & > .drawer-toggle { - & ~ .drawer-content { - @apply h-auto lg:col-start-2; - } - & ~ .drawer-side { - @apply overflow-y-auto; - & > .drawer-overlay { - @apply lg:visible; - } - & > .drawer-overlay + * { - @apply lg:translate-x-0; - } - } - } - } - .drawer-mobile.drawer-end { - grid-auto-columns: auto max-content; - direction: ltr; - & > .drawer-toggle { - & ~ .drawer-content { - @apply h-auto lg:col-start-1; - } - & ~ .drawer-side { - @apply overflow-y-auto lg:col-start-2; - & > .drawer-overlay { - @apply lg:visible; - } - & > .drawer-overlay + * { - @apply lg:translate-x-0; - } - } - } - } -} - -.drawer.drawer-end > .drawer-toggle:checked ~ .drawer-content { - @apply -translate-x-2; -} -.drawer-toggle { - & ~ .drawer-content { - @apply transition-all duration-300 ease-in-out; - } - & ~ .drawer-side { - & > .drawer-overlay { - @apply cursor-pointer bg-dim transition-all duration-300 ease-in-out; - } - & > .drawer-overlay + * { - @apply transition-all duration-300 ease-in-out; - } - } - &:checked { - & ~ .drawer-content { - @apply translate-x-2; - } - & ~ .drawer-side { - & > .drawer-overlay { - opacity: 0.999999; /* 1 causes a bug on chrome 🤷‍♂️ */ - @apply bg-opacity-40; - } - } - } - &:focus-visible { - & ~ .drawer-content .drawer-button { - outline: 2px solid hsl(var(--nf)); - outline-offset: 2px; - &.btn-primary { - outline: 2px solid hsl(var(--p)); - } - &.btn-secondary { - outline: 2px solid hsl(var(--s)); - } - &.btn-accent { - outline: 2px solid hsl(var(--a)); - } - &.btn-info { - outline: 2px solid hsl(var(--in)); - } - &.btn-success { - outline: 2px solid hsl(var(--su)); - } - &.btn-warning { - outline: 2px solid hsl(var(--wa)); - } - &.btn-error { - outline: 2px solid hsl(var(--er)); - } - &.glass { - outline: 2px solid currentColor; - } - &.btn-ghost { - outline: 2px solid currentColor; - } - &.btn-link { - outline: 2px solid currentColor; - } - } - } -} -@media (min-width: 1024px) { - .drawer-mobile { - & > .drawer-toggle { - &:checked { - & ~ .drawer-content { - @apply translate-x-0; - } - } - } - } -} diff --git a/packages/ufb-tailwind/src/components/dropdown.css b/packages/ufb-tailwind/src/components/dropdown.css deleted file mode 100644 index 4aaa8cd01..000000000 --- a/packages/ufb-tailwind/src/components/dropdown.css +++ /dev/null @@ -1,57 +0,0 @@ -.dropdown .dropdown-content { - @apply origin-top scale-95 transform transition duration-200 ease-in-out; -} -.dropdown-bottom .dropdown-content { - @apply origin-top; -} -.dropdown-top .dropdown-content { - @apply origin-bottom; -} -.dropdown-left .dropdown-content { - @apply origin-right; -} -.dropdown-right .dropdown-content { - @apply origin-left; -} -.dropdown.dropdown-open .dropdown-content, -.dropdown.dropdown-hover:hover .dropdown-content, -.dropdown:focus .dropdown-content, -.dropdown:focus-within .dropdown-content { - @apply scale-100; -} -.dropdown { - @apply relative inline-block; -} -.dropdown > *:focus { - @apply outline-none; -} -.dropdown .dropdown-content { - @apply invisible absolute z-50 opacity-0; -} -.dropdown-end .dropdown-content { - @apply right-0; -} -.dropdown-left .dropdown-content { - @apply top-0 right-full bottom-auto; -} -.dropdown-right .dropdown-content { - @apply left-full top-0 bottom-auto; -} -.dropdown-bottom .dropdown-content { - @apply bottom-auto top-full; -} -.dropdown-top .dropdown-content { - @apply bottom-full top-auto; -} -.dropdown-end.dropdown-right .dropdown-content { - @apply bottom-0 top-auto; -} -.dropdown-end.dropdown-left .dropdown-content { - @apply bottom-0 top-auto; -} -.dropdown.dropdown-open .dropdown-content, -.dropdown.dropdown-hover:hover .dropdown-content, -.dropdown:not(.dropdown-hover):focus .dropdown-content, -.dropdown:not(.dropdown-hover):focus-within .dropdown-content { - @apply visible opacity-100; -} diff --git a/packages/ufb-tailwind/src/components/header.css b/packages/ufb-tailwind/src/components/header.css deleted file mode 100644 index c993a45ea..000000000 --- a/packages/ufb-tailwind/src/components/header.css +++ /dev/null @@ -1,3 +0,0 @@ -.header { - --header-height: 48px; -} From 1532277fcae4b5aeb2d61f033dc5625207f86827 Mon Sep 17 00:00:00 2001 From: Chiyoung Jeong Date: Mon, 25 Sep 2023 10:21:03 +0900 Subject: [PATCH 02/13] fix: openapi-type (#52) --- apps/web/src/types/openapi.type.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/web/src/types/openapi.type.ts b/apps/web/src/types/openapi.type.ts index b6eccc1df..cc8a0f6f1 100644 --- a/apps/web/src/types/openapi.type.ts +++ b/apps/web/src/types/openapi.type.ts @@ -28,7 +28,12 @@ export type OAIMethodPathKeys = O.SelectKeys< export type OAIPathParameters< TPath extends OAIPathKeys, TMethod extends OAIMethods, -> = O.Path; +> = O.Path extends Record< + string, + unknown +> + ? O.Path + : undefined; export type OAIQueryParameters< TPath extends OAIPathKeys, From bb99846af413df8e7938a72fad28d3cd613b02ed Mon Sep 17 00:00:00 2001 From: Carson Date: Tue, 26 Sep 2023 18:18:08 +0900 Subject: [PATCH 03/13] chore: no log on 401 error (#53) --- apps/api/src/app.module.ts | 11 +++++++++++ apps/api/src/common/filters/http-exception.filter.ts | 7 ------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 6e3823e9b..a3967bc0f 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -92,6 +92,17 @@ const domainModules = [ autoLogging: { ignore: (req: any) => req.originalUrl === '/api/health', }, + customLogLevel: (req, res, err) => { + if (res.statusCode === 401) { + return 'silent'; + } + if (res.statusCode >= 400 && res.statusCode < 500) { + return 'warn'; + } else if (res.statusCode >= 500 || err) { + return 'error'; + } + return 'info'; + }, }, }), ClsModule.forRoot({ diff --git a/apps/api/src/common/filters/http-exception.filter.ts b/apps/api/src/common/filters/http-exception.filter.ts index 2ba06ed18..78e650ce0 100644 --- a/apps/api/src/common/filters/http-exception.filter.ts +++ b/apps/api/src/common/filters/http-exception.filter.ts @@ -45,12 +45,5 @@ export class HttpExceptionFilter implements ExceptionFilter { path: request.url, }); } - - this.logger.error( - JSON.stringify({ - request: { method: request.method, url: request.url }, - exception, - }), - ); } } From 2305fca78eec3fad07b598cfa0bbc1fd4ef07f61 Mon Sep 17 00:00:00 2001 From: Carson Date: Fri, 6 Oct 2023 14:36:07 +0900 Subject: [PATCH 04/13] fix: update feedback updatedAt on issue modification (#56) --- .../feedback/feedback.mysql.service.ts | 10 +++++++-- .../src/domains/feedback/feedback.service.ts | 21 +++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/apps/api/src/domains/feedback/feedback.mysql.service.ts b/apps/api/src/domains/feedback/feedback.mysql.service.ts index 8d6688653..2b02902f8 100644 --- a/apps/api/src/domains/feedback/feedback.mysql.service.ts +++ b/apps/api/src/domains/feedback/feedback.mysql.service.ts @@ -311,7 +311,10 @@ export class FeedbackMySQLService { this.cls.set('addIssueInFeedback', { feedbackId, issueId }); - await this.feedbackRepository.save(feedback); + await this.feedbackRepository.save({ + ...feedback, + updatedAt: dayjs().format('YYYY-MM-DD HH:mm:ss'), + }); await this.issueRepository.update(dto.issueId, { feedbackCount: () => 'feedback_count + 1', @@ -345,7 +348,10 @@ export class FeedbackMySQLService { feedback.issues = feedback.issues.filter((issue) => issue.id !== issueId); this.cls.set('removeIssueInFeedback', { feedbackId, issueId }); - await this.feedbackRepository.save(feedback); + await this.feedbackRepository.save({ + ...feedback, + updatedAt: dayjs().format('YYYY-MM-DD HH:mm:ss'), + }); await this.issueRepository.update(dto.issueId, { feedbackCount: () => 'feedback_count - 1', diff --git a/apps/api/src/domains/feedback/feedback.service.ts b/apps/api/src/domains/feedback/feedback.service.ts index 256e6f0c9..3a0593144 100644 --- a/apps/api/src/domains/feedback/feedback.service.ts +++ b/apps/api/src/domains/feedback/feedback.service.ts @@ -18,6 +18,7 @@ import { Injectable, StreamableFile, } from '@nestjs/common'; +import dayjs from 'dayjs'; import * as ExcelJS from 'exceljs'; import * as fastcsv from 'fast-csv'; import { createReadStream, existsSync } from 'fs'; @@ -475,12 +476,28 @@ export class FeedbackService { @Transactional() async addIssue(dto: AddIssueDto) { - return this.feedbackMySQLService.addIssue(dto); + await this.feedbackMySQLService.addIssue(dto); + + if (OS_USE) { + await this.feedbackOSService.upsertFeedbackItem({ + channelId: dto.channelId, + feedbackId: dto.feedbackId, + data: { updatedAt: dayjs().toISOString() }, + }); + } } @Transactional() async removeIssue(dto: RemoveIssueDto) { - return this.feedbackMySQLService.removeIssue(dto); + await this.feedbackMySQLService.removeIssue(dto); + + if (OS_USE) { + await this.feedbackOSService.upsertFeedbackItem({ + channelId: dto.channelId, + feedbackId: dto.feedbackId, + data: { updatedAt: dayjs().toISOString() }, + }); + } } async countByProjectId(dto: CountByProjectIdDto) { From 4ea141197777d537b61862657712ef6c3c8b19ad Mon Sep 17 00:00:00 2001 From: Chiyoung Jeong Date: Tue, 10 Oct 2023 10:11:38 +0900 Subject: [PATCH 05/13] feat: turborepo pipeline (#55) * feat: turberepo pipeline * feat: update Dockerfile for torborepo * chore: update README.md * fix: update README.md and Dockerfile * feat: add dev:web and dev:api in package.json --- .dockerignore | 1 - README.md | 12 +++++++++++- apps/api/Dockerfile | 13 +++++++------ apps/web/Dockerfile | 28 +++++++++++++++++----------- apps/web/README.md | 4 ++++ docker-compose.yml | 6 ++++++ package.json | 3 +++ packages/ufb-tailwind/package.json | 3 +-- packages/ufb-ui/package.json | 1 - turbo.json | 25 ++++++++++++++----------- 10 files changed, 63 insertions(+), 33 deletions(-) diff --git a/.dockerignore b/.dockerignore index 34a4261c0..6db31129e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,5 @@ **/node_modules **/.next -**/.turbo **/dist **/.env* !apps/web/.env.build \ No newline at end of file diff --git a/README.md b/README.md index f9a729db3..43b2a9fbc 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,16 @@ npm run migration:run yarn dev ``` +6. Also, you can run the `dev` target of one of apps in root directory: + +```bash +# web +yarn turbo run dev --filter=web + +# api +yarn turbo run dev --filter=api +``` + You can always find more information in each app/library's respective README.md file. ### Setting Up ABC User Feedback Manually @@ -110,7 +120,7 @@ The client is based on React, React Hook Form, React Query, Tailwind css, MUI, a ### Build Docker Image -For your code build, you can buile docker image using docker-compose +For your code build, you can buile docker image using docker-compose. Please refer to [remote caching](https://turbo.build/repo/docs/core-concepts/remote-caching) and [deploying with docker](https://turbo.build/repo/docs/handbook/deploying-with-docker) using turborepo ``` docker-compose build diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index a0d1ecad3..973ceef02 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -25,14 +25,15 @@ RUN yarn install # Build the project and its dependencies COPY --from=builder /app/out/full/ . -COPY turbo.json turbo.json +COPY turbo.json ./ +COPY .turbo/ ./.turbo/ +COPY .git/ ./.git/ -# Uncomment and use build args to enable remote caching -# ARG TURBO_TEAM -# ENV TURBO_TEAM=$TURBO_TEAM +ARG TURBO_TOKEN +ENV TURBO_TOKEN=${TURBO_TOKEN} -# ARG TURBO_TOKEN -# ENV TURBO_TOKEN=$TURBO_TOKEN +ARG TURBO_TEAM +ENV TURBO_TEAM=${TURBO_TEAM} RUN yarn turbo run build --filter=api... diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index ca14b2a39..2efa532bc 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -1,10 +1,12 @@ # This Dockerfile is copy-pasted into our main docs at /docs/handbook/deploying-with-docker. # Make sure you update both files! +FROM node:18-alpine AS base -FROM node:18-alpine AS builder +FROM base AS builder # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat RUN apk update + # Set working directory WORKDIR /app RUN yarn global add turbo @@ -12,8 +14,11 @@ COPY . . RUN turbo prune --scope=web --docker # Add lockfile and package.json's of isolated subworkspace -FROM node:18-alpine AS installer +FROM base AS installer + RUN apk add --no-cache libc6-compat +RUN apk --no-cache add --virtual .builds-deps build-base python3 + RUN apk update WORKDIR /app @@ -21,24 +26,25 @@ WORKDIR /app COPY .gitignore .gitignore COPY --from=builder /app/out/json/ . COPY --from=builder /app/out/yarn.lock ./yarn.lock +RUN yarn global add node-gyp RUN yarn install # Build the project COPY --from=builder /app/out/full/ . -COPY turbo.json turbo.json +COPY turbo.json ./ +COPY .turbo/ ./.turbo/ +COPY .git/ ./.git/ -COPY --from=builder /app/apps/web/.env.build /app/apps/web/.env.production - -# Uncomment and use build args to enable remote caching -# ARG TURBO_TEAM -# ENV TURBO_TEAM=$TURBO_TEAM +ARG TURBO_TOKEN +ENV TURBO_TOKEN=${TURBO_TOKEN} -# ARG TURBO_TOKEN -# ENV TURBO_TOKEN=$TURBO_TOKEN +ARG TURBO_TEAM +ENV TURBO_TEAM=${TURBO_TEAM} +COPY --from=builder /app/apps/web/.env.build /app/apps/web/.env.production RUN yarn turbo run build --filter=web... -FROM node:18-alpine AS runner +FROM base AS runner WORKDIR /app # install usermod and change node user to 1001 diff --git a/apps/web/README.md b/apps/web/README.md index c435881e5..16c73cbb6 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -24,6 +24,10 @@ You will also see any lint errors in the console. yarn dev ``` +> **Note** +> In order to run web properly, ui packages need to be built by the +> `yarn build:ui` command in root directory or `yarn turbo run @ufb/ui#build` command in any directory. + ### `generate-api-type` Generate api type using open api specification. This command can run after running on server. The type file is generated in `src/types/api.type.ts` diff --git a/docker-compose.yml b/docker-compose.yml index 9a4bfebfb..c5bd8265d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,9 @@ services: build: context: . dockerfile: ./apps/web/Dockerfile + args: + - TURBO_TOKEN=TURBO_TOKEN + - TURBO_TEAM=TURBO_TEAM restart: always ports: - 3000:3000 @@ -24,6 +27,9 @@ services: build: context: . dockerfile: ./apps/api/Dockerfile + args: + - TURBO_TOKEN=TURBO_TOKEN + - TURBO_TEAM=TURBO_TEAM restart: always ports: - 4000:4000 diff --git a/package.json b/package.json index d302ec020..0afe1eb7b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,10 @@ "scripts": { "postinstall": "husky install", "build": "turbo run build", + "build:ui": "turbo run @ufb/ui#build", "dev": "turbo run dev --parallel", + "dev:web": "turbo run dev --filter=web", + "dev:api": "turbo run dev --filter=api", "lint": "turbo run lint", "format": "prettier --write \"**/*.{ts,tsx}\"", "test": "turbo run test" diff --git a/packages/ufb-tailwind/package.json b/packages/ufb-tailwind/package.json index 3368009ab..fbe5eaba1 100644 --- a/packages/ufb-tailwind/package.json +++ b/packages/ufb-tailwind/package.json @@ -12,8 +12,7 @@ "utilities": "tailwindcss --config src/utilities/tailwind.config.js -i src/utilities/utilities.css -o dist/layer/utilities.css --postcss", "postutilities": "prejss-cli dist/layer/utilities.css --format commonjs", "merge": "cat dist/layer/*.css > dist/tailwind.css", - "build": "yarn base && yarn utilities && yarn components && yarn merge", - "dev": "yarn npm-watch" + "build": "yarn base && yarn utilities && yarn components && yarn merge" }, "devDependencies": { "autoprefixer": "^10.4.14", diff --git a/packages/ufb-ui/package.json b/packages/ufb-ui/package.json index 93d59ae59..e13b6f1dd 100644 --- a/packages/ufb-ui/package.json +++ b/packages/ufb-ui/package.json @@ -26,7 +26,6 @@ }, "peerDependencies": {}, "scripts": { - "dev": "rollup --watch --config --bundleConfigAsCjs", "build": "rollup --config --bundleConfigAsCjs", "lint": "eslint \"src/**/*.{ts,tsx}\"" }, diff --git a/turbo.json b/turbo.json index 7a528f4dc..510d9c41d 100644 --- a/turbo.json +++ b/turbo.json @@ -2,14 +2,8 @@ "$schema": "https://turbo.build/schema.json", "pipeline": { "build": { - "outputs": [ - "dist/**", - ".next/**", - "public/dist/**" - ], - "dependsOn": [ - "^build" - ], + "outputs": ["dist/**", ".next/**", "!.next/cache/**"], + "dependsOn": ["^build"], "env": [ "NODE_ENV", "SESSION_PASSWORD", @@ -41,8 +35,17 @@ "outputs": [] }, "dev": { - "cache": false + "dependsOn": ["@ufb/ui#build"], + "cache": false, + "persistent": true }, - "test": {} + "test": {}, + "@ufb/tailwind#build": { + "outputs": ["dist/**"] + }, + "@ufb/ui#build": { + "outputs": ["dist/**"], + "dependsOn": ["@ufb/tailwind#build"] + } } -} \ No newline at end of file +} From fc7e211dfd375e35d4f4d9f43ae03d0f214b50a4 Mon Sep 17 00:00:00 2001 From: Chiyoung Jeong Date: Tue, 10 Oct 2023 10:12:15 +0900 Subject: [PATCH 06/13] fix: web issues (#57) * feat: update * feat: feedback and issue search query url * feat: remove console.log * feat: remove comments * feat: remove comments --- apps/web/next.config.js | 2 +- apps/web/public/locales/en/common.json | 9 +- apps/web/public/locales/ja/common.json | 7 +- apps/web/public/locales/ko/common.json | 7 +- .../etc/CheckedTableHead/CheckedTableHead.tsx | 20 +-- .../etc/DateRangePicker/DateRangePicker.tsx | 42 ++++--- .../etc/ShareButton/ShareButton.tsx | 5 +- .../etc/TableResizer/TableResizer.tsx | 50 ++++++++ .../src/components/etc/TableResizer/index.ts | 16 +++ .../etc/TableSearchInput/TableSearchInput.tsx | 21 ++-- .../table-search-input.service.ts | 18 ++- apps/web/src/components/etc/index.ts | 1 + .../components/layouts/Header/HeaderName.tsx | 21 ++-- .../components/layouts/SideNav/SideNav.tsx | 9 +- .../templates/MainTemplate/MainTemplate.tsx | 6 +- .../ColumnSettingPopover.tsx | 66 +++++----- .../tables/FeedbackTable/FeedbackTable.tsx | 87 ++++++------- .../FeedbackTableBar/FeedbackTableBar.tsx | 2 +- .../FeedbackTableRow/FeedbackTableRow.tsx | 11 +- .../FeedbackTable/feedback-table.context.tsx | 11 +- .../tables/IssueTable/IssueTable.tsx | 65 ++++++---- apps/web/src/hooks/useQueryParamsState.ts | 114 ++++++++++++++++++ packages/ufb-ui/src/Badge/Badge.tsx | 2 +- 23 files changed, 412 insertions(+), 180 deletions(-) create mode 100644 apps/web/src/components/etc/TableResizer/TableResizer.tsx create mode 100644 apps/web/src/components/etc/TableResizer/index.ts create mode 100644 apps/web/src/hooks/useQueryParamsState.ts diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 1717ac9be..495214e58 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -29,7 +29,7 @@ const nextConfig = { ignoreDuringBuilds: true, }, transpilePackages: ['@ufb/ui'], - compiler: { removeConsole: true }, + compiler: { removeConsole: process.env.NODE_ENV === 'production' }, }; module.exports = nextConfig; diff --git a/apps/web/public/locales/en/common.json b/apps/web/public/locales/en/common.json index 708178b97..a687580cf 100644 --- a/apps/web/public/locales/en/common.json +++ b/apps/web/public/locales/en/common.json @@ -70,7 +70,7 @@ } }, "feedback": { - "title": "Feedback Management", + "title": "Feedback", "column-setting": "Column Setting", "issue-cell": { "issue-list": "Issue list", @@ -101,7 +101,7 @@ } }, "issue": { - "title": "Issue Management", + "title": "Issue", "setting": "Issue Setting", "dialog": { "delete-issue": { @@ -263,7 +263,8 @@ "date": { "today": "Today", "yesterday": "Yesterday", - "before-days": "Before {{day, number}} days" + "before-days": "Before {{day, number}} days", + "date-range-over-max-days": "The inquiry period can only be entered up to {{maxDays}} days" }, "equal-search": "Equal", "like-search": "Like" @@ -279,4 +280,4 @@ "add": "Addition Complete", "copy": "Copy Complete" } -} \ No newline at end of file +} diff --git a/apps/web/public/locales/ja/common.json b/apps/web/public/locales/ja/common.json index 1e1976a2c..4ebe47eae 100644 --- a/apps/web/public/locales/ja/common.json +++ b/apps/web/public/locales/ja/common.json @@ -68,7 +68,7 @@ } }, "feedback": { - "title": "フィードバック管理", + "title": "フィードバック", "column-setting": "カラムの設定", "issue-cell": { "issue-list": "イシューリスト", @@ -99,7 +99,7 @@ } }, "issue": { - "title": "イシュー管理", + "title": "イシュー", "setting": "イシュー設定", "dialog": { "delete-issue": { @@ -253,7 +253,8 @@ "date": { "today": "今日", "yesterday": "昨日", - "before-days": "{{day, number}}日前" + "before-days": "{{day, number}}日前", + "date-range-over-max-days": "照会期間は最大{{maxDays}}日まで入力可能です。" }, "equal-search": "完全一致", "like-search": "部分一致" diff --git a/apps/web/public/locales/ko/common.json b/apps/web/public/locales/ko/common.json index b94115546..9ebc3673a 100644 --- a/apps/web/public/locales/ko/common.json +++ b/apps/web/public/locales/ko/common.json @@ -68,7 +68,7 @@ } }, "feedback": { - "title": "피드백 관리", + "title": "피드백", "column-setting": "컬럼설정", "issue-cell": { "issue-list": "이슈 목록", @@ -99,7 +99,7 @@ } }, "issue": { - "title": "이슈 관리", + "title": "이슈", "setting": "이슈 설정", "dialog": { "delete-issue": { @@ -253,7 +253,8 @@ "date": { "today": "오늘", "yesterday": "어제", - "before-days": "{{day, number}}일전" + "before-days": "{{day, number}}일전", + "date-range-over-max-days": "조회 기간은 최대 {{maxDays}}일까지만 입력 가능합니다." }, "equal-search": "완전 일치", "like-search": "부분 일치" diff --git a/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx b/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx index 19fc13417..658b8e4b4 100644 --- a/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx +++ b/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx @@ -53,13 +53,9 @@ const CheckedTableHead: React.FC = (props) => {
- + + {t('text.select-count', { count })} +
diff --git a/apps/web/src/components/etc/DateRangePicker/DateRangePicker.tsx b/apps/web/src/components/etc/DateRangePicker/DateRangePicker.tsx index 341b105d2..b292ee0c7 100644 --- a/apps/web/src/components/etc/DateRangePicker/DateRangePicker.tsx +++ b/apps/web/src/components/etc/DateRangePicker/DateRangePicker.tsx @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon, Popover, PopoverContent, PopoverTrigger } from '@ufb/ui'; +import { Icon, Popover, PopoverContent, PopoverTrigger, toast } from '@ufb/ui'; import { enUS, ja, ko } from 'date-fns/locale'; import dayjs from 'dayjs'; import weekday from 'dayjs/plugin/weekday'; @@ -92,6 +92,15 @@ const DateRangePicker: React.FC = (props) => { }; const handleApply = () => { if (!currentValue?.startDate || !currentValue?.endDate) return; + if ( + maxDays && + isOverMaxDays(currentValue.startDate, currentValue.endDate, maxDays) + ) { + toast.negative({ + title: t('text.date.date-range-over-max-days', { maxDays }), + }); + return; + } onChange(currentValue); setIsOpen(false); }; @@ -102,16 +111,22 @@ const DateRangePicker: React.FC = (props) => {
setIsOpen(true)} >

- {value - ? `${dayjs(value?.startDate).format(DATE_FORMAT)} ~ ${dayjs( - value?.endDate, - ).format(DATE_FORMAT)}` + {currentValue + ? `${ + currentValue?.startDate + ? dayjs(currentValue?.startDate).format(DATE_FORMAT) + : '' + } ~ ${ + currentValue?.endDate + ? dayjs(currentValue.endDate).format(DATE_FORMAT) + : '' + }` : 'YYYY-MM-DD ~ YYYY-MM-DD'}

@@ -158,14 +173,7 @@ const DateRangePicker: React.FC = (props) => { endDate={currentValue?.endDate} monthsShown={2} minDate={minDate} - maxDate={ - maxDays && currentValue?.startDate - ? getMinDate( - dayjs(currentValue.startDate).add(maxDays, 'days').toDate(), - maxDate, - ) - : maxDate - } + maxDate={currentValue?.startDate ? maxDate : undefined} disabledKeyboardNavigation selectsRange inline @@ -188,10 +196,8 @@ const DateRangePicker: React.FC = (props) => { ); }; -const getMinDate = (a?: Date, b?: Date) => { - if (!a) return b; - if (!b) return a; - return a < b ? a : b; +const isOverMaxDays = (startDate: Date, endDate: Date, maxDays: number) => { + return dayjs(startDate).add(maxDays, 'days').toDate() < endDate; }; export default DateRangePicker; diff --git a/apps/web/src/components/etc/ShareButton/ShareButton.tsx b/apps/web/src/components/etc/ShareButton/ShareButton.tsx index 2ed600567..a530c66b9 100644 --- a/apps/web/src/components/etc/ShareButton/ShareButton.tsx +++ b/apps/web/src/components/etc/ShareButton/ShareButton.tsx @@ -18,18 +18,17 @@ import { MouseEventHandler } from 'react'; import { useTranslation } from 'react-i18next'; interface IProps { - id: number; pathname: string; } -const ShareButton: React.FC = ({ id, pathname }) => { +const ShareButton: React.FC = ({ pathname }) => { const { t } = useTranslation(); const onClickLinkCopy: MouseEventHandler = (e) => { e.stopPropagation(); try { const { origin } = window.location; - navigator.clipboard.writeText(`${origin}${pathname}?id=${id}`); + navigator.clipboard.writeText(`${origin}${pathname}`); toast.positive({ title: t('toast.copy'), iconName: 'CopyFill' }); } catch (error) { toast.negative({ title: 'fail' }); diff --git a/apps/web/src/components/etc/TableResizer/TableResizer.tsx b/apps/web/src/components/etc/TableResizer/TableResizer.tsx new file mode 100644 index 000000000..01c028489 --- /dev/null +++ b/apps/web/src/components/etc/TableResizer/TableResizer.tsx @@ -0,0 +1,50 @@ +/** + * Copyright 2023 LINE Corporation + * + * LINE Corporation licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import { Header, Table } from '@tanstack/react-table'; +import { Icon } from '@ufb/ui'; + +interface IProps { + table: Table; + header: Header; +} + +const TableResizer: React.FC = ({ table, header }) => { + return ( +
+ +
+ ); +}; + +export default TableResizer; diff --git a/apps/web/src/components/etc/TableResizer/index.ts b/apps/web/src/components/etc/TableResizer/index.ts new file mode 100644 index 000000000..1a75c64e1 --- /dev/null +++ b/apps/web/src/components/etc/TableResizer/index.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2023 LINE Corporation + * + * LINE Corporation licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +export { default } from './TableResizer'; diff --git a/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx b/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx index 27e875b92..a15d827e8 100644 --- a/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx +++ b/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx @@ -45,14 +45,14 @@ export type SearchItemType = { interface IProps { onChangeQuery: (query: Record) => void; searchItems: SearchItemType[]; - initialQuery?: Record; + query?: Record; defaultQuery?: Record; } const TableSearchInput: React.FC = ({ onChangeQuery, searchItems, - initialQuery, + query, }) => { const inputRef = useRef(null); const popoverRef = useRef(null); @@ -98,9 +98,10 @@ const TableSearchInput: React.FC = ({ ); useEffect(() => { - if (!initialQuery) return; - setInputValue(objToStr(initialQuery, searchItems)); - }, [searchItems]); + if (!query) return; + const inputValue = objToStr(query, searchItems); + setInputValue(inputValue); + }, [searchItems, query]); const filterIconCN = useMemo( () => (isOpenPopover ? 'text-primary' : 'text-tertiary'), @@ -115,10 +116,14 @@ const TableSearchInput: React.FC = ({ ? removeEmptyValueInObject({ ...currentObj, ...inputObject }) : {}; - setInputValue(objToStr(currentQuery, searchItems)); - onChangeQuery( - removeEmptyValueInObject(objToQuery(currentQuery, searchItems)), + const inputText = objToStr(currentQuery, searchItems); + setInputValue(inputText); + + const newQUery = removeEmptyValueInObject( + objToQuery(currentQuery, searchItems), ); + + onChangeQuery(newQUery); }; const reset = () => { diff --git a/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts b/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts index 9033a63ec..006119e2a 100644 --- a/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts +++ b/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts @@ -87,10 +87,20 @@ export const objToStr = ( return ''; } case 'issue': - const issueName = Array.isArray(value) - ? column.options?.find((v) => v.id === value[0])?.name - : value?.name ?? value; - return `${name}:${issueName}`; + if (Array.isArray(value)) { + const issueName = column.options?.find( + (v) => v.id === value[0], + )?.name; + return `${name}:${issueName}`; + } else if (value?.name) { + const issueName = value?.name; + return `${name}:${issueName}`; + } else { + const issueName = + column.options?.find((v) => v.id === parseInt(value))?.name ?? + value; + return `${name}:${issueName}`; + } case 'issue_status': case 'select': case 'multiSelect': diff --git a/apps/web/src/components/etc/index.ts b/apps/web/src/components/etc/index.ts index deb236e49..22d9e0c46 100644 --- a/apps/web/src/components/etc/index.ts +++ b/apps/web/src/components/etc/index.ts @@ -29,3 +29,4 @@ export { default as TableLoadingRow } from './TableLoadingRow'; export { default as IssueCircle } from './IssueCircle'; export { default as Dialog } from './Dialog'; export { default as PopoverModalContent } from './PopoverModalContent'; +export { default as TableResizer } from './TableResizer'; diff --git a/apps/web/src/components/layouts/Header/HeaderName.tsx b/apps/web/src/components/layouts/Header/HeaderName.tsx index 914ffc9b5..ab6752805 100644 --- a/apps/web/src/components/layouts/Header/HeaderName.tsx +++ b/apps/web/src/components/layouts/Header/HeaderName.tsx @@ -39,7 +39,7 @@ const HeaderName: React.FC = () => { }); return ( - <> +
@@ -47,14 +47,21 @@ const HeaderName: React.FC = () => { {tenant?.siteName}
{data && ( -
-
- + <> + +
+
+ +
+ {data?.name}
- {data?.name} -
+ )} - +
); }; diff --git a/apps/web/src/components/layouts/SideNav/SideNav.tsx b/apps/web/src/components/layouts/SideNav/SideNav.tsx index b9681e7d7..e5bf0b929 100644 --- a/apps/web/src/components/layouts/SideNav/SideNav.tsx +++ b/apps/web/src/components/layouts/SideNav/SideNav.tsx @@ -27,7 +27,6 @@ interface IProps extends React.PropsWithChildren {} const SideNav: React.FC = () => { const { t } = useTranslation(); - const router = useRouter(); const { projectId } = useCurrentProjectId(); const perms = usePermissions(projectId); @@ -43,14 +42,14 @@ const SideNav: React.FC = () => { onMouseOver={() => setIsHover(true)} onMouseOut={() => setIsHover(false)} style={{ - width: 'max-content', + width: isHover ? 200 : 'max-content', boxShadow: isHover ? '4px 4px 8px 0px #0000000F' : '', }} > = () => { = () => { = ({ children }) => { const router = useRouter(); return ( - <> +
{Path.hasSideNav(router.pathname) && }
= ({ children }) => { {children}
- +
); }; diff --git a/apps/web/src/containers/tables/FeedbackTable/ColumnSettingPopover/ColumnSettingPopover.tsx b/apps/web/src/containers/tables/FeedbackTable/ColumnSettingPopover/ColumnSettingPopover.tsx index c23204315..f47480c2c 100644 --- a/apps/web/src/containers/tables/FeedbackTable/ColumnSettingPopover/ColumnSettingPopover.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/ColumnSettingPopover/ColumnSettingPopover.tsx @@ -57,10 +57,26 @@ const ColumnSettingPopover: React.FC = ({ const { t } = useTranslation(); const columnKeys = useMemo( - () => columns.map((v) => v.id) as string[], - [columns], + () => + columnOrder.length === 0 + ? (columns.map((v) => v.id) as string[]) + : columnOrder, + [columns, columnOrder], ); + const checkedNum = useMemo(() => { + return columnKeys.reduce((acc, key) => { + return ( + acc + + (typeof columnVisibility[key] === 'undefined' + ? 1 + : columnVisibility[key] + ? 1 + : 0) + ); + }, 0); + }, [columnKeys, columnVisibility]); + const onDragEnd: OnDragEndResponder = (result) => { const { destination, source } = result; @@ -69,7 +85,7 @@ const ColumnSettingPopover: React.FC = ({ if (destination.index < 2) destination.index = 2; const newFields: string[] = reorder( - columnOrder.length === 0 ? columnKeys : columnOrder, + columnKeys, source.index, destination.index, ); @@ -81,7 +97,7 @@ const ColumnSettingPopover: React.FC = ({ - {t('main.feedback.column-setting')} + {t('main.feedback.column-setting')} ({checkedNum}/{columnKeys.length}) {t('main.feedback.column-setting')} @@ -94,29 +110,25 @@ const ColumnSettingPopover: React.FC = ({ {...provided.droppableProps} className="space-y-1 min-w-[200px]" > - {(columnOrder.length === 0 ? columnKeys : columnOrder)?.map( - (key, index) => ( - v.key === key)?.name ?? '' - } - index={index} - key={key} - isChecked={ - typeof columnVisibility[key] === 'undefined' - ? true - : columnVisibility[key] - } - onChange={(isChecked) => - onChangeColumnVisibility((prev) => ({ - ...prev, - [key]: isChecked, - })) - } - isDisabled={key === 'id' || key === 'issues'} - /> - ), - )} + {columnKeys?.map((key, index) => ( + v.key === key)?.name ?? ''} + index={index} + key={key} + isChecked={ + typeof columnVisibility[key] === 'undefined' + ? true + : columnVisibility[key] + } + onChange={(isChecked) => + onChangeColumnVisibility((prev) => ({ + ...prev, + [key]: isChecked, + })) + } + isDisabled={key === 'id' || key === 'issues'} + /> + ))} {provided.placeholder}
)} diff --git a/apps/web/src/containers/tables/FeedbackTable/FeedbackTable.tsx b/apps/web/src/containers/tables/FeedbackTable/FeedbackTable.tsx index 69007a241..f056ccdf8 100644 --- a/apps/web/src/containers/tables/FeedbackTable/FeedbackTable.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/FeedbackTable.tsx @@ -23,10 +23,14 @@ import { Icon, toast } from '@ufb/ui'; import dayjs from 'dayjs'; import produce from 'immer'; import { useTranslation } from 'next-i18next'; -import { useRouter } from 'next/router'; import { useEffect, useMemo, useState } from 'react'; -import { CheckedTableHead, TableLoadingRow, TableSortIcon } from '@/components'; +import { + CheckedTableHead, + TableLoadingRow, + TableResizer, + TableSortIcon, +} from '@/components'; import { useOAIQuery, usePermissions } from '@/hooks'; import { useFeedbackSearch, useSort } from '@/hooks'; @@ -57,13 +61,11 @@ const FeedbackTable: React.FC = (props) => { page, setPage, query, - setQuery, createdAtRange, } = useFeedbackTable(); const { t } = useTranslation(); const perms = usePermissions(); - const router = useRouter(); const [rows, setRows] = useState[]>([]); const [rowSelection, setRowSelection] = useState({}); @@ -71,36 +73,41 @@ const FeedbackTable: React.FC = (props) => { const [openDeleteDialog, setOpenDeleteDialog] = useState(false); - useEffect(() => { - setPage(1); - setQuery({}); - setRowSelection({}); - }, [channelId]); - useEffect(() => { setPage(1); setRowSelection({}); }, [limit, query]); - useEffect(() => { - if (!router.query.id || sub) return; - setQuery((prev) => ({ ...prev, ids: [router.query.id] })); - }, [router.query]); - const q = useMemo( () => produce(query, (draft) => { - if (issueId) { - draft['issueIds'] = [...(draft['issueIds'] ?? []), issueId]; - } - if (query.ids) draft['ids'] = [draft['ids']]; - if (!sub && createdAtRange) { - draft['createdAt'] = { - gte: dayjs(createdAtRange.startDate).startOf('day').toISOString(), - lt: dayjs(createdAtRange.endDate).endOf('day').toISOString(), - }; + if (sub) { + if (issueId) { + draft['issueIds'] = [...(draft['issueIds'] ?? []), issueId]; + } + Object.keys(draft).forEach((key) => { + if (key === 'issueIds') return; + delete draft[key]; + }); } else { - delete draft['createdAt']; + if (draft['ids']) draft['ids'] = [draft['ids']]; + Object.entries(draft).forEach(([key, value]) => { + if (typeof value === 'string' && value.split('~').length === 2) { + const [gte, lt] = value.split('~'); + draft[key] = { + gte: dayjs(gte).startOf('day').toISOString(), + lt: dayjs(lt).endOf('day').toISOString(), + }; + } + }); + if (createdAtRange) { + draft['createdAt'] = { + gte: dayjs(createdAtRange.startDate).startOf('day').toISOString(), + lt: dayjs(createdAtRange.endDate).endOf('day').toISOString(), + }; + } else { + delete draft['createdAt']; + } } }), [issueId, query, createdAtRange, sub], @@ -169,7 +176,11 @@ const FeedbackTable: React.FC = (props) => {
{ + setPage(1); + setRowSelection({}); + onChangeChannel(channelId); + }} table={table} fieldData={fieldData} meta={data?.meta} @@ -215,29 +226,7 @@ const FeedbackTable: React.FC = (props) => { )}
{header.column.getCanResize() && ( -
- -
+ )} )) diff --git a/apps/web/src/containers/tables/FeedbackTable/FeedbackTableBar/FeedbackTableBar.tsx b/apps/web/src/containers/tables/FeedbackTable/FeedbackTableBar/FeedbackTableBar.tsx index 9059ca55d..747f0b69e 100644 --- a/apps/web/src/containers/tables/FeedbackTable/FeedbackTableBar/FeedbackTableBar.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/FeedbackTableBar/FeedbackTableBar.tsx @@ -180,7 +180,7 @@ const FeedbackTableBar: React.FC = (props) => { )}
diff --git a/apps/web/src/containers/tables/FeedbackTable/FeedbackTableRow/FeedbackTableRow.tsx b/apps/web/src/containers/tables/FeedbackTable/FeedbackTableRow/FeedbackTableRow.tsx index ba7a47777..e155db478 100644 --- a/apps/web/src/containers/tables/FeedbackTable/FeedbackTableRow/FeedbackTableRow.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/FeedbackTableRow/FeedbackTableRow.tsx @@ -15,10 +15,12 @@ */ import { Row, flexRender } from '@tanstack/react-table'; import { Icon, toast } from '@ufb/ui'; +import dayjs from 'dayjs'; import { useCallback, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { ShareButton, TableCheckbox } from '@/components'; +import { DATE_FORMAT } from '@/constants/dayjs-format'; import { useOAIMutation, usePermissions } from '@/hooks'; import useTableStore from '@/zustand/table.store'; @@ -107,8 +109,13 @@ const FeedbackTableRow: React.FC = ({ ) : ( diff --git a/apps/web/src/containers/tables/FeedbackTable/feedback-table.context.tsx b/apps/web/src/containers/tables/FeedbackTable/feedback-table.context.tsx index 91f87e189..59ac5698d 100644 --- a/apps/web/src/containers/tables/FeedbackTable/feedback-table.context.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/feedback-table.context.tsx @@ -27,13 +27,15 @@ import { } from 'react'; import { DEFAULT_DATE_RANGE } from '@/constants/default-date-range'; +import { Path } from '@/constants/path'; import { useLocalColumnSetting, useLocalStorage } from '@/hooks'; +import useQueryParamsState from '@/hooks/useQueryParamsState'; import { DateRangeType } from '@/types/date-range.type'; const DEFAULT_FN = () => {}; interface IFeedbackTableContext { query: Record; - setQuery: Dispatch>>; + setQuery: (_: Record) => void; page: number; setPage: Dispatch>; limit: number; @@ -48,7 +50,7 @@ interface IFeedbackTableContext { projectId: number; channelId: number; createdAtRange: DateRangeType; - setCreatedAtRange: Dispatch>; + setCreatedAtRange: (_: DateRangeType) => void; } export const FeedbackTableContext = createContext({ query: {}, @@ -82,10 +84,9 @@ export const FeedbackTableProvider: React.FC = ({ fixedLimit, }) => { const [page, setPage] = useState(1); - const [query, setQuery] = useState>({}); - const [createdAtRange, setCreatedAtRange] = - useState(DEFAULT_DATE_RANGE); + const { createdAtRange, query, setCreatedAtRange, setQuery } = + useQueryParamsState(Path.FEEDBACK, { projectId, channelId }); const [limit, setLimit] = useLocalStorage(`limit`, 50); diff --git a/apps/web/src/containers/tables/IssueTable/IssueTable.tsx b/apps/web/src/containers/tables/IssueTable/IssueTable.tsx index 737061d1b..402d5f3a6 100644 --- a/apps/web/src/containers/tables/IssueTable/IssueTable.tsx +++ b/apps/web/src/containers/tables/IssueTable/IssueTable.tsx @@ -25,7 +25,6 @@ import { import { Badge, Icon, toast } from '@ufb/ui'; import dayjs from 'dayjs'; import { TFunction, useTranslation } from 'next-i18next'; -import { useRouter } from 'next/router'; import { Fragment, useEffect, useMemo, useState } from 'react'; import { @@ -38,13 +37,14 @@ import { TableCheckbox, TableLoadingRow, TablePagination, + TableResizer, TableSearchInput, TableSortIcon, } from '@/components'; import { SearchItemType } from '@/components/etc/TableSearchInput/TableSearchInput'; -import { DATE_TIME_FORMAT } from '@/constants/dayjs-format'; -import { DEFAULT_DATE_RANGE } from '@/constants/default-date-range'; +import { DATE_FORMAT, DATE_TIME_FORMAT } from '@/constants/dayjs-format'; import { ISSUES, getStatusColor } from '@/constants/issues'; +import { Path } from '@/constants/path'; import { env } from '@/env.mjs'; import { useIssueSearch, @@ -53,6 +53,7 @@ import { usePermissions, useSort, } from '@/hooks'; +import useQueryParamsState from '@/hooks/useQueryParamsState'; import { IssueTrackerType } from '@/types/issue-tracker.type'; import { IssueType } from '@/types/issue.type'; @@ -83,6 +84,7 @@ const getColumns = (t: TFunction, issueTracker?: IssueTrackerType) => [ /> ), size: 40, + enableResizing: false, }), columnHelper.accessor('id', { header: 'ID', @@ -91,24 +93,23 @@ const getColumns = (t: TFunction, issueTracker?: IssueTrackerType) => [ {getValue()} ), - size: 100, + size: 50, + minSize: 50, enableSorting: false, }), columnHelper.accessor('name', { header: 'Name', cell: ({ getValue, row }) => ( - - {getValue()} - +
+ + {getValue()} + +
), - size: 100, + size: 150, + minSize: 50, enableSorting: false, }), - columnHelper.accessor('feedbackCount', { - header: 'Feedback Count', - cell: ({ getValue }) => getValue().toLocaleString(), - size: 100, - }), columnHelper.accessor('description', { header: 'Description', cell: ({ getValue, row }) => ( @@ -117,7 +118,13 @@ const getColumns = (t: TFunction, issueTracker?: IssueTrackerType) => [ ), enableSorting: false, - size: 250, + size: 300, + }), + columnHelper.accessor('feedbackCount', { + header: 'Feedback Count', + cell: ({ getValue }) => getValue().toLocaleString(), + size: 100, + minSize: 100, }), columnHelper.accessor('status', { header: 'Status', @@ -128,7 +135,8 @@ const getColumns = (t: TFunction, issueTracker?: IssueTrackerType) => [ {ISSUES(t).find((v) => v.key === getValue())?.name}
), - size: 70, + size: 100, + minSize: 100, }), columnHelper.accessor('externalIssueId', { header: 'Ticket', @@ -144,16 +152,19 @@ const getColumns = (t: TFunction, issueTracker?: IssueTrackerType) => [ ), enableSorting: false, size: 100, + minSize: 50, }), columnHelper.accessor('createdAt', { header: 'Created', cell: ({ getValue }) => <>{dayjs(getValue()).format(DATE_TIME_FORMAT)}, size: 100, + minSize: 50, }), columnHelper.accessor('updatedAt', { header: 'Updated', cell: ({ getValue }) => <>{dayjs(getValue()).format(DATE_TIME_FORMAT)}, size: 100, + minSize: 50, }), ]; @@ -162,7 +173,6 @@ interface IProps extends React.PropsWithChildren { } const IssueTable: React.FC = ({ projectId }) => { - const router = useRouter(); const perms = usePermissions(); const { t } = useTranslation(); @@ -176,16 +186,10 @@ const IssueTable: React.FC = ({ projectId }) => { const [page, setPage] = useState(1); const [limit, setLimit] = useState(50); - const [createdAtRange, setCreatedAtRange] = useState(DEFAULT_DATE_RANGE); - - const [query, setQuery] = useState>({}); + const { createdAtRange, query, setCreatedAtRange, setQuery } = + useQueryParamsState(Path.ISSUE, { projectId }); const sort = useSort(sorting); - useEffect(() => { - if (!router.query.id) return; - setQuery({ id: router.query.id }); - }, [router.query]); - useEffect(() => { setPage(1); setRowSelection({}); @@ -313,6 +317,7 @@ const IssueTable: React.FC = ({ projectId }) => { setQuery(input)} + query={query} />
@@ -347,6 +352,9 @@ const IssueTable: React.FC = ({ projectId }) => { {header.column.getCanSort() && ( )} + {header.column.getCanResize() && ( + + )} )) )} @@ -390,8 +398,13 @@ const IssueTable: React.FC = ({ projectId }) => { /> , +) => { + const router = useRouter(); + + const query = useMemo(() => { + const newQuery = Object.entries(router.query).reduce( + (acc, [key, value]) => { + if (key in defaultQuery) return acc; + return { ...acc, [key]: value }; + }, + {} as Record, + ); + + return removeEmptyValueInObject(newQuery); + }, [router.query]); + + const createdAtRange = useMemo(() => { + if (!query.createdAt) return DEFAULT_DATE_RANGE; + + const [startDate, endDate] = query.createdAt.split('~'); + + return { + startDate: dayjs(startDate).toDate(), + endDate: dayjs(endDate).toDate(), + }; + }, [query]); + + const setCreatedAtRange = useCallback( + (dateRange: DateRangeType) => { + if (!dateRange) return; + const { startDate, endDate } = dateRange; + router.push( + { + pathname, + query: { + ...defaultQuery, + ...query, + createdAt: `${dayjs(startDate).format(DATE_FORMAT)}~${dayjs( + endDate, + ).format(DATE_FORMAT)}`, + }, + }, + undefined, + { shallow: true }, + ); + }, + [router, query], + ); + + const setQuery = useCallback( + (input: Record) => { + const newQuery = Object.entries(input).reduce((acc, [key, value]) => { + if (typeof value === 'object' && isDate(value)) { + value = `${dayjs(value.gte).format(DATE_FORMAT)}~${dayjs( + value.lt, + ).format(DATE_FORMAT)}`; + } + return { ...acc, [key]: value }; + }, {} as Record); + if (createdAtRange) { + const { startDate, endDate } = createdAtRange; + newQuery['createdAt'] = `${dayjs(startDate).format( + DATE_FORMAT, + )}~${dayjs(endDate).format(DATE_FORMAT)}`; + } + + router.push( + { + pathname, + query: { + ...defaultQuery, + ...newQuery, + }, + }, + undefined, + { shallow: true }, + ); + }, + [router, defaultQuery], + ); + return { query, setQuery, createdAtRange, setCreatedAtRange }; +}; + +export default useQueryParamsState; + +const isDate = (value: any) => { + return 'gte' in value && 'lt' in value; +}; diff --git a/packages/ufb-ui/src/Badge/Badge.tsx b/packages/ufb-ui/src/Badge/Badge.tsx index 82912c477..e290c1dfe 100644 --- a/packages/ufb-ui/src/Badge/Badge.tsx +++ b/packages/ufb-ui/src/Badge/Badge.tsx @@ -150,7 +150,7 @@ export const Badge: React.FC = (props) => { return (
Date: Fri, 13 Oct 2023 19:34:36 +0900 Subject: [PATCH 07/13] refactor: monorepo folder structure (#59) * feat: 3 layers tooling, packages, apps * feat: next config * feat: dockerignore and build.sh * Update docker-beta-image.yml * Update docker-dev-image.yml * Update docker-prod-image.yml * fix: api test --- .dockerignore | 4 +- .eslintignore | 2 - .eslintrc.js | 3 - .github/workflows/docker-beta-image.yml | 4 +- .github/workflows/docker-dev-image.yml | 4 +- .github/workflows/docker-prod-image.yml | 4 +- .prettierignore | 11 - .prettierrc | 8 - apps/api/.eslintrc.js | 2 +- apps/api/package.json | 35 +- apps/api/src/app.module.ts | 2 +- .../api-ok-response-pagination.decorator.ts | 3 +- .../common/decorators/dto-validator.spec.ts | 3 - .../common/dtos/pagination-response.dto.ts | 2 +- .../common/filters/http-exception.filter.ts | 11 +- .../common/repositories/dtos/get-data.dto.ts | 2 +- .../common/repositories/dtos/scroll.dto.ts | 2 +- .../opensearch.repository.spec.ts | 9 +- .../repositories/opensearch.repository.ts | 2 +- .../src/common/validators/array-distinct.ts | 7 +- .../mailer-config/mailer-config.module.ts | 2 +- .../opensearch-config.module.ts | 2 +- .../migrations/1692159572819-init.ts | 275 +- .../1692690482919-issue-name-unique.ts | 27 +- .../typeorm-config.datasource.ts | 6 +- .../typeorm-config/typeorm-config.service.ts | 9 +- .../src/domains/auth/auth.controller.spec.ts | 1 - apps/api/src/domains/auth/auth.controller.ts | 7 +- apps/api/src/domains/auth/auth.module.ts | 3 +- .../api/src/domains/auth/auth.service.spec.ts | 8 +- apps/api/src/domains/auth/auth.service.ts | 13 +- .../src/domains/auth/guards/api-key.guard.ts | 3 +- .../src/domains/auth/guards/jwt-auth.guard.ts | 11 +- .../domains/auth/guards/use-email.guard.ts | 3 +- .../domains/auth/guards/use-oauth.guard.ts | 3 +- .../domains/auth/strategies/jwt.strategy.ts | 4 +- .../domains/auth/strategies/local.strategy.ts | 1 - .../channel/channel.controller.spec.ts | 3 +- .../channel/channel/channel.controller.ts | 1 - .../domains/channel/channel/channel.entity.ts | 1 - .../domains/channel/channel/channel.module.ts | 3 +- .../channel/channel/channel.mysql.service.ts | 9 +- .../channel/channel/channel.service.spec.ts | 5 +- .../channel/channel/channel.service.ts | 4 +- .../channel/channel/create-channel.dto.ts | 3 +- .../channel/dtos/create-channel.dto.ts | 2 +- .../find-all-channels-by-project-id.dto.ts | 2 +- .../find-channel-by-id-response.dto.ts | 2 +- .../find-channels-by-id-response.dto.ts | 2 +- .../field/dtos/create-many-fields.dto.ts | 2 +- .../field/dtos/replace-many-fields.dto.ts | 2 +- .../responses/find-fields-response.dto.ts | 2 +- .../src/domains/channel/field/field.entity.ts | 1 - .../src/domains/channel/field/field.module.ts | 1 - .../channel/field/field.mysql.service.ts | 9 +- .../channel/field/field.service.spec.ts | 5 +- .../domains/channel/field/field.service.ts | 3 +- .../channel/option/option.controller.spec.ts | 3 +- .../channel/option/option.controller.ts | 1 - .../domains/channel/option/option.entity.ts | 1 - .../channel/option/option.service.spec.ts | 3 +- .../domains/channel/option/option.service.ts | 1 - .../feedback/dtos/create-feedback.dto.ts | 2 +- .../dtos/find-feedbacks-by-channel-id.dto.ts | 7 +- .../feedback/dtos/generate-excel.dto.ts | 4 +- .../src/domains/feedback/dtos/os-query.dto.ts | 2 +- ...ind-feedbacks-by-channel-id-request.dto.ts | 5 +- ...nd-feedbacks-by-channel-id-response.dto.ts | 4 +- .../feedback/dtos/scroll-feedbacks.dto.ts | 6 +- .../src/domains/feedback/feedback.common.ts | 3 +- .../feedback/feedback.controller.spec.ts | 7 +- .../domains/feedback/feedback.controller.ts | 1 - .../src/domains/feedback/feedback.entity.ts | 1 - .../src/domains/feedback/feedback.module.ts | 3 +- .../feedback/feedback.mysql.service.ts | 19 +- .../domains/feedback/feedback.os.service.ts | 23 +- .../domains/feedback/feedback.service.spec.ts | 5 +- .../src/domains/feedback/feedback.service.ts | 27 +- .../src/domains/history/create-history.dto.ts | 4 +- .../api/src/domains/history/history.entity.ts | 1 - .../src/domains/history/history.service.ts | 2 +- .../abstract-history.subscriber.ts | 7 +- .../subscribers/api-key-history.subscriber.ts | 1 - .../subscribers/channel-history.subscriber.ts | 1 - .../subscribers/code-history.subscriber.ts | 1 - .../feedback-history.subscriber.ts | 1 - .../feedback-issue-history.subscriber.ts | 10 +- .../subscribers/field-history.subscriber.ts | 1 - .../subscribers/issue-history.subscriber.ts | 1 - .../issue-tracker-history.subscriber.ts | 1 - .../subscribers/member-history.subscriber.ts | 1 - .../subscribers/option-history.subscriber.ts | 1 - .../subscribers/project-history.subscriber.ts | 1 - .../subscribers/role-history.subscriber.ts | 1 - .../subscribers/tenant-history.subscriber.ts | 1 - .../subscribers/user-history.subscriber.ts | 1 - .../src/domains/migration/migration.module.ts | 4 +- .../domains/migration/migration.service.ts | 4 +- .../api-key/api-key.controller.spec.ts | 3 +- .../domains/project/api-key/api-key.entity.ts | 1 - .../project/api-key/api-key.service.spec.ts | 5 +- .../project/api-key/api-key.service.ts | 2 +- .../responses/find-api-keys-response.dto.ts | 2 +- .../issue-tracker.controller.spec.ts | 3 +- .../issue-tracker/issue-tracker.entity.ts | 3 +- .../issue-tracker.service.spec.ts | 3 +- .../dtos/find-issues-by-project-id.dto.ts | 6 +- .../find-issues-by-project-id-request.dto.ts | 5 +- .../dtos/requests/update-issue-request.dto.ts | 1 - .../find-issues-by-project-id-response.dto.ts | 3 +- .../project/issue/issue.controller.spec.ts | 3 +- .../src/domains/project/issue/issue.entity.ts | 1 - .../project/issue/issue.service.spec.ts | 6 +- .../domains/project/issue/issue.service.ts | 24 +- .../member/dtos/find-by-project-id.dto.ts | 2 +- .../dtos/responses/get-all-members.dto.ts | 2 +- .../project/member/member.controller.ts | 1 - .../domains/project/member/member.entity.ts | 1 - .../project/member/member.service.spec.ts | 3 +- .../domains/project/member/member.service.ts | 3 +- .../project/dtos/find-all-projects.dto.ts | 4 +- .../responses/find-projects-response.dto.ts | 3 +- .../project/project.controller.spec.ts | 3 +- .../project/project/project.controller.ts | 1 - .../domains/project/project/project.entity.ts | 5 +- .../domains/project/project/project.module.ts | 3 +- .../project/project/project.service.spec.ts | 6 +- .../project/project/project.service.ts | 6 +- .../project/role/dtos/create-role.dto.ts | 2 +- .../dtos/requests/create-role-request.dto.ts | 1 - .../responses/get-all-role-response.dto.ts | 2 +- .../domains/project/role/permission.guard.ts | 11 +- .../role/require-permission.decorator.ts | 4 +- .../project/role/role.controller.spec.ts | 3 +- .../src/domains/project/role/role.entity.ts | 3 +- .../domains/project/role/role.service.spec.ts | 3 +- .../dtos/responses/get-tenant-response.dto.ts | 2 +- .../domains/tenant/dtos/update-tenant.dto.ts | 2 +- apps/api/src/domains/tenant/tenant.entity.ts | 4 +- .../src/domains/tenant/tenant.service.spec.ts | 3 +- apps/api/src/domains/tenant/tenant.service.ts | 8 +- .../domains/user/create-user.service.spec.ts | 7 +- .../src/domains/user/create-user.service.ts | 4 +- .../user/decorators/current-user.decorator.ts | 3 +- .../user/decorators/is-nullable.decorator.ts | 3 +- .../user/dtos/create-invitation-user.dto.ts | 2 +- .../src/domains/user/dtos/create-user.dto.ts | 8 +- .../domains/user/dtos/find-all-users.dto.ts | 7 +- .../src/domains/user/dtos/invite-user.dto.ts | 4 +- .../requests/get-all-users-request.dto.ts | 1 - .../responses/get-all-user-response.dto.ts | 3 +- .../src/domains/user/dtos/update-user.dto.ts | 2 +- .../src/domains/user/entities/user.entity.ts | 4 +- .../src/domains/user/super-user.decorator.ts | 2 +- apps/api/src/domains/user/super-user.guard.ts | 3 +- .../user/user-password.service.spec.ts | 3 +- .../src/domains/user/user-password.service.ts | 1 - .../src/domains/user/user.controller.spec.ts | 1 - apps/api/src/domains/user/user.controller.ts | 1 - apps/api/src/domains/user/user.module.ts | 1 - .../api/src/domains/user/user.service.spec.ts | 4 +- apps/api/src/domains/user/user.service.ts | 6 +- apps/api/src/main.ts | 10 +- apps/api/src/shared/code/code.entity.ts | 1 - apps/api/src/shared/code/code.module.ts | 1 - apps/api/src/shared/code/code.service.spec.ts | 3 +- apps/api/src/shared/code/code.service.ts | 2 +- .../shared/code/dtos/set-code-verified.dto.ts | 2 +- apps/api/src/shared/code/dtos/set-code.dto.ts | 7 +- ...email-verification-mailing.service.spec.ts | 1 - .../email-verification-mailing.service.ts | 2 +- apps/api/src/shared/mailing/mailing.module.ts | 1 - .../reset-password-mailing.service.spec.ts | 3 +- .../mailing/reset-password-mailing.service.ts | 5 +- .../user-invitation-mailing.service.spec.ts | 3 +- .../user-invitation-mailing.service.ts | 5 +- apps/api/src/types/cls-service.type.ts | 2 +- apps/api/src/types/config-service.type.ts | 12 +- apps/api/src/utils/test-util-fixture.ts | 6 +- apps/api/src/utils/test-utils.ts | 6 +- apps/api/test/auth.e2e-spec.ts | 10 +- apps/api/test/feedback/channel.e2e-spec.ts | 10 +- apps/api/test/feedback/feedback.e2e-spec.ts | 8 +- apps/api/test/feedback/project.e2e-spec.ts | 8 +- apps/api/test/role.e2e-spec.ts | 8 +- apps/api/test/tenant.e2e-spec.ts | 8 +- apps/api/test/user.e2e-spec.ts | 8 +- apps/api/tsconfig.json | 19 +- apps/web/.eslintrc.js | 10 - apps/web/{jest.config.js => jest.config.mjs} | 6 +- apps/web/jest.setup.js | 20 - apps/web/next-i18next.config.js | 15 - apps/web/next.config.mjs | 47 + apps/web/package.json | 42 +- .../cards/ChannelCard/ChannelCard.tsx | 22 +- .../etc/CheckedTableHead/CheckedTableHead.tsx | 11 +- .../etc/DateRangePicker/DateRangePicker.tsx | 15 +- .../src/components/etc/Dialog/Dialog_back.tsx | 10 +- .../etc/Dialog/PopoverModalContent.tsx | 7 +- .../etc/IssueCircle/IssueCircle.tsx | 2 +- .../PopoverModalContent.tsx | 7 +- apps/web/src/components/etc/Popper/Popper.tsx | 8 +- .../components/etc/SelectBox/SelectBox.tsx | 6 +- .../etc/SelectBox/SelectBoxCreatable.tsx | 8 +- .../SelectBoxWithIcon/SelectBoxWithIcon.tsx | 6 +- .../etc/ShareButton/ShareButton.tsx | 5 +- .../etc/TableCheckbox/TableCheckbox.tsx | 3 +- .../etc/TableLoadingRow/TableLoadingRow.tsx | 4 +- .../etc/TablePagination/TablePagination.tsx | 3 +- .../etc/TableResizer/TableResizer.tsx | 5 +- .../etc/TableSearchInput/TableSearchInput.tsx | 24 +- .../TableSearchInputPopover.tsx | 12 +- .../table-search-input.service.ts | 25 +- .../etc/TableSortIcon/TableSortIcon.tsx | 3 +- .../src/components/etc/Tooltip/Tooltip.tsx | 45 - apps/web/src/components/etc/index.ts | 1 - .../src/components/layouts/Header/Header.tsx | 12 +- .../components/layouts/Header/HeaderName.tsx | 9 +- .../layouts/Header/LocaleSelectBox.tsx | 13 +- .../components/layouts/Header/ProfileBox.tsx | 11 +- .../components/layouts/SideNav/SideNav.tsx | 14 +- .../layouts/setting-menu/SettingMenuBox.tsx | 2 +- .../layouts/setting-menu/SettingMenuItem.tsx | 7 +- .../setting-menu/SettingMenuSubtitle.tsx | 7 +- .../templates/AuthTemplate/AuthTemplate.tsx | 4 +- .../templates/MainTemplate/MainTemplate.tsx | 4 +- .../SettingMenuTemplate.tsx | 4 +- apps/web/src/constants/default-date-range.ts | 2 +- apps/web/src/constants/i18n.ts | 4 +- apps/web/src/constants/iron-option.ts | 2 +- apps/web/src/constants/issues.ts | 4 +- .../my-profile/ChangePasswordForm.tsx | 5 +- .../my-profile/DeleteMyAccountButton.tsx | 7 +- .../containers/my-profile/MyProfileForm.tsx | 8 +- .../APIKeySetting/APIKeyDeleteButton.tsx | 3 +- .../APIKeySetting/APIKeyEditButton.tsx | 7 +- .../APIKeySetting/APIKeySetting.tsx | 10 +- .../ChannelDeleteSetting.tsx | 16 +- .../ChannelInfoSetting/ChannelInfoSetting.tsx | 5 +- .../setting-menu/ChannelSettingMenu.tsx | 6 +- .../FieldSetting/FeedbackRequestPopover.tsx | 9 +- .../FieldSetting/FieldSetting.tsx | 26 +- .../FieldSetting/FieldSettingPopover.tsx | 28 +- .../setting-menu/FieldSetting/OptionBadge.tsx | 7 +- .../FieldSetting/OptionInfoPopover.tsx | 9 +- .../FieldSetting/PreviewTable.tsx | 7 +- .../MemberSetting/MemberDeleteDialog.tsx | 3 +- .../MemberSetting/MemberInvitationDialog.tsx | 10 +- .../MemberSetting/MemberSetting.tsx | 12 +- .../MemberSetting/MemberUpdatePopover.tsx | 8 +- .../ProjectDeleteSetting.tsx | 17 +- .../ProjectInfoSetting/ProjectInfoSetting.tsx | 5 +- .../setting-menu/ProjectSettingMenu.tsx | 2 +- .../RoleSetting/AddRoleDialog.tsx | 3 +- .../RoleSetting/PermissionRows.tsx | 4 +- .../setting-menu/RoleSetting/RoleSetting.tsx | 6 +- .../RoleSetting/RoleSettingHead.tsx | 13 +- .../setting-menu/SignUpSetting/OAuthInput.tsx | 7 +- .../setting-menu/SignUpSetting/RadioGroup.tsx | 2 +- .../SignUpSetting/SignUpSetting.tsx | 12 +- .../TenantInfoSetting/TenantInfoSetting.tsx | 5 +- .../setting-menu/TenantSettingMenu.tsx | 2 +- .../TicketSetting/TicketSetting.tsx | 11 +- .../UserSetting/UserEditPopover.tsx | 14 +- .../UserSetting/UserInvitationDialog.tsx | 11 +- .../setting-menu/UserSetting/UserSetting.tsx | 15 +- .../AllExpandButton/AllExpandButton.tsx | 8 +- .../ChannelSelectBox/ChannelSelectBox.tsx | 7 +- .../ColumnSettingPopover.tsx | 28 +- .../DraggableColumnItem.tsx | 5 +- .../DownloadButton/DownloadButton.tsx | 26 +- .../EditableCell/EditableCell.tsx | 9 +- .../FeedbackCell/FeedbackCell.tsx | 4 +- .../FeedbackDeleteDialog.tsx | 3 +- .../tables/FeedbackTable/FeedbackTable.tsx | 26 +- .../FeedbackTableBar/FeedbackTableBar.tsx | 19 +- .../FeedbackTable/FeedbackTableInIssue.tsx | 5 +- .../FeedbackTableRow/FeedbackTableRow.tsx | 9 +- .../FeedbackTable/FeedbackTableWrapper.tsx | 5 +- .../FeedbackTable/IssueCell/IssueCell.tsx | 26 +- .../FeedbackTable/IssueCell/IssueSetting.tsx | 13 +- .../FeedbackTable/feedback-table-columns.tsx | 6 +- .../FeedbackTable/feedback-table.context.tsx | 13 +- .../IssueSettingPopover.tsx | 23 +- .../IssueTabelSelectBox.tsx | 8 +- .../tables/IssueTable/IssueTable.tsx | 37 +- .../tables/IssueTable/TableRow/TableRow.tsx | 2 +- .../tables/IssueTable/TicketLink.tsx | 9 +- apps/web/src/contexts/tenant.context.tsx | 6 +- apps/web/src/contexts/user.context.tsx | 12 +- apps/web/src/env.mjs | 54 +- apps/web/src/hooks/useCurrentProjectId.ts | 2 +- apps/web/src/hooks/useDownload.ts | 5 +- apps/web/src/hooks/useFeedbackSearch.ts | 7 +- apps/web/src/hooks/useIssueSearch.ts | 5 +- apps/web/src/hooks/useLocalColumnSetting.ts | 2 +- apps/web/src/hooks/useLocalStorage.ts | 2 +- apps/web/src/hooks/useOAIMutation.ts | 7 +- apps/web/src/hooks/useOAIQuery.ts | 2 +- apps/web/src/hooks/usePermissions.ts | 6 +- apps/web/src/hooks/useQueryParamsState.ts | 25 +- apps/web/src/hooks/useSort.ts | 2 +- apps/web/src/hooks/useUserSearch.ts | 5 +- apps/web/src/libs/client.ts | 4 +- apps/web/src/libs/session-storage.ts | 2 +- apps/web/src/middleware.ts | 2 +- apps/web/src/pages/_app.tsx | 15 +- apps/web/src/pages/_document.tsx | 10 +- apps/web/src/pages/api/health.ts | 2 +- apps/web/src/pages/auth/oauth-callback.tsx | 9 +- apps/web/src/pages/auth/reset-password.tsx | 20 +- apps/web/src/pages/auth/sign-in.tsx | 23 +- apps/web/src/pages/auth/sign-up.tsx | 26 +- apps/web/src/pages/link/reset-password.tsx | 22 +- apps/web/src/pages/link/user-invitation.tsx | 20 +- .../src/pages/main/[projectId]/feedback.tsx | 2 +- apps/web/src/pages/main/[projectId]/issue.tsx | 5 +- .../pages/main/[projectId]/not-permission.tsx | 2 +- .../src/pages/main/[projectId]/setting.tsx | 14 +- apps/web/src/pages/main/index.tsx | 30 +- apps/web/src/pages/main/profile.tsx | 27 +- apps/web/src/pages/tenant/create.tsx | 14 +- apps/web/src/types/api.type.ts | 757 ++-- apps/web/src/types/channel.type.ts | 2 +- apps/web/src/types/role.type.ts | 2 +- apps/web/src/types/svg.d.ts | 22 + apps/web/src/utils/reorder.ts | 4 +- apps/web/src/utils/test-utils.tsx | 5 +- apps/web/tsconfig.json | 20 +- apps/api/Dockerfile => docker/api.dockerfile | 0 {deploy => docker}/build.sh | 4 +- .../docker-compose.infra.yml | 0 .../docker-compose.yml | 8 +- apps/web/Dockerfile => docker/web.dockerfile | 5 +- package.json | 42 +- packages/eslint-config-ufb/index.js | 55 - packages/eslint-config-ufb/package.json | 18 - packages/ufb-tailwind/.eslintrc.js | 4 - packages/ufb-tailwind/package.json | 27 +- packages/ufb-tailwind/src/colors.js | 15 + packages/ufb-tailwind/src/index.d.ts | 20 + packages/ufb-tailwind/src/index.js | 31 +- packages/ufb-tailwind/src/theme.js | 15 + .../src/utilities/tailwind.config.js | 1 + packages/ufb-tailwind/tsconfig.json | 5 + packages/ufb-tsconfig/README.md | 3 - packages/ufb-tsconfig/base.json | 19 - packages/ufb-ui/.eslintrc.js | 10 - packages/ufb-ui/package.json | 51 +- .../index.ts => packages/ufb-ui/postcss.js | 3 +- packages/ufb-ui/rollup.config.js | 37 - packages/ufb-ui/src/Badge/Badge.tsx | 8 +- packages/ufb-ui/src/Dialog/Dialog.tsx | 13 +- packages/ufb-ui/src/Popover/Popover.tsx | 12 +- packages/ufb-ui/src/Toast/ToastBox.tsx | 9 +- packages/ufb-ui/src/Toast/ToastPromiseBox.tsx | 9 +- packages/ufb-ui/src/Toast/toast.tsx | 5 +- packages/ufb-ui/src/Tooltip/Tooltip.tsx | 82 +- packages/ufb-ui/src/inputs/Input.tsx | 7 +- packages/ufb-ui/src/inputs/TextInput.tsx | 6 +- packages/ufb-ui/src/types/svg.d.ts | 2 +- packages/ufb-ui/tailwind.config.js | 5 + packages/ufb-ui/tsconfig.json | 11 +- tooling/eslint/base.js | 72 + .../eslint/nestjs.js | 26 +- tooling/eslint/nextjs.js | 21 + tooling/eslint/package.json | 43 + tooling/eslint/react.js | 25 + tooling/eslint/tsconfig.json | 8 + tooling/prettier/index.mjs | 33 + tooling/prettier/package.json | 21 + tooling/prettier/tsconfig.json | 8 + .../typescript/base.json | 14 +- .../typescript}/nestjs.json | 5 +- .../typescript}/package.json | 3 +- .../typescript}/react-library.json | 4 +- turbo.json | 87 +- yarn.lock | 3116 ++++++++++------- 378 files changed, 4272 insertions(+), 3152 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 apps/web/.eslintrc.js rename apps/web/{jest.config.js => jest.config.mjs} (79%) delete mode 100644 apps/web/jest.setup.js create mode 100644 apps/web/next.config.mjs delete mode 100644 apps/web/src/components/etc/Tooltip/Tooltip.tsx create mode 100644 apps/web/src/types/svg.d.ts rename apps/api/Dockerfile => docker/api.dockerfile (100%) rename {deploy => docker}/build.sh (88%) rename docker-compose.infra.yml => docker/docker-compose.infra.yml (100%) rename docker-compose.yml => docker/docker-compose.yml (91%) rename apps/web/Dockerfile => docker/web.dockerfile (92%) delete mode 100644 packages/eslint-config-ufb/index.js delete mode 100644 packages/eslint-config-ufb/package.json delete mode 100644 packages/ufb-tailwind/.eslintrc.js create mode 100644 packages/ufb-tailwind/src/index.d.ts create mode 100644 packages/ufb-tailwind/tsconfig.json delete mode 100644 packages/ufb-tsconfig/README.md delete mode 100644 packages/ufb-tsconfig/base.json delete mode 100644 packages/ufb-ui/.eslintrc.js rename apps/web/src/components/etc/Tooltip/index.ts => packages/ufb-ui/postcss.js (90%) delete mode 100644 packages/ufb-ui/rollup.config.js create mode 100644 packages/ufb-ui/tailwind.config.js create mode 100644 tooling/eslint/base.js rename apps/web/next.config.js => tooling/eslint/nestjs.js (57%) create mode 100644 tooling/eslint/nextjs.js create mode 100644 tooling/eslint/package.json create mode 100644 tooling/eslint/react.js create mode 100644 tooling/eslint/tsconfig.json create mode 100644 tooling/prettier/index.mjs create mode 100644 tooling/prettier/package.json create mode 100644 tooling/prettier/tsconfig.json rename packages/ufb-tsconfig/nextjs.json => tooling/typescript/base.json (68%) rename {packages/ufb-tsconfig => tooling/typescript}/nestjs.json (85%) rename {packages/ufb-tsconfig => tooling/typescript}/package.json (75%) rename {packages/ufb-tsconfig => tooling/typescript}/react-library.json (80%) diff --git a/.dockerignore b/.dockerignore index 6db31129e..279a8592a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,4 +2,6 @@ **/.next **/dist **/.env* -!apps/web/.env.build \ No newline at end of file +!apps/web/.env.build +docker +volumes \ No newline at end of file diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index ec0c01863..000000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -jest.config.* -api.type.ts \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index e35135249..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - root: true, -}; diff --git a/.github/workflows/docker-beta-image.yml b/.github/workflows/docker-beta-image.yml index f43b7022e..2efeabd67 100644 --- a/.github/workflows/docker-beta-image.yml +++ b/.github/workflows/docker-beta-image.yml @@ -34,7 +34,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./apps/api/Dockerfile + file: ./docker/api.dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.api-meta.outputs.tags }} labels: ${{ steps.api-meta.outputs.labels }} @@ -67,7 +67,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./apps/web/Dockerfile + file: ./docker/web.dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.web-meta.outputs.tags }} labels: ${{ steps.web-meta.outputs.labels }} diff --git a/.github/workflows/docker-dev-image.yml b/.github/workflows/docker-dev-image.yml index 47ef03d63..3fbd81d04 100644 --- a/.github/workflows/docker-dev-image.yml +++ b/.github/workflows/docker-dev-image.yml @@ -34,7 +34,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./apps/api/Dockerfile + file: ./docker/api.dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.api-meta.outputs.tags }} labels: ${{ steps.api-meta.outputs.labels }} @@ -67,7 +67,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./apps/web/Dockerfile + file: ./docker/web.dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.web-meta.outputs.tags }} labels: ${{ steps.web-meta.outputs.labels }} diff --git a/.github/workflows/docker-prod-image.yml b/.github/workflows/docker-prod-image.yml index 8e2711d1b..cb5baaeb6 100644 --- a/.github/workflows/docker-prod-image.yml +++ b/.github/workflows/docker-prod-image.yml @@ -36,7 +36,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./apps/api/Dockerfile + file: ./docker/api.dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.api-meta.outputs.tags }} labels: ${{ steps.api-meta.outputs.labels }} @@ -69,7 +69,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: ./apps/web/Dockerfile + file: ./docker/web.dockerfile push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.web-meta.outputs.tags }} labels: ${{ steps.web-meta.outputs.labels }} diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index af41fa5aa..000000000 --- a/.prettierignore +++ /dev/null @@ -1,11 +0,0 @@ -migrations - - -api.type.ts - -dist -.next - -volumes - -node_modules \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 983f234af..000000000 --- a/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all", - "importOrder": ["", "^@/(.*)$", "^[./]", "^[../]"], - "importOrderSeparation": true, - "importOrderSortSpecifiers": true, - "importOrderParserPlugins": ["typescript", "jsx", "decorators-legacy"] -} diff --git a/apps/api/.eslintrc.js b/apps/api/.eslintrc.js index b42f4d403..57bf1108d 100644 --- a/apps/api/.eslintrc.js +++ b/apps/api/.eslintrc.js @@ -1,6 +1,6 @@ module.exports = { root: true, - extends: ['ufb'], + extends: ['@ufb/eslint-config/base'], parserOptions: { project: 'tsconfig.json', tsconfigRootDir: __dirname, diff --git a/apps/api/package.json b/apps/api/package.json index 977e8db85..ade364d84 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,28 +1,29 @@ { "name": "api", "version": "0.0.1", - "description": "", - "author": "", "private": true, - "license": "UNLICENSED", "scripts": { "build": "nest build", + "clean": "git clean -xdf .next .turbo node_modules", "dev": "nest start --watch", + "format": "prettier --check \"./src/**/*.{js,cjs,mjs,ts,tsx,md,json}\"", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"", + "migration:generate": "npm run typeorm -- migration:generate src/configs/modules/typeorm-config/migrations/$npm_config_name", + "migration:revert": "npm run typeorm -- migration:revert", + "migration:run": "npm run typeorm -- migration:run", "start": "nest start", - "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", + "start:dev": "nest start --watch", "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"", "test": "jest --detectOpenHandles --forceExit", - "test:watch": "jest --watch --detectOpenHandles", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json --runInBand --detectOpenHandles", - "typeorm": "ts-node --project ./tsconfig.json -r tsconfig-paths/register ./node_modules/typeorm/cli -d src/configs/modules/typeorm-config/typeorm-config.datasource.ts", - "migration:generate": "npm run typeorm -- migration:generate src/configs/modules/typeorm-config/migrations/$npm_config_name", - "migration:run": "npm run typeorm -- migration:run", - "migration:revert": "npm run typeorm -- migration:revert" + "test:watch": "jest --watch --detectOpenHandles", + "typecheck": "tsc --noEmit", + "typeorm": "ts-node --project ./tsconfig.json -r tsconfig-paths/register ./node_modules/typeorm/cli -d src/configs/modules/typeorm-config/typeorm-config.datasource.ts" }, + "prettier": "@ufb/prettier-config", "dependencies": { "@fastify/static": "^6.10.2", "@nestjs-modules/mailer": "^1.9.1", @@ -74,21 +75,21 @@ "@swc/core": "^1.3.62", "@types/bcrypt": "^5.0.0", "@types/express": "^4.17.17", - "@types/jest": "29.2.4", + "@types/jest": "^29.5.2", "@types/node": "18.11.18", "@types/nodemailer": "^6.4.8", "@types/supertest": "^2.0.12", - "@ufb/tsconfig": "0.0.0", - "eslint": "^8.42.0", - "eslint-config-ufb": "0.0.0", - "jest": "29.3.1", + "@ufb/eslint-config": "^0.1.0", + "@ufb/prettier-config": "^0.1.0", + "@ufb/tsconfig": "^0.1.0", + "eslint": "^8.50.0", + "jest": "^29.5.0", "mockdate": "^3.0.5", - "prettier": "^2.8.8", "supertest": "^6.3.3", "ts-jest": "29.0.3", "ts-loader": "^9.4.3", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", - "typescript": "^4.9.5" + "typescript": "4.9.5" } } diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index a3967bc0f..7d4c76f9b 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -26,7 +26,7 @@ import { OpensearchConfigModule, TypeOrmConfigModule, } from './configs/modules'; -import { mySqlConfigSchema, mysqlConfig } from './configs/mysql.config'; +import { mysqlConfig, mySqlConfigSchema } from './configs/mysql.config'; import { opensearchConfig, opensearchSchema, diff --git a/apps/api/src/common/decorators/api-ok-response-pagination.decorator.ts b/apps/api/src/common/decorators/api-ok-response-pagination.decorator.ts index 82edd97c8..3a3146b77 100644 --- a/apps/api/src/common/decorators/api-ok-response-pagination.decorator.ts +++ b/apps/api/src/common/decorators/api-ok-response-pagination.decorator.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Type, applyDecorators } from '@nestjs/common'; +import type { Type } from '@nestjs/common'; +import { applyDecorators } from '@nestjs/common'; import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger'; import { PaginationResponseDto } from '../dtos/pagination-response.dto'; diff --git a/apps/api/src/common/decorators/dto-validator.spec.ts b/apps/api/src/common/decorators/dto-validator.spec.ts index 908eefb8f..1ac260fe2 100644 --- a/apps/api/src/common/decorators/dto-validator.spec.ts +++ b/apps/api/src/common/decorators/dto-validator.spec.ts @@ -14,9 +14,6 @@ * under the License. */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -/* eslint-disable @typescript-eslint/no-empty-function */ import { IsString } from 'class-validator'; import DtoValidator from './dto-validator'; diff --git a/apps/api/src/common/dtos/pagination-response.dto.ts b/apps/api/src/common/dtos/pagination-response.dto.ts index 3f7f73e1f..0ff16b358 100644 --- a/apps/api/src/common/dtos/pagination-response.dto.ts +++ b/apps/api/src/common/dtos/pagination-response.dto.ts @@ -15,7 +15,7 @@ */ import { ApiProperty } from '@nestjs/swagger'; import { Expose, Type } from 'class-transformer'; -import { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; +import type { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; class PaginationMetaDto implements IPaginationMeta { @ApiProperty() diff --git a/apps/api/src/common/filters/http-exception.filter.ts b/apps/api/src/common/filters/http-exception.filter.ts index 78e650ce0..2c4a771b2 100644 --- a/apps/api/src/common/filters/http-exception.filter.ts +++ b/apps/api/src/common/filters/http-exception.filter.ts @@ -13,14 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { - ArgumentsHost, - Catch, - ExceptionFilter, - HttpException, - Logger, -} from '@nestjs/common'; -import { FastifyReply, FastifyRequest } from 'fastify'; +import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'; +import { Catch, HttpException, Logger } from '@nestjs/common'; +import type { FastifyReply, FastifyRequest } from 'fastify'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { diff --git a/apps/api/src/common/repositories/dtos/get-data.dto.ts b/apps/api/src/common/repositories/dtos/get-data.dto.ts index 30f67ae9e..46c0d5828 100644 --- a/apps/api/src/common/repositories/dtos/get-data.dto.ts +++ b/apps/api/src/common/repositories/dtos/get-data.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { PaginationDto } from '@/common/dtos'; -import { OsQueryDto } from '@/domains/feedback/dtos/os-query.dto'; +import type { OsQueryDto } from '@/domains/feedback/dtos/os-query.dto'; export class GetDataDto extends PaginationDto { index: string; diff --git a/apps/api/src/common/repositories/dtos/scroll.dto.ts b/apps/api/src/common/repositories/dtos/scroll.dto.ts index 9e9e3dc6a..274a2cbfd 100644 --- a/apps/api/src/common/repositories/dtos/scroll.dto.ts +++ b/apps/api/src/common/repositories/dtos/scroll.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { OsQueryDto } from '@/domains/feedback/dtos/os-query.dto'; +import type { OsQueryDto } from '@/domains/feedback/dtos/os-query.dto'; export class ScrollDto { index: string; diff --git a/apps/api/src/common/repositories/opensearch.repository.spec.ts b/apps/api/src/common/repositories/opensearch.repository.spec.ts index ee149e1c3..f55d85fe8 100644 --- a/apps/api/src/common/repositories/opensearch.repository.spec.ts +++ b/apps/api/src/common/repositories/opensearch.repository.spec.ts @@ -19,10 +19,9 @@ import { NotFoundException, } from '@nestjs/common'; import { Test } from '@nestjs/testing'; -import { Client } from '@opensearch-project/opensearch'; +import type { Client } from '@opensearch-project/opensearch'; import { getMockProvider } from '@/utils/test-utils'; - import { CreateDataDto, PutMappingsDto } from './dtos'; import { OpensearchRepository } from './opensearch.repository'; @@ -248,21 +247,15 @@ describe('Opensearch Repository Test suite', () => { }); }); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('getData', () => {}); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('scroll', () => {}); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('updateData', () => {}); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('deleteBulkData', () => {}); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('deleteIndex', () => {}); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('getTotal', () => {}); }); diff --git a/apps/api/src/common/repositories/opensearch.repository.ts b/apps/api/src/common/repositories/opensearch.repository.ts index cb4a3d34f..c33b6f23c 100644 --- a/apps/api/src/common/repositories/opensearch.repository.ts +++ b/apps/api/src/common/repositories/opensearch.repository.ts @@ -21,7 +21,7 @@ import { } from '@nestjs/common'; import { Client, errors } from '@opensearch-project/opensearch'; -import { +import type { CreateDataDto, CreateIndexDto, DeleteBulkDataDto, diff --git a/apps/api/src/common/validators/array-distinct.ts b/apps/api/src/common/validators/array-distinct.ts index 3773eb966..bd8c7cb99 100644 --- a/apps/api/src/common/validators/array-distinct.ts +++ b/apps/api/src/common/validators/array-distinct.ts @@ -13,11 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { - ValidationArguments, - ValidationOptions, - registerDecorator, -} from 'class-validator'; +import type { ValidationArguments, ValidationOptions } from 'class-validator'; +import { registerDecorator } from 'class-validator'; export const ArrayDistinct = ( property?: string, diff --git a/apps/api/src/configs/modules/mailer-config/mailer-config.module.ts b/apps/api/src/configs/modules/mailer-config/mailer-config.module.ts index 238ce38e7..ec8c612aa 100644 --- a/apps/api/src/configs/modules/mailer-config/mailer-config.module.ts +++ b/apps/api/src/configs/modules/mailer-config/mailer-config.module.ts @@ -18,7 +18,7 @@ import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handleba import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; -import { ConfigServiceType } from '@/types/config-service.type'; +import type { ConfigServiceType } from '@/types/config-service.type'; @Module({ imports: [ diff --git a/apps/api/src/configs/modules/opensearch-config/opensearch-config.module.ts b/apps/api/src/configs/modules/opensearch-config/opensearch-config.module.ts index f2d9e428a..435dbb952 100644 --- a/apps/api/src/configs/modules/opensearch-config/opensearch-config.module.ts +++ b/apps/api/src/configs/modules/opensearch-config/opensearch-config.module.ts @@ -18,7 +18,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config'; import { Client } from '@opensearch-project/opensearch'; import * as dotenv from 'dotenv'; -import { ConfigServiceType } from '@/types/config-service.type'; +import type { ConfigServiceType } from '@/types/config-service.type'; dotenv.config(); diff --git a/apps/api/src/configs/modules/typeorm-config/migrations/1692159572819-init.ts b/apps/api/src/configs/modules/typeorm-config/migrations/1692159572819-init.ts index 9d636dc93..a1e9615b0 100644 --- a/apps/api/src/configs/modules/typeorm-config/migrations/1692159572819-init.ts +++ b/apps/api/src/configs/modules/typeorm-config/migrations/1692159572819-init.ts @@ -1,86 +1,199 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; +import { MigrationInterface, QueryRunner } from 'typeorm'; export class Init1692159572819 implements MigrationInterface { - name = 'Init1692159572819' + name = 'Init1692159572819'; - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE TABLE \`tenant\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`site_name\` varchar(50) NOT NULL, \`description\` varchar(255) NULL, \`use_email\` tinyint NOT NULL DEFAULT 1, \`is_private\` tinyint NOT NULL DEFAULT 0, \`is_restrict_domain\` tinyint NOT NULL DEFAULT 0, \`allow_domains\` text NULL, \`use_o_auth\` tinyint NOT NULL DEFAULT 0, \`oauth_config\` json NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`issues\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`status\` enum ('INIT', 'ON_REVIEW', 'IN_PROGRESS', 'RESOLVED', 'PENDING') NOT NULL DEFAULT 'INIT', \`external_issue_id\` varchar(255) NULL, \`feedback_count\` int NOT NULL DEFAULT '0', \`project_id\` int NULL, INDEX \`IDX_b7fd6df20da19c630741ea9045\` (\`status\`), INDEX \`IDX_db94fcc9ef9f968b43ec5d2b2a\` (\`feedback_count\`), INDEX \`IDX_8e64309f790aa4270b955a9947\` (\`project_id\`, \`created_at\`), UNIQUE INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`feedbacks\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`raw_data\` json NOT NULL, \`additional_data\` json NULL, \`channel_id\` int NULL, INDEX \`IDX_a640975f8ccf17d9337d4ff828\` (\`created_at\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`options\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`key\` varchar(255) NOT NULL, \`field_id\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`fields\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`key\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`format\` enum ('text', 'keyword', 'number', 'boolean', 'select', 'multiSelect', 'date') NOT NULL, \`type\` enum ('DEFAULT', 'ADMIN', 'API') NOT NULL, \`status\` enum ('ACTIVE', 'INACTIVE') NOT NULL, \`channel_id\` int NULL, INDEX \`IDX_4b2181db660323e7ae856adeae\` (\`created_at\`), UNIQUE INDEX \`field-name-unique\` (\`name\`, \`channel_id\`), UNIQUE INDEX \`field-key-unique\` (\`key\`, \`channel_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`channels\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`project_id\` int NULL, INDEX \`IDX_1233531abfb8d56d2a15050143\` (\`name\`, \`created_at\`), UNIQUE INDEX \`project-name-unique\` (\`name\`, \`project_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`projects\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`tenant_id\` int NULL, UNIQUE INDEX \`IDX_2187088ab5ef2a918473cb9900\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`roles\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`permissions\` text NOT NULL, \`project_id\` int NULL, INDEX \`IDX_f4f2789197a3cbbc0182396b26\` (\`name\`, \`project_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`members\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`role_id\` int NULL, \`user_id\` int NULL, UNIQUE INDEX \`IDX_858f5ec01bcfe14ab3f2a328dc\` (\`role_id\`, \`user_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`users\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`email\` varchar(320) NULL, \`name\` varchar(255) NULL, \`department\` varchar(255) NULL, \`state\` enum ('Active', 'Blocked') NOT NULL DEFAULT 'Active', \`hash_password\` varchar(255) NULL, \`type\` enum ('SUPER', 'GENERAL') NOT NULL DEFAULT 'GENERAL', \`sign_up_method\` enum ('EMAIL', 'OAUTH') NOT NULL DEFAULT 'EMAIL', UNIQUE INDEX \`IDX_1301b11757c5b489adc8bc05e4\` (\`email\`, \`sign_up_method\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`histories\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`entity_name\` enum ('ApiKey', 'Channel', 'Feedback', 'Field', 'IssueTracker', 'Issue', 'Member', 'Option', 'Project', 'Role', 'Tenant', 'User', 'FeedbackIssue', 'Code') NOT NULL, \`entity_id\` decimal NOT NULL, \`action\` enum ('Create', 'Update', 'Delete', 'SoftDelete', 'Download', 'Recover') NOT NULL, \`entity\` json NOT NULL, \`user_id\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`codes\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`type\` enum ('EMAIL_VEIRIFICATION', 'RESET_PASSWORD', 'USER_INVITATION') NOT NULL, \`key\` varchar(255) NOT NULL, \`code\` varchar(255) NOT NULL, \`data\` varchar(255) NULL, \`is_verified\` tinyint NOT NULL DEFAULT 0, \`expired_at\` datetime NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`api_keys\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`value\` varchar(255) NOT NULL, \`project_id\` int NULL, UNIQUE INDEX \`IDX_2662a95fc4dd64493ca686a82f\` (\`value\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`issue_trackers\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`data\` json NULL, \`project_id\` int NULL, UNIQUE INDEX \`REL_0d000918b0c670b7d2488257dd\` (\`project_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); - await queryRunner.query(`CREATE TABLE \`feedbacks_issues_issues\` (\`feedbacks_id\` int NOT NULL, \`issues_id\` int NOT NULL, INDEX \`IDX_3435079c319679ba3aaccd806b\` (\`feedbacks_id\`), INDEX \`IDX_6d6f24cf306a31c0af7b50973a\` (\`issues_id\`), PRIMARY KEY (\`feedbacks_id\`, \`issues_id\`)) ENGINE=InnoDB`); - await queryRunner.query(`ALTER TABLE \`issues\` ADD CONSTRAINT \`FK_11f35e8296e10c229e7b68c68d4\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`feedbacks\` ADD CONSTRAINT \`FK_4adbe5e6c46eba8a93a0265a078\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`options\` ADD CONSTRAINT \`FK_dc520ce6f54769336c4afa5e9b9\` FOREIGN KEY (\`field_id\`) REFERENCES \`fields\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`fields\` ADD CONSTRAINT \`FK_da856f4b147eb542917c5968c43\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`channels\` ADD CONSTRAINT \`FK_63c4e21cafd9504a7c139144d1c\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`projects\` ADD CONSTRAINT \`FK_7393a03ef67e2ea91b81faa95dd\` FOREIGN KEY (\`tenant_id\`) REFERENCES \`tenant\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`roles\` ADD CONSTRAINT \`FK_cb48212dfe65dfe431d486034d2\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`members\` ADD CONSTRAINT \`FK_274c5ebb3c595f5a56f1f8fba9a\` FOREIGN KEY (\`role_id\`) REFERENCES \`roles\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`members\` ADD CONSTRAINT \`FK_da404b5fd9c390e25338996e2d1\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`api_keys\` ADD CONSTRAINT \`FK_f5de07dbb229225e2be643ff3d0\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`issue_trackers\` ADD CONSTRAINT \`FK_0d000918b0c670b7d2488257dd7\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE \`feedbacks_issues_issues\` ADD CONSTRAINT \`FK_3435079c319679ba3aaccd806b1\` FOREIGN KEY (\`feedbacks_id\`) REFERENCES \`feedbacks\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`); - await queryRunner.query(`ALTER TABLE \`feedbacks_issues_issues\` ADD CONSTRAINT \`FK_6d6f24cf306a31c0af7b50973ab\` FOREIGN KEY (\`issues_id\`) REFERENCES \`issues\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE \`feedbacks_issues_issues\` DROP FOREIGN KEY \`FK_6d6f24cf306a31c0af7b50973ab\``); - await queryRunner.query(`ALTER TABLE \`feedbacks_issues_issues\` DROP FOREIGN KEY \`FK_3435079c319679ba3aaccd806b1\``); - await queryRunner.query(`ALTER TABLE \`issue_trackers\` DROP FOREIGN KEY \`FK_0d000918b0c670b7d2488257dd7\``); - await queryRunner.query(`ALTER TABLE \`api_keys\` DROP FOREIGN KEY \`FK_f5de07dbb229225e2be643ff3d0\``); - await queryRunner.query(`ALTER TABLE \`members\` DROP FOREIGN KEY \`FK_da404b5fd9c390e25338996e2d1\``); - await queryRunner.query(`ALTER TABLE \`members\` DROP FOREIGN KEY \`FK_274c5ebb3c595f5a56f1f8fba9a\``); - await queryRunner.query(`ALTER TABLE \`roles\` DROP FOREIGN KEY \`FK_cb48212dfe65dfe431d486034d2\``); - await queryRunner.query(`ALTER TABLE \`projects\` DROP FOREIGN KEY \`FK_7393a03ef67e2ea91b81faa95dd\``); - await queryRunner.query(`ALTER TABLE \`channels\` DROP FOREIGN KEY \`FK_63c4e21cafd9504a7c139144d1c\``); - await queryRunner.query(`ALTER TABLE \`fields\` DROP FOREIGN KEY \`FK_da856f4b147eb542917c5968c43\``); - await queryRunner.query(`ALTER TABLE \`options\` DROP FOREIGN KEY \`FK_dc520ce6f54769336c4afa5e9b9\``); - await queryRunner.query(`ALTER TABLE \`feedbacks\` DROP FOREIGN KEY \`FK_4adbe5e6c46eba8a93a0265a078\``); - await queryRunner.query(`ALTER TABLE \`issues\` DROP FOREIGN KEY \`FK_11f35e8296e10c229e7b68c68d4\``); - await queryRunner.query(`DROP INDEX \`IDX_6d6f24cf306a31c0af7b50973a\` ON \`feedbacks_issues_issues\``); - await queryRunner.query(`DROP INDEX \`IDX_3435079c319679ba3aaccd806b\` ON \`feedbacks_issues_issues\``); - await queryRunner.query(`DROP TABLE \`feedbacks_issues_issues\``); - await queryRunner.query(`DROP INDEX \`REL_0d000918b0c670b7d2488257dd\` ON \`issue_trackers\``); - await queryRunner.query(`DROP TABLE \`issue_trackers\``); - await queryRunner.query(`DROP INDEX \`IDX_2662a95fc4dd64493ca686a82f\` ON \`api_keys\``); - await queryRunner.query(`DROP TABLE \`api_keys\``); - await queryRunner.query(`DROP TABLE \`codes\``); - await queryRunner.query(`DROP TABLE \`histories\``); - await queryRunner.query(`DROP INDEX \`IDX_1301b11757c5b489adc8bc05e4\` ON \`users\``); - await queryRunner.query(`DROP TABLE \`users\``); - await queryRunner.query(`DROP INDEX \`IDX_858f5ec01bcfe14ab3f2a328dc\` ON \`members\``); - await queryRunner.query(`DROP TABLE \`members\``); - await queryRunner.query(`DROP INDEX \`IDX_f4f2789197a3cbbc0182396b26\` ON \`roles\``); - await queryRunner.query(`DROP TABLE \`roles\``); - await queryRunner.query(`DROP INDEX \`IDX_2187088ab5ef2a918473cb9900\` ON \`projects\``); - await queryRunner.query(`DROP TABLE \`projects\``); - await queryRunner.query(`DROP INDEX \`project-name-unique\` ON \`channels\``); - await queryRunner.query(`DROP INDEX \`IDX_1233531abfb8d56d2a15050143\` ON \`channels\``); - await queryRunner.query(`DROP TABLE \`channels\``); - await queryRunner.query(`DROP INDEX \`field-key-unique\` ON \`fields\``); - await queryRunner.query(`DROP INDEX \`field-name-unique\` ON \`fields\``); - await queryRunner.query(`DROP INDEX \`IDX_4b2181db660323e7ae856adeae\` ON \`fields\``); - await queryRunner.query(`DROP TABLE \`fields\``); - await queryRunner.query(`DROP TABLE \`options\``); - await queryRunner.query(`DROP INDEX \`IDX_a640975f8ccf17d9337d4ff828\` ON \`feedbacks\``); - await queryRunner.query(`DROP TABLE \`feedbacks\``); - await queryRunner.query(`DROP INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` ON \`issues\``); - await queryRunner.query(`DROP INDEX \`IDX_8e64309f790aa4270b955a9947\` ON \`issues\``); - await queryRunner.query(`DROP INDEX \`IDX_db94fcc9ef9f968b43ec5d2b2a\` ON \`issues\``); - await queryRunner.query(`DROP INDEX \`IDX_b7fd6df20da19c630741ea9045\` ON \`issues\``); - await queryRunner.query(`DROP TABLE \`issues\``); - await queryRunner.query(`DROP TABLE \`tenant\``); - } + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE \`tenant\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`site_name\` varchar(50) NOT NULL, \`description\` varchar(255) NULL, \`use_email\` tinyint NOT NULL DEFAULT 1, \`is_private\` tinyint NOT NULL DEFAULT 0, \`is_restrict_domain\` tinyint NOT NULL DEFAULT 0, \`allow_domains\` text NULL, \`use_o_auth\` tinyint NOT NULL DEFAULT 0, \`oauth_config\` json NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`issues\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`status\` enum ('INIT', 'ON_REVIEW', 'IN_PROGRESS', 'RESOLVED', 'PENDING') NOT NULL DEFAULT 'INIT', \`external_issue_id\` varchar(255) NULL, \`feedback_count\` int NOT NULL DEFAULT '0', \`project_id\` int NULL, INDEX \`IDX_b7fd6df20da19c630741ea9045\` (\`status\`), INDEX \`IDX_db94fcc9ef9f968b43ec5d2b2a\` (\`feedback_count\`), INDEX \`IDX_8e64309f790aa4270b955a9947\` (\`project_id\`, \`created_at\`), UNIQUE INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`feedbacks\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`raw_data\` json NOT NULL, \`additional_data\` json NULL, \`channel_id\` int NULL, INDEX \`IDX_a640975f8ccf17d9337d4ff828\` (\`created_at\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`options\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`key\` varchar(255) NOT NULL, \`field_id\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`fields\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`key\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`format\` enum ('text', 'keyword', 'number', 'boolean', 'select', 'multiSelect', 'date') NOT NULL, \`type\` enum ('DEFAULT', 'ADMIN', 'API') NOT NULL, \`status\` enum ('ACTIVE', 'INACTIVE') NOT NULL, \`channel_id\` int NULL, INDEX \`IDX_4b2181db660323e7ae856adeae\` (\`created_at\`), UNIQUE INDEX \`field-name-unique\` (\`name\`, \`channel_id\`), UNIQUE INDEX \`field-key-unique\` (\`key\`, \`channel_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`channels\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`project_id\` int NULL, INDEX \`IDX_1233531abfb8d56d2a15050143\` (\`name\`, \`created_at\`), UNIQUE INDEX \`project-name-unique\` (\`name\`, \`project_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`projects\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`description\` varchar(255) NULL, \`tenant_id\` int NULL, UNIQUE INDEX \`IDX_2187088ab5ef2a918473cb9900\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`roles\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`name\` varchar(255) NOT NULL, \`permissions\` text NOT NULL, \`project_id\` int NULL, INDEX \`IDX_f4f2789197a3cbbc0182396b26\` (\`name\`, \`project_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`members\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`role_id\` int NULL, \`user_id\` int NULL, UNIQUE INDEX \`IDX_858f5ec01bcfe14ab3f2a328dc\` (\`role_id\`, \`user_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`users\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`email\` varchar(320) NULL, \`name\` varchar(255) NULL, \`department\` varchar(255) NULL, \`state\` enum ('Active', 'Blocked') NOT NULL DEFAULT 'Active', \`hash_password\` varchar(255) NULL, \`type\` enum ('SUPER', 'GENERAL') NOT NULL DEFAULT 'GENERAL', \`sign_up_method\` enum ('EMAIL', 'OAUTH') NOT NULL DEFAULT 'EMAIL', UNIQUE INDEX \`IDX_1301b11757c5b489adc8bc05e4\` (\`email\`, \`sign_up_method\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`histories\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`entity_name\` enum ('ApiKey', 'Channel', 'Feedback', 'Field', 'IssueTracker', 'Issue', 'Member', 'Option', 'Project', 'Role', 'Tenant', 'User', 'FeedbackIssue', 'Code') NOT NULL, \`entity_id\` decimal NOT NULL, \`action\` enum ('Create', 'Update', 'Delete', 'SoftDelete', 'Download', 'Recover') NOT NULL, \`entity\` json NOT NULL, \`user_id\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`codes\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`type\` enum ('EMAIL_VEIRIFICATION', 'RESET_PASSWORD', 'USER_INVITATION') NOT NULL, \`key\` varchar(255) NOT NULL, \`code\` varchar(255) NOT NULL, \`data\` varchar(255) NULL, \`is_verified\` tinyint NOT NULL DEFAULT 0, \`expired_at\` datetime NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`api_keys\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`value\` varchar(255) NOT NULL, \`project_id\` int NULL, UNIQUE INDEX \`IDX_2662a95fc4dd64493ca686a82f\` (\`value\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`issue_trackers\` (\`id\` int NOT NULL AUTO_INCREMENT, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deleted_at\` datetime(6) NULL, \`data\` json NULL, \`project_id\` int NULL, UNIQUE INDEX \`REL_0d000918b0c670b7d2488257dd\` (\`project_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`feedbacks_issues_issues\` (\`feedbacks_id\` int NOT NULL, \`issues_id\` int NOT NULL, INDEX \`IDX_3435079c319679ba3aaccd806b\` (\`feedbacks_id\`), INDEX \`IDX_6d6f24cf306a31c0af7b50973a\` (\`issues_id\`), PRIMARY KEY (\`feedbacks_id\`, \`issues_id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `ALTER TABLE \`issues\` ADD CONSTRAINT \`FK_11f35e8296e10c229e7b68c68d4\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`feedbacks\` ADD CONSTRAINT \`FK_4adbe5e6c46eba8a93a0265a078\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`options\` ADD CONSTRAINT \`FK_dc520ce6f54769336c4afa5e9b9\` FOREIGN KEY (\`field_id\`) REFERENCES \`fields\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`fields\` ADD CONSTRAINT \`FK_da856f4b147eb542917c5968c43\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`channels\` ADD CONSTRAINT \`FK_63c4e21cafd9504a7c139144d1c\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`projects\` ADD CONSTRAINT \`FK_7393a03ef67e2ea91b81faa95dd\` FOREIGN KEY (\`tenant_id\`) REFERENCES \`tenant\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`roles\` ADD CONSTRAINT \`FK_cb48212dfe65dfe431d486034d2\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`members\` ADD CONSTRAINT \`FK_274c5ebb3c595f5a56f1f8fba9a\` FOREIGN KEY (\`role_id\`) REFERENCES \`roles\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`members\` ADD CONSTRAINT \`FK_da404b5fd9c390e25338996e2d1\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`api_keys\` ADD CONSTRAINT \`FK_f5de07dbb229225e2be643ff3d0\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`issue_trackers\` ADD CONSTRAINT \`FK_0d000918b0c670b7d2488257dd7\` FOREIGN KEY (\`project_id\`) REFERENCES \`projects\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE \`feedbacks_issues_issues\` ADD CONSTRAINT \`FK_3435079c319679ba3aaccd806b1\` FOREIGN KEY (\`feedbacks_id\`) REFERENCES \`feedbacks\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, + ); + await queryRunner.query( + `ALTER TABLE \`feedbacks_issues_issues\` ADD CONSTRAINT \`FK_6d6f24cf306a31c0af7b50973ab\` FOREIGN KEY (\`issues_id\`) REFERENCES \`issues\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE \`feedbacks_issues_issues\` DROP FOREIGN KEY \`FK_6d6f24cf306a31c0af7b50973ab\``, + ); + await queryRunner.query( + `ALTER TABLE \`feedbacks_issues_issues\` DROP FOREIGN KEY \`FK_3435079c319679ba3aaccd806b1\``, + ); + await queryRunner.query( + `ALTER TABLE \`issue_trackers\` DROP FOREIGN KEY \`FK_0d000918b0c670b7d2488257dd7\``, + ); + await queryRunner.query( + `ALTER TABLE \`api_keys\` DROP FOREIGN KEY \`FK_f5de07dbb229225e2be643ff3d0\``, + ); + await queryRunner.query( + `ALTER TABLE \`members\` DROP FOREIGN KEY \`FK_da404b5fd9c390e25338996e2d1\``, + ); + await queryRunner.query( + `ALTER TABLE \`members\` DROP FOREIGN KEY \`FK_274c5ebb3c595f5a56f1f8fba9a\``, + ); + await queryRunner.query( + `ALTER TABLE \`roles\` DROP FOREIGN KEY \`FK_cb48212dfe65dfe431d486034d2\``, + ); + await queryRunner.query( + `ALTER TABLE \`projects\` DROP FOREIGN KEY \`FK_7393a03ef67e2ea91b81faa95dd\``, + ); + await queryRunner.query( + `ALTER TABLE \`channels\` DROP FOREIGN KEY \`FK_63c4e21cafd9504a7c139144d1c\``, + ); + await queryRunner.query( + `ALTER TABLE \`fields\` DROP FOREIGN KEY \`FK_da856f4b147eb542917c5968c43\``, + ); + await queryRunner.query( + `ALTER TABLE \`options\` DROP FOREIGN KEY \`FK_dc520ce6f54769336c4afa5e9b9\``, + ); + await queryRunner.query( + `ALTER TABLE \`feedbacks\` DROP FOREIGN KEY \`FK_4adbe5e6c46eba8a93a0265a078\``, + ); + await queryRunner.query( + `ALTER TABLE \`issues\` DROP FOREIGN KEY \`FK_11f35e8296e10c229e7b68c68d4\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_6d6f24cf306a31c0af7b50973a\` ON \`feedbacks_issues_issues\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_3435079c319679ba3aaccd806b\` ON \`feedbacks_issues_issues\``, + ); + await queryRunner.query(`DROP TABLE \`feedbacks_issues_issues\``); + await queryRunner.query( + `DROP INDEX \`REL_0d000918b0c670b7d2488257dd\` ON \`issue_trackers\``, + ); + await queryRunner.query(`DROP TABLE \`issue_trackers\``); + await queryRunner.query( + `DROP INDEX \`IDX_2662a95fc4dd64493ca686a82f\` ON \`api_keys\``, + ); + await queryRunner.query(`DROP TABLE \`api_keys\``); + await queryRunner.query(`DROP TABLE \`codes\``); + await queryRunner.query(`DROP TABLE \`histories\``); + await queryRunner.query( + `DROP INDEX \`IDX_1301b11757c5b489adc8bc05e4\` ON \`users\``, + ); + await queryRunner.query(`DROP TABLE \`users\``); + await queryRunner.query( + `DROP INDEX \`IDX_858f5ec01bcfe14ab3f2a328dc\` ON \`members\``, + ); + await queryRunner.query(`DROP TABLE \`members\``); + await queryRunner.query( + `DROP INDEX \`IDX_f4f2789197a3cbbc0182396b26\` ON \`roles\``, + ); + await queryRunner.query(`DROP TABLE \`roles\``); + await queryRunner.query( + `DROP INDEX \`IDX_2187088ab5ef2a918473cb9900\` ON \`projects\``, + ); + await queryRunner.query(`DROP TABLE \`projects\``); + await queryRunner.query( + `DROP INDEX \`project-name-unique\` ON \`channels\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_1233531abfb8d56d2a15050143\` ON \`channels\``, + ); + await queryRunner.query(`DROP TABLE \`channels\``); + await queryRunner.query(`DROP INDEX \`field-key-unique\` ON \`fields\``); + await queryRunner.query(`DROP INDEX \`field-name-unique\` ON \`fields\``); + await queryRunner.query( + `DROP INDEX \`IDX_4b2181db660323e7ae856adeae\` ON \`fields\``, + ); + await queryRunner.query(`DROP TABLE \`fields\``); + await queryRunner.query(`DROP TABLE \`options\``); + await queryRunner.query( + `DROP INDEX \`IDX_a640975f8ccf17d9337d4ff828\` ON \`feedbacks\``, + ); + await queryRunner.query(`DROP TABLE \`feedbacks\``); + await queryRunner.query( + `DROP INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` ON \`issues\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_8e64309f790aa4270b955a9947\` ON \`issues\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_db94fcc9ef9f968b43ec5d2b2a\` ON \`issues\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_b7fd6df20da19c630741ea9045\` ON \`issues\``, + ); + await queryRunner.query(`DROP TABLE \`issues\``); + await queryRunner.query(`DROP TABLE \`tenant\``); + } } diff --git a/apps/api/src/configs/modules/typeorm-config/migrations/1692690482919-issue-name-unique.ts b/apps/api/src/configs/modules/typeorm-config/migrations/1692690482919-issue-name-unique.ts index 0c835d877..5cad8c4b4 100644 --- a/apps/api/src/configs/modules/typeorm-config/migrations/1692690482919-issue-name-unique.ts +++ b/apps/api/src/configs/modules/typeorm-config/migrations/1692690482919-issue-name-unique.ts @@ -1,16 +1,21 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; +import { MigrationInterface, QueryRunner } from 'typeorm'; export class IssueNameUnique1692690482919 implements MigrationInterface { - name = 'IssueNameUnique1692690482919' + name = 'IssueNameUnique1692690482919'; - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` ON \`issues\``); - await queryRunner.query(`CREATE UNIQUE INDEX \`issue-name-unique\` ON \`issues\` (\`name\`, \`project_id\`)`); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX \`issue-name-unique\` ON \`issues\``); - await queryRunner.query(`CREATE UNIQUE INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` ON \`issues\` (\`name\`)`); - } + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DROP INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` ON \`issues\``, + ); + await queryRunner.query( + `CREATE UNIQUE INDEX \`issue-name-unique\` ON \`issues\` (\`name\`, \`project_id\`)`, + ); + } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX \`issue-name-unique\` ON \`issues\``); + await queryRunner.query( + `CREATE UNIQUE INDEX \`IDX_b711d3eb6f21e35f5a0623dbe2\` ON \`issues\` (\`name\`)`, + ); + } } diff --git a/apps/api/src/configs/modules/typeorm-config/typeorm-config.datasource.ts b/apps/api/src/configs/modules/typeorm-config/typeorm-config.datasource.ts index e028bdb53..3bf98a7ad 100644 --- a/apps/api/src/configs/modules/typeorm-config/typeorm-config.datasource.ts +++ b/apps/api/src/configs/modules/typeorm-config/typeorm-config.datasource.ts @@ -15,10 +15,10 @@ */ import { ConfigService } from '@nestjs/config'; import * as dotenv from 'dotenv'; -import { DataSource, DataSourceOptions } from 'typeorm'; - -import { mySqlConfigSchema, mysqlConfig } from '@/configs/mysql.config'; +import type { DataSourceOptions } from 'typeorm'; +import { DataSource } from 'typeorm'; +import { mysqlConfig, mySqlConfigSchema } from '@/configs/mysql.config'; import { TypeOrmConfigService } from './typeorm-config.service'; dotenv.config(); diff --git a/apps/api/src/configs/modules/typeorm-config/typeorm-config.service.ts b/apps/api/src/configs/modules/typeorm-config/typeorm-config.service.ts index 8444146a7..9a6fce4e4 100644 --- a/apps/api/src/configs/modules/typeorm-config/typeorm-config.service.ts +++ b/apps/api/src/configs/modules/typeorm-config/typeorm-config.service.ts @@ -13,14 +13,17 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { join } from 'path'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm'; +import type { + TypeOrmModuleOptions, + TypeOrmOptionsFactory, +} from '@nestjs/typeorm'; import * as dotenv from 'dotenv'; -import { join } from 'path'; import { SnakeNamingStrategy } from 'typeorm-naming-strategies'; -import { ConfigServiceType } from '@/types/config-service.type'; +import type { ConfigServiceType } from '@/types/config-service.type'; dotenv.config(); @Injectable() diff --git a/apps/api/src/domains/auth/auth.controller.spec.ts b/apps/api/src/domains/auth/auth.controller.spec.ts index 99305ea2b..e07e0da8e 100644 --- a/apps/api/src/domains/auth/auth.controller.spec.ts +++ b/apps/api/src/domains/auth/auth.controller.spec.ts @@ -18,7 +18,6 @@ import { Test } from '@nestjs/testing'; import dayjs from 'dayjs'; import { getMockProvider } from '@/utils/test-utils'; - import { TenantService } from '../tenant/tenant.service'; import { UserDto } from '../user/dtos'; import { AuthController } from './auth.controller'; diff --git a/apps/api/src/domains/auth/auth.controller.ts b/apps/api/src/domains/auth/auth.controller.ts index 27ddedb12..fb41d5495 100644 --- a/apps/api/src/domains/auth/auth.controller.ts +++ b/apps/api/src/domains/auth/auth.controller.ts @@ -43,8 +43,11 @@ import { InvitationUserSignUpRequestDto, OAuthUserSignUpRequestDto, } from './dtos/requests'; -import { OAuthLoginUrlResponseDto, SignInResponseDto } from './dtos/responses'; -import { SendEmailCodeResponseDto } from './dtos/responses'; +import { + OAuthLoginUrlResponseDto, + SendEmailCodeResponseDto, + SignInResponseDto, +} from './dtos/responses'; import { JwtAuthGuard } from './guards'; import { UseEmailGuard } from './guards/use-email.guard'; import { UseOAuthGuard } from './guards/use-oauth.guard'; diff --git a/apps/api/src/domains/auth/auth.module.ts b/apps/api/src/domains/auth/auth.module.ts index ee9e6ef0d..bbbfe7315 100644 --- a/apps/api/src/domains/auth/auth.module.ts +++ b/apps/api/src/domains/auth/auth.module.ts @@ -20,8 +20,7 @@ import { PassportModule } from '@nestjs/passport'; import { CodeModule } from '@/shared/code/code.module'; import { MailingModule } from '@/shared/mailing/mailing.module'; -import { ConfigServiceType } from '@/types/config-service.type'; - +import type { ConfigServiceType } from '@/types/config-service.type'; import { ApiKeyModule } from '../project/api-key/api-key.module'; import { MemberModule } from '../project/member/member.module'; import { RoleModule } from '../project/role/role.module'; diff --git a/apps/api/src/domains/auth/auth.service.spec.ts b/apps/api/src/domains/auth/auth.service.spec.ts index 127d88667..594e24956 100644 --- a/apps/api/src/domains/auth/auth.service.spec.ts +++ b/apps/api/src/domains/auth/auth.service.spec.ts @@ -20,14 +20,13 @@ import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import * as bcrypt from 'bcrypt'; import { ClsService } from 'nestjs-cls'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { CodeEntity } from '@/shared/code/code.entity'; import { CodeServiceProviders } from '@/shared/code/code.service.spec'; import { EmailVerificationMailingService } from '@/shared/mailing/email-verification-mailing.service'; import { NotVerifiedEmailException } from '@/shared/mailing/exceptions'; import { getMockProvider } from '@/utils/test-utils'; - import { ApiKeyEntity } from '../project/api-key/api-key.entity'; import { ApiKeyServiceProviders } from '../project/api-key/api-key.service.spec'; import { MemberServiceProviders } from '../project/member/member.service.spec'; @@ -143,7 +142,6 @@ describe('auth service ', () => { }); }); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('verifyEmailCode', () => {}); describe('validateEmailUser', () => { @@ -267,10 +265,8 @@ describe('auth service ', () => { }); }); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('signUpInvitationUser', () => {}); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('signUpOAuthUser', () => {}); describe('signIn', () => { @@ -302,7 +298,6 @@ describe('auth service ', () => { }); }); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('refreshToken', () => {}); describe('validateApiKey', () => { @@ -379,6 +374,5 @@ describe('auth service ', () => { }); }); - // eslint-disable-next-line @typescript-eslint/no-empty-function describe('signInByOAuth', () => {}); }); diff --git a/apps/api/src/domains/auth/auth.service.ts b/apps/api/src/domains/auth/auth.service.ts index c541a8b38..c42006104 100644 --- a/apps/api/src/domains/auth/auth.service.ts +++ b/apps/api/src/domains/auth/auth.service.ts @@ -13,6 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ +import crypto from 'crypto'; import { BadRequestException, Injectable, @@ -22,15 +23,13 @@ import { import { JwtService } from '@nestjs/jwt'; import axios from 'axios'; import * as bcrypt from 'bcrypt'; -import crypto from 'crypto'; import dayjs from 'dayjs'; import { ClsService } from 'nestjs-cls'; import { Transactional } from 'typeorm-transactional'; import { EmailVerificationMailingService } from '@/shared/mailing/email-verification-mailing.service'; import { NotVerifiedEmailException } from '@/shared/mailing/exceptions'; -import { ClsServiceType } from '@/types/cls-service.type'; - +import type { ClsServiceType } from '@/types/cls-service.type'; import { CodeTypeEnum } from '../../shared/code/code-type.enum'; import { CodeService } from '../../shared/code/code.service'; import { ApiKeyService } from '../project/api-key/api-key.service'; @@ -45,14 +44,16 @@ import { UserNotFoundException, } from '../user/exceptions'; import { UserService } from '../user/user.service'; -import { +import type { JwtDto, SendEmailCodeDto, + ValidateEmailUserDto, + VerifyEmailCodeDto, +} from './dtos'; +import { SignUpEmailUserDto, SignUpInvitationUserDto, SignUpOauthUserDto, - ValidateEmailUserDto, - VerifyEmailCodeDto, } from './dtos'; import { PasswordNotMatchException, UserBlockedException } from './exceptions'; diff --git a/apps/api/src/domains/auth/guards/api-key.guard.ts b/apps/api/src/domains/auth/guards/api-key.guard.ts index 3bbb6fc72..ce191d65c 100644 --- a/apps/api/src/domains/auth/guards/api-key.guard.ts +++ b/apps/api/src/domains/auth/guards/api-key.guard.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import type { CanActivate, ExecutionContext } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { AuthService } from '../auth.service'; diff --git a/apps/api/src/domains/auth/guards/jwt-auth.guard.ts b/apps/api/src/domains/auth/guards/jwt-auth.guard.ts index 24e40aed7..d9f351788 100644 --- a/apps/api/src/domains/auth/guards/jwt-auth.guard.ts +++ b/apps/api/src/domains/auth/guards/jwt-auth.guard.ts @@ -13,16 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { - ExecutionContext, - Injectable, - UnauthorizedException, -} from '@nestjs/common'; +import type { ExecutionContext } from '@nestjs/common'; +import { Injectable, UnauthorizedException } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ClsService } from 'nestjs-cls'; -import { Observable } from 'rxjs'; +import type { Observable } from 'rxjs'; -import { ClsServiceType } from '@/types/cls-service.type'; +import type { ClsServiceType } from '@/types/cls-service.type'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { diff --git a/apps/api/src/domains/auth/guards/use-email.guard.ts b/apps/api/src/domains/auth/guards/use-email.guard.ts index 24ee66269..2e7b72e95 100644 --- a/apps/api/src/domains/auth/guards/use-email.guard.ts +++ b/apps/api/src/domains/auth/guards/use-email.guard.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { CanActivate, Injectable } from '@nestjs/common'; +import type { CanActivate } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { TenantService } from '@/domains/tenant/tenant.service'; diff --git a/apps/api/src/domains/auth/guards/use-oauth.guard.ts b/apps/api/src/domains/auth/guards/use-oauth.guard.ts index 1bc3d9121..dbafadfdc 100644 --- a/apps/api/src/domains/auth/guards/use-oauth.guard.ts +++ b/apps/api/src/domains/auth/guards/use-oauth.guard.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { CanActivate, Injectable } from '@nestjs/common'; +import type { CanActivate } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { TenantService } from '@/domains/tenant/tenant.service'; diff --git a/apps/api/src/domains/auth/strategies/jwt.strategy.ts b/apps/api/src/domains/auth/strategies/jwt.strategy.ts index 0a66691c2..f92ba8396 100644 --- a/apps/api/src/domains/auth/strategies/jwt.strategy.ts +++ b/apps/api/src/domains/auth/strategies/jwt.strategy.ts @@ -18,8 +18,8 @@ import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; -import { UserTypeEnum } from '@/domains/user/entities/enums'; -import { ConfigServiceType } from '@/types/config-service.type'; +import type { UserTypeEnum } from '@/domains/user/entities/enums'; +import type { ConfigServiceType } from '@/types/config-service.type'; interface IPayload { sub: string; diff --git a/apps/api/src/domains/auth/strategies/local.strategy.ts b/apps/api/src/domains/auth/strategies/local.strategy.ts index 20fd1b5c1..38505ea32 100644 --- a/apps/api/src/domains/auth/strategies/local.strategy.ts +++ b/apps/api/src/domains/auth/strategies/local.strategy.ts @@ -18,7 +18,6 @@ import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-local'; import { UserDto } from '@/domains/user/dtos'; - import { AuthService } from '../auth.service'; @Injectable() diff --git a/apps/api/src/domains/channel/channel/channel.controller.spec.ts b/apps/api/src/domains/channel/channel/channel.controller.spec.ts index 65c4c018e..7114469a7 100644 --- a/apps/api/src/domains/channel/channel/channel.controller.spec.ts +++ b/apps/api/src/domains/channel/channel/channel.controller.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { DataSource } from 'typeorm'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { ChannelController } from './channel.controller'; import { ChannelService } from './channel.service'; import { diff --git a/apps/api/src/domains/channel/channel/channel.controller.ts b/apps/api/src/domains/channel/channel/channel.controller.ts index 7ddb73c55..3dce7ca6e 100644 --- a/apps/api/src/domains/channel/channel/channel.controller.ts +++ b/apps/api/src/domains/channel/channel/channel.controller.ts @@ -33,7 +33,6 @@ import { import { PermissionEnum } from '@/domains/project/role/permission.enum'; import { RequirePermission } from '@/domains/project/role/require-permission.decorator'; - import { ChannelService } from './channel.service'; import { CreateChannelDto } from './dtos'; import { diff --git a/apps/api/src/domains/channel/channel/channel.entity.ts b/apps/api/src/domains/channel/channel/channel.entity.ts index a283fa3f5..7210927fc 100644 --- a/apps/api/src/domains/channel/channel/channel.entity.ts +++ b/apps/api/src/domains/channel/channel/channel.entity.ts @@ -24,7 +24,6 @@ import { } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { FeedbackEntity } from '../../feedback/feedback.entity'; import { ProjectEntity } from '../../project/project/project.entity'; import { FieldEntity } from '../field/field.entity'; diff --git a/apps/api/src/domains/channel/channel/channel.module.ts b/apps/api/src/domains/channel/channel/channel.module.ts index dca4143af..210d1dc04 100644 --- a/apps/api/src/domains/channel/channel/channel.module.ts +++ b/apps/api/src/domains/channel/channel/channel.module.ts @@ -13,14 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Module, forwardRef } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpensearchRepository } from '@/common/repositories'; import { FeedbackModule } from '@/domains/feedback/feedback.module'; import { ProjectEntity } from '@/domains/project/project/project.entity'; import { ProjectModule } from '@/domains/project/project/project.module'; - import { FieldModule } from '../field/field.module'; import { ChannelController } from './channel.controller'; import { ChannelEntity } from './channel.entity'; diff --git a/apps/api/src/domains/channel/channel/channel.mysql.service.ts b/apps/api/src/domains/channel/channel/channel.mysql.service.ts index 8a3379836..8bdf15558 100644 --- a/apps/api/src/domains/channel/channel/channel.mysql.service.ts +++ b/apps/api/src/domains/channel/channel/channel.mysql.service.ts @@ -20,14 +20,9 @@ import { Like, Not, Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; import { isSelectFieldFormat } from '@/common/enums'; - import { ChannelEntity } from './channel.entity'; -import { - CreateChannelDto, - FindAllChannelsByProjectIdDto, - FindByChannelIdDto, - UpdateChannelDto, -} from './dtos'; +import type { FindAllChannelsByProjectIdDto, FindByChannelIdDto } from './dtos'; +import { CreateChannelDto, UpdateChannelDto } from './dtos'; import { ChannelAlreadyExistsException, ChannelInvalidNameException, diff --git a/apps/api/src/domains/channel/channel/channel.service.spec.ts b/apps/api/src/domains/channel/channel/channel.service.spec.ts index bc9124aa8..b5b7bc542 100644 --- a/apps/api/src/domains/channel/channel/channel.service.spec.ts +++ b/apps/api/src/domains/channel/channel/channel.service.spec.ts @@ -16,17 +16,16 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { OpensearchRepository } from '@/common/repositories'; import { ProjectServiceProviders } from '@/domains/project/project/project.service.spec'; import { createFieldDto } from '@/utils/test-util-fixture'; import { - MockOpensearchRepository, getMockProvider, + MockOpensearchRepository, mockRepository, } from '@/utils/test-utils'; - import { ChannelEntity } from '../../channel/channel/channel.entity'; import { ProjectEntity } from '../../project/project/project.entity'; import { FieldEntity } from '../field/field.entity'; diff --git a/apps/api/src/domains/channel/channel/channel.service.ts b/apps/api/src/domains/channel/channel/channel.service.ts index 0ac25d7f2..ef1980fdd 100644 --- a/apps/api/src/domains/channel/channel/channel.service.ts +++ b/apps/api/src/domains/channel/channel/channel.service.ts @@ -19,13 +19,11 @@ import { Transactional } from 'typeorm-transactional'; import { OpensearchRepository } from '@/common/repositories'; import { OS_USE } from '@/configs/opensearch.config'; import { ProjectService } from '@/domains/project/project/project.service'; - import { FieldService } from '../field/field.service'; import { ChannelMySQLService } from './channel.mysql.service'; +import type { FindAllChannelsByProjectIdDto, FindByChannelIdDto } from './dtos'; import { CreateChannelDto, - FindAllChannelsByProjectIdDto, - FindByChannelIdDto, UpdateChannelDto, UpdateChannelFieldsDto, } from './dtos'; diff --git a/apps/api/src/domains/channel/channel/create-channel.dto.ts b/apps/api/src/domains/channel/channel/create-channel.dto.ts index cf9abe31a..fcaab3a0c 100644 --- a/apps/api/src/domains/channel/channel/create-channel.dto.ts +++ b/apps/api/src/domains/channel/channel/create-channel.dto.ts @@ -13,10 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { ChannelEntity } from '@/domains/channel/channel/channel.entity'; - import { CreateFieldDto } from '../field/dtos'; export class CreateChannelDto { diff --git a/apps/api/src/domains/channel/channel/dtos/create-channel.dto.ts b/apps/api/src/domains/channel/channel/dtos/create-channel.dto.ts index 2eb508d17..1677bcefd 100644 --- a/apps/api/src/domains/channel/channel/dtos/create-channel.dto.ts +++ b/apps/api/src/domains/channel/channel/dtos/create-channel.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { CreateFieldDto } from '../../field/dtos/create-field.dto'; import { ChannelEntity } from '../channel.entity'; diff --git a/apps/api/src/domains/channel/channel/dtos/find-all-channels-by-project-id.dto.ts b/apps/api/src/domains/channel/channel/dtos/find-all-channels-by-project-id.dto.ts index d3939f22f..eeaa3d9fa 100644 --- a/apps/api/src/domains/channel/channel/dtos/find-all-channels-by-project-id.dto.ts +++ b/apps/api/src/domains/channel/channel/dtos/find-all-channels-by-project-id.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { IPaginationOptions } from 'nestjs-typeorm-paginate'; +import type { IPaginationOptions } from 'nestjs-typeorm-paginate'; export class FindAllChannelsByProjectIdDto { options: IPaginationOptions; diff --git a/apps/api/src/domains/channel/channel/dtos/responses/find-channel-by-id-response.dto.ts b/apps/api/src/domains/channel/channel/dtos/responses/find-channel-by-id-response.dto.ts index 7966d1cb5..12f48ecff 100644 --- a/apps/api/src/domains/channel/channel/dtos/responses/find-channel-by-id-response.dto.ts +++ b/apps/api/src/domains/channel/channel/dtos/responses/find-channel-by-id-response.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { FindFieldsResponseDto } from '@/domains/channel/field/dtos/responses'; diff --git a/apps/api/src/domains/channel/channel/dtos/responses/find-channels-by-id-response.dto.ts b/apps/api/src/domains/channel/channel/dtos/responses/find-channels-by-id-response.dto.ts index af2fce41a..e55f36dbb 100644 --- a/apps/api/src/domains/channel/channel/dtos/responses/find-channels-by-id-response.dto.ts +++ b/apps/api/src/domains/channel/channel/dtos/responses/find-channels-by-id-response.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PaginationResponseDto } from '@/common/dtos'; diff --git a/apps/api/src/domains/channel/field/dtos/create-many-fields.dto.ts b/apps/api/src/domains/channel/field/dtos/create-many-fields.dto.ts index 76d42938d..78f11954d 100644 --- a/apps/api/src/domains/channel/field/dtos/create-many-fields.dto.ts +++ b/apps/api/src/domains/channel/field/dtos/create-many-fields.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { CreateFieldDto } from './create-field.dto'; +import type { CreateFieldDto } from './create-field.dto'; export class CreateManyFieldsDto { channelId: number; diff --git a/apps/api/src/domains/channel/field/dtos/replace-many-fields.dto.ts b/apps/api/src/domains/channel/field/dtos/replace-many-fields.dto.ts index d7efe0d1a..a85527e67 100644 --- a/apps/api/src/domains/channel/field/dtos/replace-many-fields.dto.ts +++ b/apps/api/src/domains/channel/field/dtos/replace-many-fields.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { ReplaceFieldDto } from './replace-field.dto'; +import type { ReplaceFieldDto } from './replace-field.dto'; export class ReplaceManyFieldsDto { channelId: number; diff --git a/apps/api/src/domains/channel/field/dtos/responses/find-fields-response.dto.ts b/apps/api/src/domains/channel/field/dtos/responses/find-fields-response.dto.ts index 26701881c..3faf726eb 100644 --- a/apps/api/src/domains/channel/field/dtos/responses/find-fields-response.dto.ts +++ b/apps/api/src/domains/channel/field/dtos/responses/find-fields-response.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { FieldFormatEnum, diff --git a/apps/api/src/domains/channel/field/field.entity.ts b/apps/api/src/domains/channel/field/field.entity.ts index 3eb0b912e..c987df06f 100644 --- a/apps/api/src/domains/channel/field/field.entity.ts +++ b/apps/api/src/domains/channel/field/field.entity.ts @@ -24,7 +24,6 @@ import { } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { FieldFormatEnum, FieldStatusEnum, diff --git a/apps/api/src/domains/channel/field/field.module.ts b/apps/api/src/domains/channel/field/field.module.ts index 4d5ba95ed..7305fe38c 100644 --- a/apps/api/src/domains/channel/field/field.module.ts +++ b/apps/api/src/domains/channel/field/field.module.ts @@ -17,7 +17,6 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpensearchRepository } from '@/common/repositories'; - import { FieldEntity } from '../field/field.entity'; import { FieldMySQLService } from '../field/field.mysql.service'; import { FieldService } from '../field/field.service'; diff --git a/apps/api/src/domains/channel/field/field.mysql.service.ts b/apps/api/src/domains/channel/field/field.mysql.service.ts index 92a11ffce..89d830cae 100644 --- a/apps/api/src/domains/channel/field/field.mysql.service.ts +++ b/apps/api/src/domains/channel/field/field.mysql.service.ts @@ -25,15 +25,10 @@ import { isSelectFieldFormat, } from '@/common/enums'; import { validateUnique } from '@/utils/validate-unique'; - import { FieldEntity } from '../../channel/field/field.entity'; import { OptionService } from '../option/option.service'; -import { - CreateFieldDto, - CreateManyFieldsDto, - ReplaceFieldDto, - ReplaceManyFieldsDto, -} from './dtos'; +import type { CreateFieldDto, ReplaceFieldDto } from './dtos'; +import { CreateManyFieldsDto, ReplaceManyFieldsDto } from './dtos'; import { FieldKeyDuplicatedException, FieldNameDuplicatedException, diff --git a/apps/api/src/domains/channel/field/field.service.spec.ts b/apps/api/src/domains/channel/field/field.service.spec.ts index 7a6a86006..846830952 100644 --- a/apps/api/src/domains/channel/field/field.service.spec.ts +++ b/apps/api/src/domains/channel/field/field.service.spec.ts @@ -17,17 +17,16 @@ import { faker } from '@faker-js/faker'; import { BadRequestException } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { FieldFormatEnum, isSelectFieldFormat } from '@/common/enums'; import { OpensearchRepository } from '@/common/repositories'; import { createFieldDto, updateFieldDto } from '@/utils/test-util-fixture'; import { - MockOpensearchRepository, getMockProvider, + MockOpensearchRepository, mockRepository, } from '@/utils/test-utils'; - import { FieldEntity } from '../../channel/field/field.entity'; import { OptionEntity } from '../option/option.entity'; import { OptionServiceProviders } from '../option/option.service.spec'; diff --git a/apps/api/src/domains/channel/field/field.service.ts b/apps/api/src/domains/channel/field/field.service.ts index 645a59301..8af377798 100644 --- a/apps/api/src/domains/channel/field/field.service.ts +++ b/apps/api/src/domains/channel/field/field.service.ts @@ -19,8 +19,7 @@ import { Transactional } from 'typeorm-transactional'; import { FieldFormatEnum } from '@/common/enums'; import { OpensearchRepository } from '@/common/repositories'; import { OS_USE } from '@/configs/opensearch.config'; - -import { FieldEntity } from '../../channel/field/field.entity'; +import type { FieldEntity } from '../../channel/field/field.entity'; import { CreateManyFieldsDto, ReplaceManyFieldsDto } from './dtos'; import { FieldMySQLService } from './field.mysql.service'; diff --git a/apps/api/src/domains/channel/option/option.controller.spec.ts b/apps/api/src/domains/channel/option/option.controller.spec.ts index bac01f0e9..3b71edade 100644 --- a/apps/api/src/domains/channel/option/option.controller.spec.ts +++ b/apps/api/src/domains/channel/option/option.controller.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { DataSource } from 'typeorm'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { CreateOptionRequestDto } from './dtos/requests'; import { OptionController } from './option.controller'; import { OptionEntity } from './option.entity'; diff --git a/apps/api/src/domains/channel/option/option.controller.ts b/apps/api/src/domains/channel/option/option.controller.ts index fe71be921..b33984c0d 100644 --- a/apps/api/src/domains/channel/option/option.controller.ts +++ b/apps/api/src/domains/channel/option/option.controller.ts @@ -25,7 +25,6 @@ import { ApiCreatedResponse, ApiOkResponse } from '@nestjs/swagger'; import { PermissionEnum } from '@/domains/project/role/permission.enum'; import { RequirePermission } from '@/domains/project/role/require-permission.decorator'; - import { CreateOptionRequestDto } from './dtos/requests'; import { CreateOptionResponseDto, diff --git a/apps/api/src/domains/channel/option/option.entity.ts b/apps/api/src/domains/channel/option/option.entity.ts index fa7587e76..85f6977a4 100644 --- a/apps/api/src/domains/channel/option/option.entity.ts +++ b/apps/api/src/domains/channel/option/option.entity.ts @@ -16,7 +16,6 @@ import { Column, Entity, ManyToOne, Relation } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { FieldEntity } from '../field/field.entity'; @Entity('options') diff --git a/apps/api/src/domains/channel/option/option.service.spec.ts b/apps/api/src/domains/channel/option/option.service.spec.ts index 92c8606d4..357235afe 100644 --- a/apps/api/src/domains/channel/option/option.service.spec.ts +++ b/apps/api/src/domains/channel/option/option.service.spec.ts @@ -16,10 +16,9 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { mockRepository } from '@/utils/test-utils'; - import { OptionEntity } from '../../channel/option/option.entity'; import { CreateManyOptionsDto, diff --git a/apps/api/src/domains/channel/option/option.service.ts b/apps/api/src/domains/channel/option/option.service.ts index 46c4031d1..550334119 100644 --- a/apps/api/src/domains/channel/option/option.service.ts +++ b/apps/api/src/domains/channel/option/option.service.ts @@ -19,7 +19,6 @@ import { Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; import { validateUnique } from '@/utils/validate-unique'; - import { OptionEntity } from '../../channel/option/option.entity'; import { CreateManyOptionsDto, diff --git a/apps/api/src/domains/feedback/dtos/create-feedback.dto.ts b/apps/api/src/domains/feedback/dtos/create-feedback.dto.ts index b389a5add..38138b865 100644 --- a/apps/api/src/domains/feedback/dtos/create-feedback.dto.ts +++ b/apps/api/src/domains/feedback/dtos/create-feedback.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { FeedbackEntity } from '@/domains/feedback/feedback.entity'; +import type { FeedbackEntity } from '@/domains/feedback/feedback.entity'; export class CreateFeedbackDto { channelId: number; diff --git a/apps/api/src/domains/feedback/dtos/find-feedbacks-by-channel-id.dto.ts b/apps/api/src/domains/feedback/dtos/find-feedbacks-by-channel-id.dto.ts index 68c200473..b47f54cad 100644 --- a/apps/api/src/domains/feedback/dtos/find-feedbacks-by-channel-id.dto.ts +++ b/apps/api/src/domains/feedback/dtos/find-feedbacks-by-channel-id.dto.ts @@ -13,9 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { PaginationDto, TimeRange } from '@/common/dtos'; -import { SortMethodEnum } from '@/common/enums'; -import { FieldEntity } from '@/domains/channel/field/field.entity'; +import type { TimeRange } from '@/common/dtos'; +import { PaginationDto } from '@/common/dtos'; +import type { SortMethodEnum } from '@/common/enums'; +import type { FieldEntity } from '@/domains/channel/field/field.entity'; export class FindFeedbacksByChannelIdDto extends PaginationDto { channelId: number; diff --git a/apps/api/src/domains/feedback/dtos/generate-excel.dto.ts b/apps/api/src/domains/feedback/dtos/generate-excel.dto.ts index 29945f06e..866bb7727 100644 --- a/apps/api/src/domains/feedback/dtos/generate-excel.dto.ts +++ b/apps/api/src/domains/feedback/dtos/generate-excel.dto.ts @@ -13,8 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { TimeRange } from '@/common/dtos'; -import { SortMethodEnum } from '@/common/enums'; +import type { TimeRange } from '@/common/dtos'; +import type { SortMethodEnum } from '@/common/enums'; export class GenerateExcelDto { channelId: number; diff --git a/apps/api/src/domains/feedback/dtos/os-query.dto.ts b/apps/api/src/domains/feedback/dtos/os-query.dto.ts index 35ef0cf04..b0da9798e 100644 --- a/apps/api/src/domains/feedback/dtos/os-query.dto.ts +++ b/apps/api/src/domains/feedback/dtos/os-query.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { TimeRange } from '@/common/dtos'; +import type { TimeRange } from '@/common/dtos'; export class OsQueryDto { bool: { diff --git a/apps/api/src/domains/feedback/dtos/requests/find-feedbacks-by-channel-id-request.dto.ts b/apps/api/src/domains/feedback/dtos/requests/find-feedbacks-by-channel-id-request.dto.ts index ebae8db28..0f0de2399 100644 --- a/apps/api/src/domains/feedback/dtos/requests/find-feedbacks-by-channel-id-request.dto.ts +++ b/apps/api/src/domains/feedback/dtos/requests/find-feedbacks-by-channel-id-request.dto.ts @@ -16,8 +16,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsOptional } from 'class-validator'; -import { PaginationRequestDto, TimeRange } from '@/common/dtos'; -import { SortMethodEnum } from '@/common/enums'; +import type { TimeRange } from '@/common/dtos'; +import { PaginationRequestDto } from '@/common/dtos'; +import type { SortMethodEnum } from '@/common/enums'; export class FindFeedbacksByChannelIdRequestDto extends PaginationRequestDto { @ApiProperty({ required: false }) diff --git a/apps/api/src/domains/feedback/dtos/responses/find-feedbacks-by-channel-id-response.dto.ts b/apps/api/src/domains/feedback/dtos/responses/find-feedbacks-by-channel-id-response.dto.ts index 3acac8610..a5ab88d73 100644 --- a/apps/api/src/domains/feedback/dtos/responses/find-feedbacks-by-channel-id-response.dto.ts +++ b/apps/api/src/domains/feedback/dtos/responses/find-feedbacks-by-channel-id-response.dto.ts @@ -14,10 +14,10 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PaginationResponseDto } from '@/common/dtos'; -import { IssueEntity } from '@/domains/project/issue/issue.entity'; +import type { IssueEntity } from '@/domains/project/issue/issue.entity'; export class Feedback { [key: string]: any; diff --git a/apps/api/src/domains/feedback/dtos/scroll-feedbacks.dto.ts b/apps/api/src/domains/feedback/dtos/scroll-feedbacks.dto.ts index 75971c0d5..16225f0d5 100644 --- a/apps/api/src/domains/feedback/dtos/scroll-feedbacks.dto.ts +++ b/apps/api/src/domains/feedback/dtos/scroll-feedbacks.dto.ts @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { TimeRange } from '@/common/dtos'; -import { SortMethodEnum } from '@/common/enums'; -import { FieldEntity } from '@/domains/channel/field/field.entity'; +import type { TimeRange } from '@/common/dtos'; +import type { SortMethodEnum } from '@/common/enums'; +import type { FieldEntity } from '@/domains/channel/field/field.entity'; export class ScrollFeedbacksDto { channelId: number; diff --git a/apps/api/src/domains/feedback/feedback.common.ts b/apps/api/src/domains/feedback/feedback.common.ts index 6c18133f2..c02d2c452 100644 --- a/apps/api/src/domains/feedback/feedback.common.ts +++ b/apps/api/src/domains/feedback/feedback.common.ts @@ -14,8 +14,7 @@ * under the License. */ import { FieldFormatEnum, SortMethodEnum } from '@/common/enums'; - -import { FieldEntity } from '../channel/field/field.entity'; +import type { FieldEntity } from '../channel/field/field.entity'; export function isInvalidSortMethod(method: SortMethodEnum) { return ![SortMethodEnum.ASC, SortMethodEnum.DESC].includes(method); diff --git a/apps/api/src/domains/feedback/feedback.controller.spec.ts b/apps/api/src/domains/feedback/feedback.controller.spec.ts index 8a91b9b4e..e3bab70ae 100644 --- a/apps/api/src/domains/feedback/feedback.controller.spec.ts +++ b/apps/api/src/domains/feedback/feedback.controller.spec.ts @@ -15,13 +15,12 @@ */ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; -import { FastifyReply } from 'fastify'; +import type { FastifyReply } from 'fastify'; import { DataSource } from 'typeorm'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { AuthService } from '../auth/auth.service'; -import { ChannelEntity } from '../channel/channel/channel.entity'; +import type { ChannelEntity } from '../channel/channel/channel.entity'; import { ChannelService } from '../channel/channel/channel.service'; import { HistoryService } from '../history/history.service'; import { UserDto } from '../user/dtos'; diff --git a/apps/api/src/domains/feedback/feedback.controller.ts b/apps/api/src/domains/feedback/feedback.controller.ts index fd37ef9c3..752efbb70 100644 --- a/apps/api/src/domains/feedback/feedback.controller.ts +++ b/apps/api/src/domains/feedback/feedback.controller.ts @@ -30,7 +30,6 @@ import dayjs from 'dayjs'; import { FastifyReply } from 'fastify'; import { ApiKeyAuthGuard } from '@/domains/auth/guards'; - import { ChannelService } from '../channel/channel/channel.service'; import { HistoryActionEnum } from '../history/history-action.enum'; import { EntityNameEnum } from '../history/history-entity.enum'; diff --git a/apps/api/src/domains/feedback/feedback.entity.ts b/apps/api/src/domains/feedback/feedback.entity.ts index 501b315dd..82c114fb6 100644 --- a/apps/api/src/domains/feedback/feedback.entity.ts +++ b/apps/api/src/domains/feedback/feedback.entity.ts @@ -24,7 +24,6 @@ import { } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { ChannelEntity } from '../channel/channel/channel.entity'; import { IssueEntity } from '../project/issue/issue.entity'; diff --git a/apps/api/src/domains/feedback/feedback.module.ts b/apps/api/src/domains/feedback/feedback.module.ts index 547eff2e3..f953b6bbe 100644 --- a/apps/api/src/domains/feedback/feedback.module.ts +++ b/apps/api/src/domains/feedback/feedback.module.ts @@ -13,11 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Module, forwardRef } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpensearchRepository } from '@/common/repositories'; - import { AuthModule } from '../auth/auth.module'; import { ChannelEntity } from '../channel/channel/channel.entity'; import { ChannelModule } from '../channel/channel/channel.module'; diff --git a/apps/api/src/domains/feedback/feedback.mysql.service.ts b/apps/api/src/domains/feedback/feedback.mysql.service.ts index 2b02902f8..1b1ca379f 100644 --- a/apps/api/src/domains/feedback/feedback.mysql.service.ts +++ b/apps/api/src/domains/feedback/feedback.mysql.service.ts @@ -17,28 +17,29 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import dayjs from 'dayjs'; import { ClsService } from 'nestjs-cls'; -import { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; +import type { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; import { Brackets, QueryFailedError, Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; -import { TimeRange } from '@/common/dtos'; +import type { TimeRange } from '@/common/dtos'; import { FieldFormatEnum, FieldTypeEnum, SortMethodEnum } from '@/common/enums'; -import { ClsServiceType } from '@/types/cls-service.type'; - +import type { ClsServiceType } from '@/types/cls-service.type'; import { ChannelEntity } from '../channel/channel/channel.entity'; -import { FieldEntity } from '../channel/field/field.entity'; +import type { FieldEntity } from '../channel/field/field.entity'; import { OptionEntity } from '../channel/option/option.entity'; import { IssueEntity } from '../project/issue/issue.entity'; -import { - AddIssueDto, +import type { CountByProjectIdDto, - CreateFeedbackMySQLDto, DeleteByIdsDto, FindFeedbacksByChannelIdDto, +} from './dtos'; +import { + AddIssueDto, + CreateFeedbackMySQLDto, RemoveIssueDto, UpdateFeedbackMySQLDto, } from './dtos'; -import { Feedback } from './dtos/responses/find-feedbacks-by-channel-id-response.dto'; +import type { Feedback } from './dtos/responses/find-feedbacks-by-channel-id-response.dto'; import { isInvalidSortMethod } from './feedback.common'; import { FeedbackEntity } from './feedback.entity'; diff --git a/apps/api/src/domains/feedback/feedback.os.service.ts b/apps/api/src/domains/feedback/feedback.os.service.ts index 33fdf0e8f..8823b0e97 100644 --- a/apps/api/src/domains/feedback/feedback.os.service.ts +++ b/apps/api/src/domains/feedback/feedback.os.service.ts @@ -16,23 +16,22 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import dayjs from 'dayjs'; -import { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; +import type { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; import { In, Repository } from 'typeorm'; -import { TimeRange } from '@/common/dtos'; +import type { TimeRange } from '@/common/dtos'; import { FieldFormatEnum, SortMethodEnum } from '@/common/enums'; import { OpensearchRepository } from '@/common/repositories'; - -import { FieldEntity } from '../channel/field/field.entity'; -import { +import type { FieldEntity } from '../channel/field/field.entity'; +import type { + CreateFeedbackOSDto, DeleteByIdsDto, FindFeedbacksByChannelIdDto, ScrollFeedbacksDto, UpdateFeedbackESDto, } from './dtos'; -import { CreateFeedbackOSDto } from './dtos'; -import { OsQueryDto } from './dtos/os-query.dto'; -import { Feedback } from './dtos/responses/find-feedbacks-by-channel-id-response.dto'; +import type { OsQueryDto } from './dtos/os-query.dto'; +import type { Feedback } from './dtos/responses/find-feedbacks-by-channel-id-response.dto'; import { isInvalidSortMethod } from './feedback.common'; import { FeedbackEntity } from './feedback.entity'; @@ -138,7 +137,9 @@ export class FeedbackOSService { return osQuery; } - if (!fieldsByKey.hasOwnProperty(fieldKey)) { + if ( + !Object.prototype.hasOwnProperty.call(fieldsByKey, fieldKey) + ) { throw new BadRequestException('bad key in query'); } @@ -188,7 +189,9 @@ export class FeedbackOSService { sort: Object.keys(sort).length !== 0 ? Object.keys(sort).map((fieldKey) => { - if (!fieldsByKey.hasOwnProperty(fieldKey)) { + if ( + !Object.prototype.hasOwnProperty.call(fieldsByKey, fieldKey) + ) { throw new BadRequestException('bad key in sort'); } const { key, format } = fieldsByKey[fieldKey]; diff --git a/apps/api/src/domains/feedback/feedback.service.spec.ts b/apps/api/src/domains/feedback/feedback.service.spec.ts index 1b2769c94..14dddbd89 100644 --- a/apps/api/src/domains/feedback/feedback.service.spec.ts +++ b/apps/api/src/domains/feedback/feedback.service.spec.ts @@ -18,7 +18,7 @@ import { BadRequestException } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { ClsService } from 'nestjs-cls'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { FieldFormatEnum, @@ -28,11 +28,10 @@ import { import { OpensearchRepository } from '@/common/repositories'; import { createFieldDto, getRandomValue } from '@/utils/test-util-fixture'; import { - MockOpensearchRepository, getMockProvider, + MockOpensearchRepository, mockRepository, } from '@/utils/test-utils'; - import { ChannelEntity } from '../channel/channel/channel.entity'; import { ChannelServiceProviders } from '../channel/channel/channel.service.spec'; import { RESERVED_FIELD_KEYS } from '../channel/field/field.constants'; diff --git a/apps/api/src/domains/feedback/feedback.service.ts b/apps/api/src/domains/feedback/feedback.service.ts index 3a0593144..6d24f0dbe 100644 --- a/apps/api/src/domains/feedback/feedback.service.ts +++ b/apps/api/src/domains/feedback/feedback.service.ts @@ -13,6 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { createReadStream, existsSync } from 'fs'; +import * as fs from 'fs/promises'; +import path from 'path'; +import { PassThrough } from 'stream'; import { BadRequestException, Injectable, @@ -21,11 +25,7 @@ import { import dayjs from 'dayjs'; import * as ExcelJS from 'exceljs'; import * as fastcsv from 'fast-csv'; -import { createReadStream, existsSync } from 'fs'; -import * as fs from 'fs/promises'; -import { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; -import path from 'path'; -import { PassThrough } from 'stream'; +import type { IPaginationMeta, Pagination } from 'nestjs-typeorm-paginate'; import { Transactional } from 'typeorm-transactional'; import { @@ -34,24 +34,25 @@ import { FieldTypeEnum, } from '@/common/enums'; import { OS_USE } from '@/configs/opensearch.config'; - import { ChannelService } from '../channel/channel/channel.service'; import { RESERVED_FIELD_KEYS } from '../channel/field/field.constants'; -import { FieldEntity } from '../channel/field/field.entity'; +import type { FieldEntity } from '../channel/field/field.entity'; import { FieldService } from '../channel/field/field.service'; import { OptionService } from '../channel/option/option.service'; import { IssueService } from '../project/issue/issue.service'; +import type { + CountByProjectIdDto, + FindFeedbacksByChannelIdDto, + GenerateExcelDto, +} from './dtos'; import { AddIssueDto, - CountByProjectIdDto, CreateFeedbackDto, DeleteByIdsDto, - FindFeedbacksByChannelIdDto, - GenerateExcelDto, RemoveIssueDto, UpdateFeedbackDto, } from './dtos'; -import { Feedback } from './dtos/responses/find-feedbacks-by-channel-id-response.dto'; +import type { Feedback } from './dtos/responses/find-feedbacks-by-channel-id-response.dto'; import { validateValue } from './feedback.common'; import { FeedbackMySQLService } from './feedback.mysql.service'; import { FeedbackOSService } from './feedback.os.service'; @@ -106,8 +107,8 @@ export class FeedbackService { if ( typeof query[fieldKey] !== 'object' || !( - query[fieldKey].hasOwnProperty('gte') && - query[fieldKey].hasOwnProperty('lt') + Object.prototype.hasOwnProperty.call(query[fieldKey], 'gte') && + Object.prototype.hasOwnProperty.call(query[fieldKey], 'lt') ) ) throw new BadRequestException(`${fieldKey} must be DateTimeRange`); diff --git a/apps/api/src/domains/history/create-history.dto.ts b/apps/api/src/domains/history/create-history.dto.ts index 4139aceb0..3a64c701d 100644 --- a/apps/api/src/domains/history/create-history.dto.ts +++ b/apps/api/src/domains/history/create-history.dto.ts @@ -13,8 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { HistoryActionEnum } from './history-action.enum'; -import { EntityNameEnum } from './history-entity.enum'; +import type { HistoryActionEnum } from './history-action.enum'; +import type { EntityNameEnum } from './history-entity.enum'; export class CreateHistoryDto { userId?: number | null; diff --git a/apps/api/src/domains/history/history.entity.ts b/apps/api/src/domains/history/history.entity.ts index c7610ebb3..1f02e3c53 100644 --- a/apps/api/src/domains/history/history.entity.ts +++ b/apps/api/src/domains/history/history.entity.ts @@ -16,7 +16,6 @@ import { Column, Entity, ManyToOne, Relation } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { UserEntity } from '../user/entities/user.entity'; import { HistoryActionEnum } from './history-action.enum'; import { EntityNameEnum } from './history-entity.enum'; diff --git a/apps/api/src/domains/history/history.service.ts b/apps/api/src/domains/history/history.service.ts index 471bbe3c8..399b214ee 100644 --- a/apps/api/src/domains/history/history.service.ts +++ b/apps/api/src/domains/history/history.service.ts @@ -17,7 +17,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectDataSource } from '@nestjs/typeorm'; import { DataSource } from 'typeorm'; -import { CreateHistoryDto } from './create-history.dto'; +import type { CreateHistoryDto } from './create-history.dto'; import { HistoryEntity } from './history.entity'; @Injectable() diff --git a/apps/api/src/domains/history/subscribers/abstract-history.subscriber.ts b/apps/api/src/domains/history/subscribers/abstract-history.subscriber.ts index 3602a85dd..c2c25e827 100644 --- a/apps/api/src/domains/history/subscribers/abstract-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/abstract-history.subscriber.ts @@ -15,8 +15,7 @@ */ import { InjectDataSource } from '@nestjs/typeorm'; import { ClsService } from 'nestjs-cls'; -import { - DataSource, +import type { EntitySubscriberInterface, InsertEvent, ObjectLiteral, @@ -25,9 +24,9 @@ import { SoftRemoveEvent, UpdateEvent, } from 'typeorm'; +import { DataSource } from 'typeorm'; -import { CommonEntity } from '@/common/entities'; - +import type { CommonEntity } from '@/common/entities'; import { HistoryActionEnum } from '../history-action.enum'; import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; diff --git a/apps/api/src/domains/history/subscribers/api-key-history.subscriber.ts b/apps/api/src/domains/history/subscribers/api-key-history.subscriber.ts index eb4f278b5..21ae776c5 100644 --- a/apps/api/src/domains/history/subscribers/api-key-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/api-key-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { ApiKeyEntity } from '@/domains/project/api-key/api-key.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/channel-history.subscriber.ts b/apps/api/src/domains/history/subscribers/channel-history.subscriber.ts index dfba3d013..4a7f39dcd 100644 --- a/apps/api/src/domains/history/subscribers/channel-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/channel-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { ChannelEntity } from '@/domains/channel/channel/channel.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/code-history.subscriber.ts b/apps/api/src/domains/history/subscribers/code-history.subscriber.ts index 7c7113f7a..99aa608bf 100644 --- a/apps/api/src/domains/history/subscribers/code-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/code-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { CodeEntity } from '@/shared/code/code.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/feedback-history.subscriber.ts b/apps/api/src/domains/history/subscribers/feedback-history.subscriber.ts index 619dd7702..9eae2d164 100644 --- a/apps/api/src/domains/history/subscribers/feedback-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/feedback-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { FeedbackEntity } from '@/domains/feedback/feedback.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/feedback-issue-history.subscriber.ts b/apps/api/src/domains/history/subscribers/feedback-issue-history.subscriber.ts index 24759dc9d..967a18dd9 100644 --- a/apps/api/src/domains/history/subscribers/feedback-issue-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/feedback-issue-history.subscriber.ts @@ -15,14 +15,10 @@ */ import { InjectDataSource } from '@nestjs/typeorm'; import { ClsService } from 'nestjs-cls'; -import { - DataSource, - EntitySubscriberInterface, - EventSubscriber, -} from 'typeorm'; - -import { ClsServiceType } from '@/types/cls-service.type'; +import type { EntitySubscriberInterface } from 'typeorm'; +import { DataSource, EventSubscriber } from 'typeorm'; +import type { ClsServiceType } from '@/types/cls-service.type'; import { HistoryActionEnum } from '../history-action.enum'; import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; diff --git a/apps/api/src/domains/history/subscribers/field-history.subscriber.ts b/apps/api/src/domains/history/subscribers/field-history.subscriber.ts index c151633d6..8dbbcf839 100644 --- a/apps/api/src/domains/history/subscribers/field-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/field-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { FieldEntity } from '@/domains/channel/field/field.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/issue-history.subscriber.ts b/apps/api/src/domains/history/subscribers/issue-history.subscriber.ts index 02834bf82..425407b83 100644 --- a/apps/api/src/domains/history/subscribers/issue-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/issue-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { IssueEntity } from '@/domains/project/issue/issue.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/issue-tracker-history.subscriber.ts b/apps/api/src/domains/history/subscribers/issue-tracker-history.subscriber.ts index 4e58b2abc..637eb3248 100644 --- a/apps/api/src/domains/history/subscribers/issue-tracker-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/issue-tracker-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { IssueTrackerEntity } from '@/domains/project/issue-tracker/issue-tracker.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/member-history.subscriber.ts b/apps/api/src/domains/history/subscribers/member-history.subscriber.ts index 51619d8c5..bc858a45d 100644 --- a/apps/api/src/domains/history/subscribers/member-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/member-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { MemberEntity } from '@/domains/project/member/member.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/option-history.subscriber.ts b/apps/api/src/domains/history/subscribers/option-history.subscriber.ts index eb761ee1c..edaac91c7 100644 --- a/apps/api/src/domains/history/subscribers/option-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/option-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { OptionEntity } from '@/domains/channel/option/option.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/project-history.subscriber.ts b/apps/api/src/domains/history/subscribers/project-history.subscriber.ts index 66f1d67d4..24f83b8ad 100644 --- a/apps/api/src/domains/history/subscribers/project-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/project-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { ProjectEntity } from '@/domains/project/project/project.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/role-history.subscriber.ts b/apps/api/src/domains/history/subscribers/role-history.subscriber.ts index 89294f9d1..06def656e 100644 --- a/apps/api/src/domains/history/subscribers/role-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/role-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { RoleEntity } from '@/domains/project/role/role.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/tenant-history.subscriber.ts b/apps/api/src/domains/history/subscribers/tenant-history.subscriber.ts index a520347e7..7b2fc461a 100644 --- a/apps/api/src/domains/history/subscribers/tenant-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/tenant-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { TenantEntity } from '@/domains/tenant/tenant.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/history/subscribers/user-history.subscriber.ts b/apps/api/src/domains/history/subscribers/user-history.subscriber.ts index a910f407e..316b23412 100644 --- a/apps/api/src/domains/history/subscribers/user-history.subscriber.ts +++ b/apps/api/src/domains/history/subscribers/user-history.subscriber.ts @@ -18,7 +18,6 @@ import { ClsService } from 'nestjs-cls'; import { DataSource, EventSubscriber } from 'typeorm'; import { UserEntity } from '@/domains/user/entities/user.entity'; - import { EntityNameEnum } from '../history-entity.enum'; import { HistoryService } from '../history.service'; import { AbstractHistorySubscriber } from './abstract-history.subscriber'; diff --git a/apps/api/src/domains/migration/migration.module.ts b/apps/api/src/domains/migration/migration.module.ts index 98cc37c29..a8a340d26 100644 --- a/apps/api/src/domains/migration/migration.module.ts +++ b/apps/api/src/domains/migration/migration.module.ts @@ -13,12 +13,12 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Module, OnModuleInit } from '@nestjs/common'; +import type { OnModuleInit } from '@nestjs/common'; +import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpensearchRepository } from '@/common/repositories'; import { OS_USE } from '@/configs/opensearch.config'; - import { ChannelEntity } from '../channel/channel/channel.entity'; import { FieldEntity } from '../channel/field/field.entity'; import { FieldModule } from '../channel/field/field.module'; diff --git a/apps/api/src/domains/migration/migration.service.ts b/apps/api/src/domains/migration/migration.service.ts index 87319aaaf..3b8f69087 100644 --- a/apps/api/src/domains/migration/migration.service.ts +++ b/apps/api/src/domains/migration/migration.service.ts @@ -13,15 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Inject, Logger } from '@nestjs/common'; -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Client } from '@opensearch-project/opensearch'; import dayjs from 'dayjs'; import { Repository } from 'typeorm'; import { OpensearchRepository } from '@/common/repositories'; - import { ChannelEntity } from '../channel/channel/channel.entity'; import { FieldService } from '../channel/field/field.service'; import { FeedbackEntity } from '../feedback/feedback.entity'; diff --git a/apps/api/src/domains/project/api-key/api-key.controller.spec.ts b/apps/api/src/domains/project/api-key/api-key.controller.spec.ts index ee7b476c2..238a135f8 100644 --- a/apps/api/src/domains/project/api-key/api-key.controller.spec.ts +++ b/apps/api/src/domains/project/api-key/api-key.controller.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { DataSource } from 'typeorm'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { ApiKeyController } from './api-key.controller'; import { ApiKeyService } from './api-key.service'; diff --git a/apps/api/src/domains/project/api-key/api-key.entity.ts b/apps/api/src/domains/project/api-key/api-key.entity.ts index 2fdabb837..ebba86846 100644 --- a/apps/api/src/domains/project/api-key/api-key.entity.ts +++ b/apps/api/src/domains/project/api-key/api-key.entity.ts @@ -16,7 +16,6 @@ import { Column, Entity, ManyToOne, Relation } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { ProjectEntity } from '../project/project.entity'; @Entity('api_keys') diff --git a/apps/api/src/domains/project/api-key/api-key.service.spec.ts b/apps/api/src/domains/project/api-key/api-key.service.spec.ts index f6642e48f..7ce4c7895 100644 --- a/apps/api/src/domains/project/api-key/api-key.service.spec.ts +++ b/apps/api/src/domains/project/api-key/api-key.service.spec.ts @@ -13,14 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { randomBytes } from 'crypto'; import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { randomBytes } from 'crypto'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { mockRepository } from '@/utils/test-utils'; - import { ProjectNotFoundException } from '../project/exceptions'; import { ProjectEntity } from '../project/project.entity'; import { ProjectServiceProviders } from '../project/project.service.spec'; diff --git a/apps/api/src/domains/project/api-key/api-key.service.ts b/apps/api/src/domains/project/api-key/api-key.service.ts index 09870a1df..31b79e38e 100644 --- a/apps/api/src/domains/project/api-key/api-key.service.ts +++ b/apps/api/src/domains/project/api-key/api-key.service.ts @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { randomBytes } from 'crypto'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { randomBytes } from 'crypto'; import dayjs from 'dayjs'; import { Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; diff --git a/apps/api/src/domains/project/api-key/dtos/responses/find-api-keys-response.dto.ts b/apps/api/src/domains/project/api-key/dtos/responses/find-api-keys-response.dto.ts index b0c9939df..202ce7ce7 100644 --- a/apps/api/src/domains/project/api-key/dtos/responses/find-api-keys-response.dto.ts +++ b/apps/api/src/domains/project/api-key/dtos/responses/find-api-keys-response.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; class ApiKeyResponseDto { @Expose() diff --git a/apps/api/src/domains/project/issue-tracker/issue-tracker.controller.spec.ts b/apps/api/src/domains/project/issue-tracker/issue-tracker.controller.spec.ts index 91a4fd329..a040a3bd5 100644 --- a/apps/api/src/domains/project/issue-tracker/issue-tracker.controller.spec.ts +++ b/apps/api/src/domains/project/issue-tracker/issue-tracker.controller.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { DataSource } from 'typeorm'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { IssueTrackerController } from './issue-tracker.controller'; import { IssueTrackerService } from './issue-tracker.service'; diff --git a/apps/api/src/domains/project/issue-tracker/issue-tracker.entity.ts b/apps/api/src/domains/project/issue-tracker/issue-tracker.entity.ts index ea7f30157..cd3c38031 100644 --- a/apps/api/src/domains/project/issue-tracker/issue-tracker.entity.ts +++ b/apps/api/src/domains/project/issue-tracker/issue-tracker.entity.ts @@ -16,9 +16,8 @@ import { Column, Entity, JoinColumn, OneToOne, Relation } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { ProjectEntity } from '../project/project.entity'; -import { CreateIssueTrackerDto } from './dtos'; +import type { CreateIssueTrackerDto } from './dtos'; @Entity('issue_trackers') export class IssueTrackerEntity extends CommonEntity { diff --git a/apps/api/src/domains/project/issue-tracker/issue-tracker.service.spec.ts b/apps/api/src/domains/project/issue-tracker/issue-tracker.service.spec.ts index 2e707aba2..ed71c3142 100644 --- a/apps/api/src/domains/project/issue-tracker/issue-tracker.service.spec.ts +++ b/apps/api/src/domains/project/issue-tracker/issue-tracker.service.spec.ts @@ -16,10 +16,9 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { mockRepository } from '@/utils/test-utils'; - import { UpdateIssueTrackerDto } from './dtos'; import { IssueTrackerEntity } from './issue-tracker.entity'; import { IssueTrackerService } from './issue-tracker.service'; diff --git a/apps/api/src/domains/project/issue/dtos/find-issues-by-project-id.dto.ts b/apps/api/src/domains/project/issue/dtos/find-issues-by-project-id.dto.ts index 1305eddac..7b4aa63a7 100644 --- a/apps/api/src/domains/project/issue/dtos/find-issues-by-project-id.dto.ts +++ b/apps/api/src/domains/project/issue/dtos/find-issues-by-project-id.dto.ts @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { PaginationDto, TimeRange } from '@/common/dtos'; - -import { SortMethodEnum } from '../../../../common/enums'; +import type { TimeRange } from '@/common/dtos'; +import { PaginationDto } from '@/common/dtos'; +import type { SortMethodEnum } from '../../../../common/enums'; export class FindIssuesByProjectIdDto extends PaginationDto { projectId: number; diff --git a/apps/api/src/domains/project/issue/dtos/requests/find-issues-by-project-id-request.dto.ts b/apps/api/src/domains/project/issue/dtos/requests/find-issues-by-project-id-request.dto.ts index 9affc746d..e615cc8ca 100644 --- a/apps/api/src/domains/project/issue/dtos/requests/find-issues-by-project-id-request.dto.ts +++ b/apps/api/src/domains/project/issue/dtos/requests/find-issues-by-project-id-request.dto.ts @@ -16,8 +16,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsOptional } from 'class-validator'; -import { PaginationRequestDto, TimeRange } from '@/common/dtos'; -import { SortMethodEnum } from '@/common/enums'; +import type { TimeRange } from '@/common/dtos'; +import { PaginationRequestDto } from '@/common/dtos'; +import type { SortMethodEnum } from '@/common/enums'; export class FindIssuesByProjectIdRequestDto extends PaginationRequestDto { @ApiProperty({ type: Object, required: false }) diff --git a/apps/api/src/domains/project/issue/dtos/requests/update-issue-request.dto.ts b/apps/api/src/domains/project/issue/dtos/requests/update-issue-request.dto.ts index 710cf36af..6576113c9 100644 --- a/apps/api/src/domains/project/issue/dtos/requests/update-issue-request.dto.ts +++ b/apps/api/src/domains/project/issue/dtos/requests/update-issue-request.dto.ts @@ -18,7 +18,6 @@ import { IsEnum, IsOptional, IsString } from 'class-validator'; import { IssueStatusEnum } from '@/common/enums'; import { IsNullable } from '@/domains/user/decorators'; - import { CreateIssueRequestDto } from './create-issue-request.dto'; export class UpdateIssueRequestDto extends CreateIssueRequestDto { diff --git a/apps/api/src/domains/project/issue/dtos/responses/find-issues-by-project-id-response.dto.ts b/apps/api/src/domains/project/issue/dtos/responses/find-issues-by-project-id-response.dto.ts index fb75725df..7aef21bc2 100644 --- a/apps/api/src/domains/project/issue/dtos/responses/find-issues-by-project-id-response.dto.ts +++ b/apps/api/src/domains/project/issue/dtos/responses/find-issues-by-project-id-response.dto.ts @@ -14,10 +14,9 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PaginationResponseDto } from '@/common/dtos'; - import { FindIssueByIdResponseDto } from './find-issue-by-id-response.dto'; export class FindIssuesByProjectIdResponseDto extends PaginationResponseDto { diff --git a/apps/api/src/domains/project/issue/issue.controller.spec.ts b/apps/api/src/domains/project/issue/issue.controller.spec.ts index cab38dc89..2b1f20d85 100644 --- a/apps/api/src/domains/project/issue/issue.controller.spec.ts +++ b/apps/api/src/domains/project/issue/issue.controller.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { DataSource } from 'typeorm'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { CreateIssueRequestDto, DeleteIssuesRequestDto, diff --git a/apps/api/src/domains/project/issue/issue.entity.ts b/apps/api/src/domains/project/issue/issue.entity.ts index 55b76c93f..722a19773 100644 --- a/apps/api/src/domains/project/issue/issue.entity.ts +++ b/apps/api/src/domains/project/issue/issue.entity.ts @@ -25,7 +25,6 @@ import { import { CommonEntity } from '@/common/entities'; import { IssueStatusEnum } from '@/common/enums'; - import { FeedbackEntity } from '../../feedback/feedback.entity'; import { ProjectEntity } from '../project/project.entity'; diff --git a/apps/api/src/domains/project/issue/issue.service.spec.ts b/apps/api/src/domains/project/issue/issue.service.spec.ts index 41208a0c1..2cac517be 100644 --- a/apps/api/src/domains/project/issue/issue.service.spec.ts +++ b/apps/api/src/domains/project/issue/issue.service.spec.ts @@ -16,11 +16,11 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Like, Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; +import { Like } from 'typeorm'; -import { TimeRange } from '@/common/dtos'; +import type { TimeRange } from '@/common/dtos'; import { createQueryBuilder, mockRepository } from '@/utils/test-utils'; - import { CreateIssueDto, FindIssuesByProjectIdDto, diff --git a/apps/api/src/domains/project/issue/issue.service.ts b/apps/api/src/domains/project/issue/issue.service.ts index 56cce6b13..72ad081e9 100644 --- a/apps/api/src/domains/project/issue/issue.service.ts +++ b/apps/api/src/domains/project/issue/issue.service.ts @@ -16,26 +16,14 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { paginate } from 'nestjs-typeorm-paginate'; -import { - FindManyOptions, - FindOptionsWhere, - In, - Like, - Not, - Raw, - Repository, -} from 'typeorm'; +import type { FindManyOptions, FindOptionsWhere } from 'typeorm'; +import { In, Like, Not, Raw, Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; -import { TimeRange } from '@/common/dtos'; -import { CountByProjectIdDto } from '@/domains/feedback/dtos'; - -import { - CreateIssueDto, - FindByIssueIdDto, - FindIssuesByProjectIdDto, - UpdateIssueDto, -} from './dtos'; +import type { TimeRange } from '@/common/dtos'; +import type { CountByProjectIdDto } from '@/domains/feedback/dtos'; +import type { FindByIssueIdDto, FindIssuesByProjectIdDto } from './dtos'; +import { CreateIssueDto, UpdateIssueDto } from './dtos'; import { IssueInvalidNameException, IssueNameDuplicatedException, diff --git a/apps/api/src/domains/project/member/dtos/find-by-project-id.dto.ts b/apps/api/src/domains/project/member/dtos/find-by-project-id.dto.ts index 846c50caf..cff53fdb4 100644 --- a/apps/api/src/domains/project/member/dtos/find-by-project-id.dto.ts +++ b/apps/api/src/domains/project/member/dtos/find-by-project-id.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { SortMethodEnum } from '@/common/enums'; +import type { SortMethodEnum } from '@/common/enums'; export class FindByProjectIdDto { projectId: number; diff --git a/apps/api/src/domains/project/member/dtos/responses/get-all-members.dto.ts b/apps/api/src/domains/project/member/dtos/responses/get-all-members.dto.ts index d7bef1a57..360a1b209 100644 --- a/apps/api/src/domains/project/member/dtos/responses/get-all-members.dto.ts +++ b/apps/api/src/domains/project/member/dtos/responses/get-all-members.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PermissionEnum } from '@/domains/project/role/permission.enum'; diff --git a/apps/api/src/domains/project/member/member.controller.ts b/apps/api/src/domains/project/member/member.controller.ts index ce234232c..bd9c77302 100644 --- a/apps/api/src/domains/project/member/member.controller.ts +++ b/apps/api/src/domains/project/member/member.controller.ts @@ -27,7 +27,6 @@ import { import { ApiOkResponse, ApiParam, ApiTags } from '@nestjs/swagger'; import { SortMethodEnum } from '@/common/enums'; - import { PermissionEnum } from '../role/permission.enum'; import { RequirePermission } from '../role/require-permission.decorator'; import { diff --git a/apps/api/src/domains/project/member/member.entity.ts b/apps/api/src/domains/project/member/member.entity.ts index d5a911071..3079c7f8d 100644 --- a/apps/api/src/domains/project/member/member.entity.ts +++ b/apps/api/src/domains/project/member/member.entity.ts @@ -16,7 +16,6 @@ import { Entity, ManyToOne, Relation, Unique } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { UserEntity } from '../../user/entities/user.entity'; import { RoleEntity } from '../role/role.entity'; diff --git a/apps/api/src/domains/project/member/member.service.spec.ts b/apps/api/src/domains/project/member/member.service.spec.ts index 87fc3fa8d..f54f8dd63 100644 --- a/apps/api/src/domains/project/member/member.service.spec.ts +++ b/apps/api/src/domains/project/member/member.service.spec.ts @@ -16,10 +16,9 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { mockRepository } from '@/utils/test-utils'; - import { RoleEntity } from '../role/role.entity'; import { RoleServiceProviders } from '../role/role.service.spec'; import { CreateMemberDto, UpdateMemberDto } from './dtos'; diff --git a/apps/api/src/domains/project/member/member.service.ts b/apps/api/src/domains/project/member/member.service.ts index 132585c5b..f14aec2e4 100644 --- a/apps/api/src/domains/project/member/member.service.ts +++ b/apps/api/src/domains/project/member/member.service.ts @@ -19,7 +19,8 @@ import { Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; import { RoleService } from '../role/role.service'; -import { CreateMemberDto, FindByProjectIdDto, UpdateMemberDto } from './dtos'; +import type { FindByProjectIdDto } from './dtos'; +import { CreateMemberDto, UpdateMemberDto } from './dtos'; import { MemberAlreadyExistsException, MemberNotFoundException, diff --git a/apps/api/src/domains/project/project/dtos/find-all-projects.dto.ts b/apps/api/src/domains/project/project/dtos/find-all-projects.dto.ts index b20d1f1c0..613f9efe3 100644 --- a/apps/api/src/domains/project/project/dtos/find-all-projects.dto.ts +++ b/apps/api/src/domains/project/project/dtos/find-all-projects.dto.ts @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { IPaginationOptions } from 'nestjs-typeorm-paginate'; +import type { IPaginationOptions } from 'nestjs-typeorm-paginate'; -import { UserDto } from '@/domains/user/dtos'; +import type { UserDto } from '@/domains/user/dtos'; export class FindAllProjectsDto { user: UserDto; diff --git a/apps/api/src/domains/project/project/dtos/responses/find-projects-response.dto.ts b/apps/api/src/domains/project/project/dtos/responses/find-projects-response.dto.ts index 085d8194b..b5b9bbc0f 100644 --- a/apps/api/src/domains/project/project/dtos/responses/find-projects-response.dto.ts +++ b/apps/api/src/domains/project/project/dtos/responses/find-projects-response.dto.ts @@ -14,10 +14,9 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PaginationResponseDto } from '@/common/dtos'; - import { FindProjectByIdResponseDto } from './find-project-by-id-response.dto'; export class FindProjectsResponseDto extends PaginationResponseDto { diff --git a/apps/api/src/domains/project/project/project.controller.spec.ts b/apps/api/src/domains/project/project/project.controller.spec.ts index d7292dd87..bbb33341e 100644 --- a/apps/api/src/domains/project/project/project.controller.spec.ts +++ b/apps/api/src/domains/project/project/project.controller.spec.ts @@ -19,8 +19,7 @@ import { DataSource } from 'typeorm'; import { FeedbackService } from '@/domains/feedback/feedback.service'; import { UserDto } from '@/domains/user/dtos'; -import { MockDataSource, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, MockDataSource } from '@/utils/test-utils'; import { IssueService } from '../issue/issue.service'; import { CreateProjectRequestDto, diff --git a/apps/api/src/domains/project/project/project.controller.ts b/apps/api/src/domains/project/project/project.controller.ts index 39eca865a..d83c73414 100644 --- a/apps/api/src/domains/project/project/project.controller.ts +++ b/apps/api/src/domains/project/project/project.controller.ts @@ -32,7 +32,6 @@ import { FeedbackService } from '@/domains/feedback/feedback.service'; import { CurrentUser } from '@/domains/user/decorators'; import { UserDto } from '@/domains/user/dtos'; import { SuperUser } from '@/domains/user/super-user.decorator'; - import { IssueService } from '../issue/issue.service'; import { PermissionEnum } from '../role/permission.enum'; import { RequirePermission } from '../role/require-permission.decorator'; diff --git a/apps/api/src/domains/project/project/project.entity.ts b/apps/api/src/domains/project/project/project.entity.ts index fb1f2cb77..a6c1ef855 100644 --- a/apps/api/src/domains/project/project/project.entity.ts +++ b/apps/api/src/domains/project/project/project.entity.ts @@ -23,10 +23,9 @@ import { } from 'typeorm'; import { CommonEntity } from '@/common/entities'; -import { ApiKeyEntity } from '@/domains/project/api-key/api-key.entity'; -import { IssueTrackerEntity } from '@/domains/project/issue-tracker/issue-tracker.entity'; +import type { ApiKeyEntity } from '@/domains/project/api-key/api-key.entity'; +import type { IssueTrackerEntity } from '@/domains/project/issue-tracker/issue-tracker.entity'; import { TenantEntity } from '@/domains/tenant/tenant.entity'; - import { ChannelEntity } from '../../channel/channel/channel.entity'; import { IssueEntity } from '../issue/issue.entity'; import { RoleEntity } from '../role/role.entity'; diff --git a/apps/api/src/domains/project/project/project.module.ts b/apps/api/src/domains/project/project/project.module.ts index f4f1017c8..59b84805b 100644 --- a/apps/api/src/domains/project/project/project.module.ts +++ b/apps/api/src/domains/project/project/project.module.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Module, forwardRef } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpensearchRepository } from '@/common/repositories'; @@ -25,7 +25,6 @@ import { OptionModule } from '@/domains/channel/option/option.module'; import { FeedbackEntity } from '@/domains/feedback/feedback.entity'; import { FeedbackModule } from '@/domains/feedback/feedback.module'; import { TenantModule } from '@/domains/tenant/tenant.module'; - import { IssueEntity } from '../issue/issue.entity'; import { IssueModule } from '../issue/issue.module'; import { RoleModule } from '../role/role.module'; diff --git a/apps/api/src/domains/project/project/project.service.spec.ts b/apps/api/src/domains/project/project/project.service.spec.ts index 9b3891f81..75e0b8a87 100644 --- a/apps/api/src/domains/project/project/project.service.spec.ts +++ b/apps/api/src/domains/project/project/project.service.spec.ts @@ -16,7 +16,8 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Like, Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; +import { Like } from 'typeorm'; import { OpensearchRepository } from '@/common/repositories'; import { TenantEntity } from '@/domains/tenant/tenant.entity'; @@ -24,12 +25,11 @@ import { TenantServiceProviders } from '@/domains/tenant/tenant.service.spec'; import { UserDto } from '@/domains/user/dtos'; import { UserTypeEnum } from '@/domains/user/entities/enums'; import { - MockOpensearchRepository, createQueryBuilder, getMockProvider, + MockOpensearchRepository, mockRepository, } from '@/utils/test-utils'; - import { ChannelEntity } from '../../channel/channel/channel.entity'; import { ProjectEntity } from '../../project/project/project.entity'; import { RoleServiceProviders } from '../role/role.service.spec'; diff --git a/apps/api/src/domains/project/project/project.service.ts b/apps/api/src/domains/project/project/project.service.ts index 8c32cb24b..c4cf8aaad 100644 --- a/apps/api/src/domains/project/project/project.service.ts +++ b/apps/api/src/domains/project/project/project.service.ts @@ -23,13 +23,13 @@ import { OpensearchRepository } from '@/common/repositories'; import { OS_USE } from '@/configs/opensearch.config'; import { TenantService } from '@/domains/tenant/tenant.service'; import { UserTypeEnum } from '@/domains/user/entities/enums'; - import { ChannelEntity } from '../../channel/channel/channel.entity'; import { ProjectEntity } from '../../project/project/project.entity'; import { AllPermissionList } from '../role/permission.enum'; import { RoleService } from '../role/role.service'; -import { CreateProjectDto, FindAllProjectsDto, UpdateProjectDto } from './dtos'; -import { FindByProjectIdDto } from './dtos/find-by-project-id.dto'; +import type { FindAllProjectsDto } from './dtos'; +import { CreateProjectDto, UpdateProjectDto } from './dtos'; +import type { FindByProjectIdDto } from './dtos/find-by-project-id.dto'; import { ProjectAlreadyExistsException, ProjectInvalidNameException, diff --git a/apps/api/src/domains/project/role/dtos/create-role.dto.ts b/apps/api/src/domains/project/role/dtos/create-role.dto.ts index d11cb9605..edf690c86 100644 --- a/apps/api/src/domains/project/role/dtos/create-role.dto.ts +++ b/apps/api/src/domains/project/role/dtos/create-role.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { PermissionEnum } from '../permission.enum'; +import type { PermissionEnum } from '../permission.enum'; export class CreateRoleDto { projectId: number; diff --git a/apps/api/src/domains/project/role/dtos/requests/create-role-request.dto.ts b/apps/api/src/domains/project/role/dtos/requests/create-role-request.dto.ts index 403655951..cb9df6b11 100644 --- a/apps/api/src/domains/project/role/dtos/requests/create-role-request.dto.ts +++ b/apps/api/src/domains/project/role/dtos/requests/create-role-request.dto.ts @@ -17,7 +17,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; import { ArrayDistinct } from '@/common/validators'; - import { PermissionEnum } from '../../permission.enum'; export class CreateRoleRequestDto { diff --git a/apps/api/src/domains/project/role/dtos/responses/get-all-role-response.dto.ts b/apps/api/src/domains/project/role/dtos/responses/get-all-role-response.dto.ts index 078729fb6..40f629d3b 100644 --- a/apps/api/src/domains/project/role/dtos/responses/get-all-role-response.dto.ts +++ b/apps/api/src/domains/project/role/dtos/responses/get-all-role-response.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PermissionEnum } from '../../permission.enum'; diff --git a/apps/api/src/domains/project/role/permission.guard.ts b/apps/api/src/domains/project/role/permission.guard.ts index b9427ddc2..2b6ee2d39 100644 --- a/apps/api/src/domains/project/role/permission.guard.ts +++ b/apps/api/src/domains/project/role/permission.guard.ts @@ -13,19 +13,14 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { - BadRequestException, - CanActivate, - ExecutionContext, - Injectable, -} from '@nestjs/common'; +import type { CanActivate, ExecutionContext } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { InjectDataSource } from '@nestjs/typeorm'; import { DataSource } from 'typeorm'; import { UserTypeEnum } from '@/domains/user/entities/enums'; - -import { PermissionEnum } from './permission.enum'; +import type { PermissionEnum } from './permission.enum'; import { PERMISSIONS_KEY } from './require-permission.decorator'; import { RoleEntity } from './role.entity'; diff --git a/apps/api/src/domains/project/role/require-permission.decorator.ts b/apps/api/src/domains/project/role/require-permission.decorator.ts index 862e81928..0be43ee85 100644 --- a/apps/api/src/domains/project/role/require-permission.decorator.ts +++ b/apps/api/src/domains/project/role/require-permission.decorator.ts @@ -13,10 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { SetMetadata, UseGuards, applyDecorators } from '@nestjs/common'; +import { applyDecorators, SetMetadata, UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from '../../auth/guards'; -import { PermissionEnum } from './permission.enum'; +import type { PermissionEnum } from './permission.enum'; import { PermissionGuard } from './permission.guard'; export const PERMISSIONS_KEY = 'permissions'; diff --git a/apps/api/src/domains/project/role/role.controller.spec.ts b/apps/api/src/domains/project/role/role.controller.spec.ts index c78007608..e501abe4d 100644 --- a/apps/api/src/domains/project/role/role.controller.spec.ts +++ b/apps/api/src/domains/project/role/role.controller.spec.ts @@ -18,11 +18,10 @@ import { Test } from '@nestjs/testing'; import { DataSource } from 'typeorm'; import { - MockDataSource, getMockProvider, getRandomEnumValue, + MockDataSource, } from '@/utils/test-utils'; - import { CreateRoleDto, UpdateRoleDto } from './dtos'; import { PermissionEnum } from './permission.enum'; import { RoleController } from './role.controller'; diff --git a/apps/api/src/domains/project/role/role.entity.ts b/apps/api/src/domains/project/role/role.entity.ts index 6ad96b763..4718335b3 100644 --- a/apps/api/src/domains/project/role/role.entity.ts +++ b/apps/api/src/domains/project/role/role.entity.ts @@ -16,10 +16,9 @@ import { Column, Entity, Index, ManyToOne, OneToMany, Relation } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { MemberEntity } from '../member/member.entity'; import { ProjectEntity } from '../project/project.entity'; -import { PermissionEnum } from './permission.enum'; +import type { PermissionEnum } from './permission.enum'; @Entity('roles') @Index(['name', 'project']) diff --git a/apps/api/src/domains/project/role/role.service.spec.ts b/apps/api/src/domains/project/role/role.service.spec.ts index 49a137a7d..98ed38430 100644 --- a/apps/api/src/domains/project/role/role.service.spec.ts +++ b/apps/api/src/domains/project/role/role.service.spec.ts @@ -16,10 +16,9 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { getRandomEnumValues, mockRepository } from '@/utils/test-utils'; - import { CreateRoleDto, UpdateRoleDto } from './dtos'; import { RoleAlreadyExistsException, diff --git a/apps/api/src/domains/tenant/dtos/responses/get-tenant-response.dto.ts b/apps/api/src/domains/tenant/dtos/responses/get-tenant-response.dto.ts index afdb6532d..666c94b09 100644 --- a/apps/api/src/domains/tenant/dtos/responses/get-tenant-response.dto.ts +++ b/apps/api/src/domains/tenant/dtos/responses/get-tenant-response.dto.ts @@ -14,7 +14,7 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; export class OAuthConfigResponseDto { @Expose() diff --git a/apps/api/src/domains/tenant/dtos/update-tenant.dto.ts b/apps/api/src/domains/tenant/dtos/update-tenant.dto.ts index cf5229e31..388aef043 100644 --- a/apps/api/src/domains/tenant/dtos/update-tenant.dto.ts +++ b/apps/api/src/domains/tenant/dtos/update-tenant.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { OAuthConfig } from '../tenant.entity'; +import type { OAuthConfig } from '../tenant.entity'; export class UpdateTenantDto { siteName: string; diff --git a/apps/api/src/domains/tenant/tenant.entity.ts b/apps/api/src/domains/tenant/tenant.entity.ts index 691d0b864..b8391b8c0 100644 --- a/apps/api/src/domains/tenant/tenant.entity.ts +++ b/apps/api/src/domains/tenant/tenant.entity.ts @@ -13,10 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Column, Entity, OneToMany, Relation } from 'typeorm'; +import type { Relation } from 'typeorm'; +import { Column, Entity, OneToMany } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { ProjectEntity } from '../project/project/project.entity'; export interface OAuthConfig { diff --git a/apps/api/src/domains/tenant/tenant.service.spec.ts b/apps/api/src/domains/tenant/tenant.service.spec.ts index b282c9cda..4c1a75dc0 100644 --- a/apps/api/src/domains/tenant/tenant.service.spec.ts +++ b/apps/api/src/domains/tenant/tenant.service.spec.ts @@ -16,10 +16,9 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { mockRepository } from '@/utils/test-utils'; - import { FeedbackEntity } from '../feedback/feedback.entity'; import { UserEntity } from '../user/entities/user.entity'; import { diff --git a/apps/api/src/domains/tenant/tenant.service.ts b/apps/api/src/domains/tenant/tenant.service.ts index ee3d20435..a96934168 100644 --- a/apps/api/src/domains/tenant/tenant.service.ts +++ b/apps/api/src/domains/tenant/tenant.service.ts @@ -19,15 +19,11 @@ import { Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; import { SMTP_USE } from '@/configs/smtp.config'; - import { FeedbackEntity } from '../feedback/feedback.entity'; import { UserTypeEnum } from '../user/entities/enums'; import { UserEntity } from '../user/entities/user.entity'; -import { - FeedbackCountByTenantIdDto, - SetupTenantDto, - UpdateTenantDto, -} from './dtos'; +import type { FeedbackCountByTenantIdDto } from './dtos'; +import { SetupTenantDto, UpdateTenantDto } from './dtos'; import { TenantAlreadyExistsException, TenantNotFoundException, diff --git a/apps/api/src/domains/user/create-user.service.spec.ts b/apps/api/src/domains/user/create-user.service.spec.ts index 3c6a42913..23467972f 100644 --- a/apps/api/src/domains/user/create-user.service.spec.ts +++ b/apps/api/src/domains/user/create-user.service.spec.ts @@ -16,18 +16,17 @@ import { faker } from '@faker-js/faker'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { mockRepository } from '@/utils/test-utils'; - import { MemberEntity } from '../project/member/member.entity'; import { MemberServiceProviders } from '../project/member/member.service.spec'; import { RoleEntity } from '../project/role/role.entity'; import { TenantEntity } from '../tenant/tenant.entity'; import { TenantServiceProviders } from '../tenant/tenant.service.spec'; import { CreateUserService } from './create-user.service'; -import { CreateEmailUserDto, CreateInvitationUserDto } from './dtos'; -import { CreateOAuthUserDto } from './dtos/create-oauth-user.dto'; +import type { CreateEmailUserDto, CreateInvitationUserDto } from './dtos'; +import type { CreateOAuthUserDto } from './dtos/create-oauth-user.dto'; import { SignUpMethodEnum, UserTypeEnum } from './entities/enums'; import { UserEntity } from './entities/user.entity'; import { diff --git a/apps/api/src/domains/user/create-user.service.ts b/apps/api/src/domains/user/create-user.service.ts index d8cace12a..5dfc64ee8 100644 --- a/apps/api/src/domains/user/create-user.service.ts +++ b/apps/api/src/domains/user/create-user.service.ts @@ -20,8 +20,8 @@ import { Transactional } from 'typeorm-transactional'; import { MemberService } from '../project/member/member.service'; import { TenantService } from '../tenant/tenant.service'; -import { CreateEmailUserDto, CreateInvitationUserDto } from './dtos'; -import { CreateOAuthUserDto } from './dtos/create-oauth-user.dto'; +import type { CreateEmailUserDto, CreateInvitationUserDto } from './dtos'; +import type { CreateOAuthUserDto } from './dtos/create-oauth-user.dto'; import { CreateUserDto } from './dtos/create-user.dto'; import { SignUpMethodEnum } from './entities/enums'; import { UserEntity } from './entities/user.entity'; diff --git a/apps/api/src/domains/user/decorators/current-user.decorator.ts b/apps/api/src/domains/user/decorators/current-user.decorator.ts index c9019151a..011366316 100644 --- a/apps/api/src/domains/user/decorators/current-user.decorator.ts +++ b/apps/api/src/domains/user/decorators/current-user.decorator.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { ExecutionContext, createParamDecorator } from '@nestjs/common'; +import type { ExecutionContext } from '@nestjs/common'; +import { createParamDecorator } from '@nestjs/common'; type DataType = 'id'; diff --git a/apps/api/src/domains/user/decorators/is-nullable.decorator.ts b/apps/api/src/domains/user/decorators/is-nullable.decorator.ts index 903f8623a..67a706db4 100644 --- a/apps/api/src/domains/user/decorators/is-nullable.decorator.ts +++ b/apps/api/src/domains/user/decorators/is-nullable.decorator.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { ValidateIf, ValidationOptions } from 'class-validator'; +import type { ValidationOptions } from 'class-validator'; +import { ValidateIf } from 'class-validator'; export function IsNullable(validationOptions?: ValidationOptions) { return ValidateIf((_object, value) => value !== null, validationOptions); diff --git a/apps/api/src/domains/user/dtos/create-invitation-user.dto.ts b/apps/api/src/domains/user/dtos/create-invitation-user.dto.ts index 34d880141..ff66f1776 100644 --- a/apps/api/src/domains/user/dtos/create-invitation-user.dto.ts +++ b/apps/api/src/domains/user/dtos/create-invitation-user.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { UserTypeEnum } from '../entities/enums'; +import type { UserTypeEnum } from '../entities/enums'; export class CreateInvitationUserDto { email: string; diff --git a/apps/api/src/domains/user/dtos/create-user.dto.ts b/apps/api/src/domains/user/dtos/create-user.dto.ts index 0278dca2b..1150896bf 100644 --- a/apps/api/src/domains/user/dtos/create-user.dto.ts +++ b/apps/api/src/domains/user/dtos/create-user.dto.ts @@ -13,10 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { SignUpMethodEnum } from '../entities/enums'; -import { CreateEmailUserDto } from './create-email-user.dto'; -import { CreateInvitationUserDto } from './create-invitation-user.dto'; -import { CreateOAuthUserDto } from './create-oauth-user.dto'; +import type { SignUpMethodEnum } from '../entities/enums'; +import type { CreateEmailUserDto } from './create-email-user.dto'; +import type { CreateInvitationUserDto } from './create-invitation-user.dto'; +import type { CreateOAuthUserDto } from './create-oauth-user.dto'; export type CreateUserDto = ( | Omit diff --git a/apps/api/src/domains/user/dtos/find-all-users.dto.ts b/apps/api/src/domains/user/dtos/find-all-users.dto.ts index 06942e739..6b41796c1 100644 --- a/apps/api/src/domains/user/dtos/find-all-users.dto.ts +++ b/apps/api/src/domains/user/dtos/find-all-users.dto.ts @@ -13,11 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { IPaginationOptions } from 'nestjs-typeorm-paginate'; +import type { IPaginationOptions } from 'nestjs-typeorm-paginate'; -import { SortMethodEnum } from '@/common/enums'; - -import { UserTypeEnum } from '../entities/enums'; +import type { SortMethodEnum } from '@/common/enums'; +import type { UserTypeEnum } from '../entities/enums'; export class FindAllUsersDto { options: IPaginationOptions; diff --git a/apps/api/src/domains/user/dtos/invite-user.dto.ts b/apps/api/src/domains/user/dtos/invite-user.dto.ts index 30e2a84d3..cfae825ab 100644 --- a/apps/api/src/domains/user/dtos/invite-user.dto.ts +++ b/apps/api/src/domains/user/dtos/invite-user.dto.ts @@ -13,8 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { UserTypeEnum } from '../entities/enums'; -import { UserDto } from './user.dto'; +import type { UserTypeEnum } from '../entities/enums'; +import type { UserDto } from './user.dto'; export class InviteUserDto { email: string; diff --git a/apps/api/src/domains/user/dtos/requests/get-all-users-request.dto.ts b/apps/api/src/domains/user/dtos/requests/get-all-users-request.dto.ts index 108f66890..e07410fc0 100644 --- a/apps/api/src/domains/user/dtos/requests/get-all-users-request.dto.ts +++ b/apps/api/src/domains/user/dtos/requests/get-all-users-request.dto.ts @@ -18,7 +18,6 @@ import { IsEnum, IsNumber, IsOptional, IsString } from 'class-validator'; import { PaginationRequestDto, TimeRange } from '@/common/dtos'; import { SortMethodEnum } from '@/common/enums'; - import { UserTypeEnum } from '../../entities/enums'; class UserOrder { diff --git a/apps/api/src/domains/user/dtos/responses/get-all-user-response.dto.ts b/apps/api/src/domains/user/dtos/responses/get-all-user-response.dto.ts index 217e304dc..1034eca6d 100644 --- a/apps/api/src/domains/user/dtos/responses/get-all-user-response.dto.ts +++ b/apps/api/src/domains/user/dtos/responses/get-all-user-response.dto.ts @@ -14,10 +14,9 @@ * under the License. */ import { ApiProperty } from '@nestjs/swagger'; -import { Expose, Type, plainToInstance } from 'class-transformer'; +import { Expose, plainToInstance, Type } from 'class-transformer'; import { PaginationResponseDto } from '@/common/dtos/pagination-response.dto'; - import { SignUpMethodEnum, UserTypeEnum } from '../../entities/enums'; class ProjectDto { diff --git a/apps/api/src/domains/user/dtos/update-user.dto.ts b/apps/api/src/domains/user/dtos/update-user.dto.ts index d72d1be64..d0026535f 100644 --- a/apps/api/src/domains/user/dtos/update-user.dto.ts +++ b/apps/api/src/domains/user/dtos/update-user.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { UserTypeEnum } from '../entities/enums'; +import type { UserTypeEnum } from '../entities/enums'; export class UpdateUserDto { userId: number; diff --git a/apps/api/src/domains/user/entities/user.entity.ts b/apps/api/src/domains/user/entities/user.entity.ts index 229ee5ff0..bf6df6120 100644 --- a/apps/api/src/domains/user/entities/user.entity.ts +++ b/apps/api/src/domains/user/entities/user.entity.ts @@ -13,11 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Column, Entity, OneToMany, Relation, Unique } from 'typeorm'; +import type { Relation } from 'typeorm'; +import { Column, Entity, OneToMany, Unique } from 'typeorm'; import { CommonEntity } from '@/common/entities'; import { MemberEntity } from '@/domains/project/member/member.entity'; - import { SignUpMethodEnum, UserStateEnum, UserTypeEnum } from './enums'; @Entity('users') diff --git a/apps/api/src/domains/user/super-user.decorator.ts b/apps/api/src/domains/user/super-user.decorator.ts index 810284e2e..f729634cc 100644 --- a/apps/api/src/domains/user/super-user.decorator.ts +++ b/apps/api/src/domains/user/super-user.decorator.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { UseGuards, applyDecorators } from '@nestjs/common'; +import { applyDecorators, UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from '../auth/guards'; import { SuperUserGuard } from './super-user.guard'; diff --git a/apps/api/src/domains/user/super-user.guard.ts b/apps/api/src/domains/user/super-user.guard.ts index 00299adb2..66761be2f 100644 --- a/apps/api/src/domains/user/super-user.guard.ts +++ b/apps/api/src/domains/user/super-user.guard.ts @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import type { CanActivate, ExecutionContext } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { UserTypeEnum } from './entities/enums'; diff --git a/apps/api/src/domains/user/user-password.service.spec.ts b/apps/api/src/domains/user/user-password.service.spec.ts index d9d3c1ab7..abd68e6c1 100644 --- a/apps/api/src/domains/user/user-password.service.spec.ts +++ b/apps/api/src/domains/user/user-password.service.spec.ts @@ -18,14 +18,13 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import * as bcrypt from 'bcrypt'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { CodeTypeEnum } from '@/shared/code/code-type.enum'; import { CodeEntity } from '@/shared/code/code.entity'; import { CodeServiceProviders } from '@/shared/code/code.service.spec'; import { ResetPasswordMailingService } from '@/shared/mailing/reset-password-mailing.service'; import { getMockProvider, mockRepository } from '@/utils/test-utils'; - import { ChangePasswordDto, ResetPasswordDto } from './dtos'; import { UserEntity } from './entities/user.entity'; import { InvalidPasswordException, UserNotFoundException } from './exceptions'; diff --git a/apps/api/src/domains/user/user-password.service.ts b/apps/api/src/domains/user/user-password.service.ts index 458f91fd7..8727618d3 100644 --- a/apps/api/src/domains/user/user-password.service.ts +++ b/apps/api/src/domains/user/user-password.service.ts @@ -22,7 +22,6 @@ import { Transactional } from 'typeorm-transactional'; import { CodeTypeEnum } from '@/shared/code/code-type.enum'; import { CodeService } from '@/shared/code/code.service'; import { ResetPasswordMailingService } from '@/shared/mailing/reset-password-mailing.service'; - import { ChangePasswordDto, ResetPasswordDto } from './dtos'; import { UserEntity } from './entities/user.entity'; import { InvalidPasswordException, UserNotFoundException } from './exceptions'; diff --git a/apps/api/src/domains/user/user.controller.spec.ts b/apps/api/src/domains/user/user.controller.spec.ts index de10fadd3..ff76edf6c 100644 --- a/apps/api/src/domains/user/user.controller.spec.ts +++ b/apps/api/src/domains/user/user.controller.spec.ts @@ -18,7 +18,6 @@ import { UnauthorizedException } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import { getMockProvider } from '@/utils/test-utils'; - import { UserDto } from './dtos'; import { ChangePasswordRequestDto, diff --git a/apps/api/src/domains/user/user.controller.ts b/apps/api/src/domains/user/user.controller.ts index 6fd73fdf8..87c28db7f 100644 --- a/apps/api/src/domains/user/user.controller.ts +++ b/apps/api/src/domains/user/user.controller.ts @@ -31,7 +31,6 @@ import { import { ApiBody, ApiOkResponse, ApiTags } from '@nestjs/swagger'; import { PaginationRequestDto } from '@/common/dtos'; - import { JwtAuthGuard } from '../auth/guards'; import { CurrentUser } from './decorators'; import { UserDto } from './dtos'; diff --git a/apps/api/src/domains/user/user.module.ts b/apps/api/src/domains/user/user.module.ts index 0055ef12e..b0a40c382 100644 --- a/apps/api/src/domains/user/user.module.ts +++ b/apps/api/src/domains/user/user.module.ts @@ -18,7 +18,6 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { CodeModule } from '@/shared/code/code.module'; import { MailingModule } from '@/shared/mailing/mailing.module'; - import { MemberModule } from '../project/member/member.module'; import { TenantModule } from '../tenant/tenant.module'; import { CreateUserService } from './create-user.service'; diff --git a/apps/api/src/domains/user/user.service.spec.ts b/apps/api/src/domains/user/user.service.spec.ts index da66ab8ad..9b08a4d7e 100644 --- a/apps/api/src/domains/user/user.service.spec.ts +++ b/apps/api/src/domains/user/user.service.spec.ts @@ -17,7 +17,8 @@ import { faker } from '@faker-js/faker'; import { MailerService } from '@nestjs-modules/mailer'; import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Like, Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; +import { Like } from 'typeorm'; import { SortMethodEnum } from '@/common/enums'; import { CodeServiceProviders } from '@/shared/code/code.service.spec'; @@ -28,7 +29,6 @@ import { getRandomEnumValue, mockRepository, } from '@/utils/test-utils'; - import { TenantServiceProviders } from '../tenant/tenant.service.spec'; import { FindAllUsersDto, UserDto } from './dtos'; import { SignUpMethodEnum, UserTypeEnum } from './entities/enums'; diff --git a/apps/api/src/domains/user/user.service.ts b/apps/api/src/domains/user/user.service.ts index 792acd740..a2a9f6c4d 100644 --- a/apps/api/src/domains/user/user.service.ts +++ b/apps/api/src/domains/user/user.service.ts @@ -20,13 +20,13 @@ import { In, Like, Raw, Repository } from 'typeorm'; import { Transactional } from 'typeorm-transactional'; import { UserInvitationMailingService } from '@/shared/mailing/user-invitation-mailing.service'; - import { CodeTypeEnum } from '../../shared/code/code-type.enum'; import { CodeService } from '../../shared/code/code.service'; import { TenantService } from '../tenant/tenant.service'; -import { FindAllUsersDto, InviteUserDto } from './dtos'; +import type { FindAllUsersDto } from './dtos'; +import { InviteUserDto } from './dtos'; import { UpdateUserDto } from './dtos/update-user.dto'; -import { SignUpMethodEnum } from './entities/enums'; +import type { SignUpMethodEnum } from './entities/enums'; import { UserEntity } from './entities/user.entity'; import { NotAllowedDomainException, diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index bca92b3c5..5ca15ce7b 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -16,17 +16,15 @@ import { Logger as DefaultLogger, ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; -import { - FastifyAdapter, - NestFastifyApplication, -} from '@nestjs/platform-fastify'; +import type { NestFastifyApplication } from '@nestjs/platform-fastify'; +import { FastifyAdapter } from '@nestjs/platform-fastify'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { Logger } from 'nestjs-pino'; import { initializeTransactionalContext } from 'typeorm-transactional'; import { AppModule } from './app.module'; import { HttpExceptionFilter } from './common/filters'; -import { ConfigServiceType } from './types/config-service.type'; +import type { ConfigServiceType } from './types/config-service.type'; const globalPrefix = 'api'; @@ -64,4 +62,4 @@ async function bootstrap() { DefaultLogger.log(`🚀 Application is running on: ${await app.getUrl()}`); } -bootstrap(); +void bootstrap(); diff --git a/apps/api/src/shared/code/code.entity.ts b/apps/api/src/shared/code/code.entity.ts index 18b3415a1..d9850e73d 100644 --- a/apps/api/src/shared/code/code.entity.ts +++ b/apps/api/src/shared/code/code.entity.ts @@ -16,7 +16,6 @@ import { Column, Entity } from 'typeorm'; import { CommonEntity } from '@/common/entities'; - import { CodeTypeEnum } from './code-type.enum'; @Entity('codes') diff --git a/apps/api/src/shared/code/code.module.ts b/apps/api/src/shared/code/code.module.ts index 91c55e0b7..5dab6e974 100644 --- a/apps/api/src/shared/code/code.module.ts +++ b/apps/api/src/shared/code/code.module.ts @@ -17,7 +17,6 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { MailingModule } from '@/shared/mailing/mailing.module'; - import { CodeEntity } from './code.entity'; import { CodeService } from './code.service'; diff --git a/apps/api/src/shared/code/code.service.spec.ts b/apps/api/src/shared/code/code.service.spec.ts index 999b79636..60dd4a02a 100644 --- a/apps/api/src/shared/code/code.service.spec.ts +++ b/apps/api/src/shared/code/code.service.spec.ts @@ -19,12 +19,11 @@ import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import dayjs from 'dayjs'; import MockDate from 'mockdate'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { UserDto } from '@/domains/user/dtos'; import { UserTypeEnum } from '@/domains/user/entities/enums'; import { mockRepository } from '@/utils/test-utils'; - import { CodeTypeEnum } from './code-type.enum'; import { CodeEntity } from './code.entity'; import { CodeService } from './code.service'; diff --git a/apps/api/src/shared/code/code.service.ts b/apps/api/src/shared/code/code.service.ts index 0361290e2..65eb33fcd 100644 --- a/apps/api/src/shared/code/code.service.ts +++ b/apps/api/src/shared/code/code.service.ts @@ -26,7 +26,7 @@ import { Transactional } from 'typeorm-transactional'; import { CodeTypeEnum } from './code-type.enum'; import { CodeEntity } from './code.entity'; import { SetCodeDto, VerifyCodeDto } from './dtos'; -import { SetCodeUserInvitationDataDto } from './dtos/set-code.dto'; +import type { SetCodeUserInvitationDataDto } from './dtos/set-code.dto'; export const SECONDS = 60 * 5; diff --git a/apps/api/src/shared/code/dtos/set-code-verified.dto.ts b/apps/api/src/shared/code/dtos/set-code-verified.dto.ts index f866a8608..e40472ae1 100644 --- a/apps/api/src/shared/code/dtos/set-code-verified.dto.ts +++ b/apps/api/src/shared/code/dtos/set-code-verified.dto.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { CodeTypeEnum } from '../code-type.enum'; +import type { CodeTypeEnum } from '../code-type.enum'; export class VerifyCodeDto { type: CodeTypeEnum; diff --git a/apps/api/src/shared/code/dtos/set-code.dto.ts b/apps/api/src/shared/code/dtos/set-code.dto.ts index e04b14ef4..0810141b5 100644 --- a/apps/api/src/shared/code/dtos/set-code.dto.ts +++ b/apps/api/src/shared/code/dtos/set-code.dto.ts @@ -13,10 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { UserDto } from '@/domains/user/dtos'; -import { UserTypeEnum } from '@/domains/user/entities/enums'; - -import { CodeTypeEnum } from '../code-type.enum'; +import type { UserDto } from '@/domains/user/dtos'; +import type { UserTypeEnum } from '@/domains/user/entities/enums'; +import type { CodeTypeEnum } from '../code-type.enum'; export type SetCodeDto = | SetCodeEmailVerificationDto diff --git a/apps/api/src/shared/mailing/email-verification-mailing.service.spec.ts b/apps/api/src/shared/mailing/email-verification-mailing.service.spec.ts index cef08c1e3..fbcf96d2c 100644 --- a/apps/api/src/shared/mailing/email-verification-mailing.service.spec.ts +++ b/apps/api/src/shared/mailing/email-verification-mailing.service.spec.ts @@ -18,7 +18,6 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Test } from '@nestjs/testing'; import { getMockProvider } from '@/utils/test-utils'; - import { EmailVerificationMailingService } from './email-verification-mailing.service'; describe('first', () => { diff --git a/apps/api/src/shared/mailing/email-verification-mailing.service.ts b/apps/api/src/shared/mailing/email-verification-mailing.service.ts index f1dc6b7e9..fcd83cccc 100644 --- a/apps/api/src/shared/mailing/email-verification-mailing.service.ts +++ b/apps/api/src/shared/mailing/email-verification-mailing.service.ts @@ -16,7 +16,7 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Injectable } from '@nestjs/common'; -import { SendMailDto } from './send-mail.dto'; +import type { SendMailDto } from './send-mail.dto'; @Injectable() export class EmailVerificationMailingService { diff --git a/apps/api/src/shared/mailing/mailing.module.ts b/apps/api/src/shared/mailing/mailing.module.ts index 236b0b39b..e4b2c9b43 100644 --- a/apps/api/src/shared/mailing/mailing.module.ts +++ b/apps/api/src/shared/mailing/mailing.module.ts @@ -16,7 +16,6 @@ import { Module } from '@nestjs/common'; import { MailerConfigModule } from '@/configs/modules'; - import { EmailVerificationMailingService } from './email-verification-mailing.service'; import { ResetPasswordMailingService } from './reset-password-mailing.service'; import { UserInvitationMailingService } from './user-invitation-mailing.service'; diff --git a/apps/api/src/shared/mailing/reset-password-mailing.service.spec.ts b/apps/api/src/shared/mailing/reset-password-mailing.service.spec.ts index 1bf1c3c3c..d03c69de2 100644 --- a/apps/api/src/shared/mailing/reset-password-mailing.service.spec.ts +++ b/apps/api/src/shared/mailing/reset-password-mailing.service.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { MailerService } from '@nestjs-modules/mailer'; import { Test } from '@nestjs/testing'; -import { TestConfig, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, TestConfig } from '@/utils/test-utils'; import { ResetPasswordMailingService } from './reset-password-mailing.service'; describe('ResetPasswordMailingService', () => { diff --git a/apps/api/src/shared/mailing/reset-password-mailing.service.ts b/apps/api/src/shared/mailing/reset-password-mailing.service.ts index 7500152df..bc46c0acf 100644 --- a/apps/api/src/shared/mailing/reset-password-mailing.service.ts +++ b/apps/api/src/shared/mailing/reset-password-mailing.service.ts @@ -17,9 +17,8 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { ConfigServiceType } from '@/types/config-service.type'; - -import { SendMailDto } from './send-mail.dto'; +import type { ConfigServiceType } from '@/types/config-service.type'; +import type { SendMailDto } from './send-mail.dto'; @Injectable() export class ResetPasswordMailingService { diff --git a/apps/api/src/shared/mailing/user-invitation-mailing.service.spec.ts b/apps/api/src/shared/mailing/user-invitation-mailing.service.spec.ts index 3992bd7db..f8038de74 100644 --- a/apps/api/src/shared/mailing/user-invitation-mailing.service.spec.ts +++ b/apps/api/src/shared/mailing/user-invitation-mailing.service.spec.ts @@ -17,8 +17,7 @@ import { faker } from '@faker-js/faker'; import { MailerService } from '@nestjs-modules/mailer'; import { Test } from '@nestjs/testing'; -import { TestConfig, getMockProvider } from '@/utils/test-utils'; - +import { getMockProvider, TestConfig } from '@/utils/test-utils'; import { UserInvitationMailingService } from './user-invitation-mailing.service'; describe('first', () => { diff --git a/apps/api/src/shared/mailing/user-invitation-mailing.service.ts b/apps/api/src/shared/mailing/user-invitation-mailing.service.ts index d40e36c20..1bc22d541 100644 --- a/apps/api/src/shared/mailing/user-invitation-mailing.service.ts +++ b/apps/api/src/shared/mailing/user-invitation-mailing.service.ts @@ -17,9 +17,8 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { ConfigServiceType } from '@/types/config-service.type'; - -import { SendMailDto } from './send-mail.dto'; +import type { ConfigServiceType } from '@/types/config-service.type'; +import type { SendMailDto } from './send-mail.dto'; @Injectable() export class UserInvitationMailingService { diff --git a/apps/api/src/types/cls-service.type.ts b/apps/api/src/types/cls-service.type.ts index 7eddc0e80..45a6f1bee 100644 --- a/apps/api/src/types/cls-service.type.ts +++ b/apps/api/src/types/cls-service.type.ts @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { ClsStore } from 'nestjs-cls'; +import type { ClsStore } from 'nestjs-cls'; export interface ClsServiceType extends ClsStore { userId?: number; diff --git a/apps/api/src/types/config-service.type.ts b/apps/api/src/types/config-service.type.ts index d06874f87..0b7f34703 100644 --- a/apps/api/src/types/config-service.type.ts +++ b/apps/api/src/types/config-service.type.ts @@ -13,13 +13,13 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { ConfigType } from '@nestjs/config'; +import type { ConfigType } from '@nestjs/config'; -import { appConfig } from '@/configs/app.config'; -import { jwtConfig } from '@/configs/jwt.config'; -import { mysqlConfig } from '@/configs/mysql.config'; -import { opensearchConfig } from '@/configs/opensearch.config'; -import { smtpConfig } from '@/configs/smtp.config'; +import type { appConfig } from '@/configs/app.config'; +import type { jwtConfig } from '@/configs/jwt.config'; +import type { mysqlConfig } from '@/configs/mysql.config'; +import type { opensearchConfig } from '@/configs/opensearch.config'; +import type { smtpConfig } from '@/configs/smtp.config'; export type ConfigServiceType = { app: ConfigType; diff --git a/apps/api/src/utils/test-util-fixture.ts b/apps/api/src/utils/test-util-fixture.ts index c039e7edd..2859bf8a3 100644 --- a/apps/api/src/utils/test-util-fixture.ts +++ b/apps/api/src/utils/test-util-fixture.ts @@ -21,9 +21,9 @@ import { FieldTypeEnum, isSelectFieldFormat, } from '@/common/enums'; -import { ReplaceFieldDto } from '@/domains/channel/field/dtos'; -import { CreateFieldDto } from '@/domains/channel/field/dtos/create-field.dto'; -import { CreateIssueDto } from '@/domains/project/issue/dtos'; +import type { ReplaceFieldDto } from '@/domains/channel/field/dtos'; +import type { CreateFieldDto } from '@/domains/channel/field/dtos/create-field.dto'; +import type { CreateIssueDto } from '@/domains/project/issue/dtos'; export const createFieldEntity = (input: Partial) => { const format = input?.format ?? getRandomEnumValue(FieldFormatEnum); diff --git a/apps/api/src/utils/test-utils.ts b/apps/api/src/utils/test-utils.ts index 9a36a2a20..ad0b13bd0 100644 --- a/apps/api/src/utils/test-utils.ts +++ b/apps/api/src/utils/test-utils.ts @@ -14,13 +14,13 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { InjectionToken, Provider } from '@nestjs/common'; +import type { InjectionToken, Provider } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { initializeTransactionalContext } from 'typeorm-transactional'; import { smtpConfig, smtpConfigSchema } from '@/configs/smtp.config'; -import { AuthService } from '@/domains/auth/auth.service'; +import type { AuthService } from '@/domains/auth/auth.service'; import { UserDto } from '@/domains/user/dtos'; import { UserStateEnum } from '@/domains/user/entities/enums'; import { UserEntity } from '@/domains/user/entities/user.entity'; diff --git a/apps/api/test/auth.e2e-spec.ts b/apps/api/test/auth.e2e-spec.ts index 9194cf7f5..895d79e63 100644 --- a/apps/api/test/auth.e2e-spec.ts +++ b/apps/api/test/auth.e2e-spec.ts @@ -14,12 +14,14 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getDataSourceToken } from '@nestjs/typeorm'; import request from 'supertest'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { @@ -29,7 +31,7 @@ import { EmailVerificationMailingRequestDto, InvitationUserSignUpRequestDto, } from '@/domains/auth/dtos/requests'; -import { RoleEntity } from '@/domains/project/role/role.entity'; +import type { RoleEntity } from '@/domains/project/role/role.entity'; import { TenantEntity } from '@/domains/tenant/tenant.entity'; import { UserStateEnum, UserTypeEnum } from '@/domains/user/entities/enums'; import { UserEntity } from '@/domains/user/entities/user.entity'; diff --git a/apps/api/test/feedback/channel.e2e-spec.ts b/apps/api/test/feedback/channel.e2e-spec.ts index 1607d02f0..57427ab04 100644 --- a/apps/api/test/feedback/channel.e2e-spec.ts +++ b/apps/api/test/feedback/channel.e2e-spec.ts @@ -14,12 +14,14 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getDataSourceToken } from '@nestjs/typeorm'; import { Client } from '@opensearch-project/opensearch/.'; import request from 'supertest'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { @@ -39,7 +41,7 @@ import { FIELD_TYPES_TO_MAPPING_TYPES } from '@/domains/channel/field/field.mysq import { OptionEntity } from '@/domains/channel/option/option.entity'; import { ProjectEntity } from '@/domains/project/project/project.entity'; import { createFieldDto, optionSort } from '@/utils/test-util-fixture'; -import { DEFAULT_FIELD_COUNT, clearEntities } from '@/utils/test-utils'; +import { clearEntities, DEFAULT_FIELD_COUNT } from '@/utils/test-utils'; describe('AppController (e2e)', () => { let app: INestApplication; diff --git a/apps/api/test/feedback/feedback.e2e-spec.ts b/apps/api/test/feedback/feedback.e2e-spec.ts index 7f011b1b2..9e9ce5eef 100644 --- a/apps/api/test/feedback/feedback.e2e-spec.ts +++ b/apps/api/test/feedback/feedback.e2e-spec.ts @@ -14,12 +14,14 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Client } from '@opensearch-project/opensearch/.'; import request from 'supertest'; -import { Repository } from 'typeorm'; +import type { Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { FieldFormatEnum } from '@/common/enums'; diff --git a/apps/api/test/feedback/project.e2e-spec.ts b/apps/api/test/feedback/project.e2e-spec.ts index d59cdaa83..9cebec670 100644 --- a/apps/api/test/feedback/project.e2e-spec.ts +++ b/apps/api/test/feedback/project.e2e-spec.ts @@ -14,11 +14,13 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getDataSourceToken } from '@nestjs/typeorm'; import request from 'supertest'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { HttpExceptionFilter } from '@/common/filters'; diff --git a/apps/api/test/role.e2e-spec.ts b/apps/api/test/role.e2e-spec.ts index 755887bb2..ebaabd370 100644 --- a/apps/api/test/role.e2e-spec.ts +++ b/apps/api/test/role.e2e-spec.ts @@ -14,11 +14,13 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getDataSourceToken } from '@nestjs/typeorm'; import request from 'supertest'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { AuthService } from '@/domains/auth/auth.service'; diff --git a/apps/api/test/tenant.e2e-spec.ts b/apps/api/test/tenant.e2e-spec.ts index 0cf38491a..623a21a3d 100644 --- a/apps/api/test/tenant.e2e-spec.ts +++ b/apps/api/test/tenant.e2e-spec.ts @@ -14,11 +14,13 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getDataSourceToken } from '@nestjs/typeorm'; import request from 'supertest'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { AuthService } from '@/domains/auth/auth.service'; diff --git a/apps/api/test/user.e2e-spec.ts b/apps/api/test/user.e2e-spec.ts index 411700647..50f74f2a9 100644 --- a/apps/api/test/user.e2e-spec.ts +++ b/apps/api/test/user.e2e-spec.ts @@ -14,12 +14,14 @@ * under the License. */ import { faker } from '@faker-js/faker'; -import { INestApplication, ValidationPipe } from '@nestjs/common'; -import { Test, TestingModule } from '@nestjs/testing'; +import type { INestApplication } from '@nestjs/common'; +import { ValidationPipe } from '@nestjs/common'; +import type { TestingModule } from '@nestjs/testing'; +import { Test } from '@nestjs/testing'; import { getDataSourceToken } from '@nestjs/typeorm'; import dayjs from 'dayjs'; import request from 'supertest'; -import { DataSource, Repository } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; import { AppModule } from '@/app.module'; import { AuthService } from '@/domains/auth/auth.service'; diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index 1c1aff619..713860307 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -4,18 +4,9 @@ "outDir": "./dist", "baseUrl": "./", "paths": { - "@/*": [ - "./src/*" - ] - }, - "sourceMap": true + "@/*": ["./src/*"] + } }, - "include": [ - "src", - "test" - ], - "exclude": [ - "node_modules", - "dist", - ] -} \ No newline at end of file + "include": ["src", "test"], + "exclude": ["node_modules", "dist"] +} diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js deleted file mode 100644 index bb2cfaf6a..000000000 --- a/apps/web/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - root: true, - extends: ['next', 'ufb'], - ignorePatterns: ['.next', '.turbo', 'api.type.ts'], - rules: { - '@next/next/no-html-link-for-pages': 'off', - 'react-hooks/exhaustive-deps': 'off', - '@typescript-eslint/no-empty-function': 'off', - }, -}; diff --git a/apps/web/jest.config.js b/apps/web/jest.config.mjs similarity index 79% rename from apps/web/jest.config.js rename to apps/web/jest.config.mjs index c29878ae9..067032bbb 100644 --- a/apps/web/jest.config.js +++ b/apps/web/jest.config.mjs @@ -1,4 +1,4 @@ -const nextJest = require('next/jest'); +import nextJest from 'next/jest.js'; const createJestConfig = nextJest({ // Provide the path to your Next.js app to load next.config.js and .env files in your test environment @@ -8,8 +8,6 @@ const createJestConfig = nextJest({ // Add any custom config to be passed to Jest /** @type {import('jest').Config} */ const jestConfig = { - // Add more setup options before each test is run - setupFilesAfterEnv: ['/jest.setup.js'], // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work moduleDirectories: ['node_modules', '/'], testEnvironment: 'jest-environment-jsdom', @@ -23,4 +21,4 @@ const jestConfig = { }; // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async -module.exports = createJestConfig(jestConfig); +export default createJestConfig(jestConfig); diff --git a/apps/web/jest.setup.js b/apps/web/jest.setup.js deleted file mode 100644 index 060ffd261..000000000 --- a/apps/web/jest.setup.js +++ /dev/null @@ -1,20 +0,0 @@ -// Optional: configure or set up a testing framework before each test. -// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js` - -// Used for __tests__/testing-library.js -// Learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom/extend-expect'; - -jest.mock('next/router', () => require('next-router-mock')); -jest.mock('next/dist/client/router', () => require('next-router-mock')); - -jest.mock('next-i18next', () => ({ - // this mock makes sure any components using the translate hook can use it without a warning being shown - useTranslation: () => ({ t: (str) => str }), -})); -delete window.ResizeObserver; -window.ResizeObserver = jest.fn().mockImplementation(() => ({ - observe: jest.fn(), - unobserve: jest.fn(), - disconnect: jest.fn(), -})); diff --git a/apps/web/next-i18next.config.js b/apps/web/next-i18next.config.js index a37c1ff4f..9dcfda2fd 100644 --- a/apps/web/next-i18next.config.js +++ b/apps/web/next-i18next.config.js @@ -1,18 +1,3 @@ -/** - * Copyright 2023 LINE Corporation - * - * LINE Corporation licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ module.exports = { i18n: { defaultLocale: 'default', diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs new file mode 100644 index 000000000..1ea4eb881 --- /dev/null +++ b/apps/web/next.config.mjs @@ -0,0 +1,47 @@ +import './src/env.mjs'; + +import path from 'path'; +import { fileURLToPath } from 'url'; + +import i18nConfig from './next-i18next.config.js'; + +const __dirname = fileURLToPath(new URL('.', import.meta.url)); + +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: false, + swcMinify: true, + i18n: i18nConfig.i18n, + output: 'standalone', + experimental: { outputFileTracingRoot: path.join(__dirname, '../../') }, + eslint: { ignoreDuringBuilds: true }, + transpilePackages: ['@ufb/ui'], + compiler: { removeConsole: process.env.NODE_ENV === 'production' }, + webpack(config) { + const fileLoaderRule = config.module.rules.find((rule) => + rule.test?.test?.('.svg'), + ); + + config.module.rules.push( + { ...fileLoaderRule, test: /\.svg$/i, resourceQuery: /url/ }, + { + test: /\.svg$/i, + issuer: /\.[jt]sx?$/, + resourceQuery: { not: /url/ }, + use: [ + { + loader: '@svgr/webpack', + options: { icon: true, exportType: 'named' }, + }, + ], + }, + ); + + // Modify the file loader rule to ignore *.svg, since we have it handled now. + fileLoaderRule.exclude = /\.svg$/i; + + return config; + }, +}; + +export default nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json index f2d0cb241..2d4d33d48 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -3,14 +3,29 @@ "version": "0.0.0", "private": true, "scripts": { - "dev": "next dev", "build": "next build", + "clean": "git clean -xdf .next .turbo node_modules", + "dev": "next dev", + "format": "prettier --check \"./src/**/*.{js,cjs,mjs,ts,tsx,md,json}\"", + "generate-api-type": "openapi-typescript http://0.0.0.0:4000/docs-json --output src/types/api.type.ts", + "lint": "SKIP_ENV_VALIDATION=1 next lint", "start": "next start", - "lint": "next lint", "test": "jest --passWithNoTests", - "test:dev": "jest --watch --passWithNoTests", "test:ci": "jest --ci --passWithNoTests", - "generate-api-type": "openapi-typescript http://0.0.0.0:4000/docs-json --output src/types/api.type.ts" + "test:dev": "jest --watch --passWithNoTests", + "typecheck": "tsc --noEmit" + }, + "prettier": "@ufb/prettier-config", + "eslintConfig": { + "extends": [ + "@ufb/eslint-config/base", + "@ufb/eslint-config/react", + "@ufb/eslint-config/nextjs" + ], + "ignorePatterns": [ + "api.type.ts" + ], + "root": true }, "dependencies": { "@emotion/react": "^11.11.0", @@ -21,10 +36,11 @@ "@headlessui/tailwindcss": "^0.1.3", "@hookform/resolvers": "^2.9.11", "@mui/base": "^5.0.0-beta.4", + "@t3-oss/env-nextjs": "^0.7.0", "@tanstack/react-query": "^4.29.12", "@tanstack/react-table": "^8.10.0", - "@ufb/tailwind": "*", - "@ufb/ui": "*", + "@ufb/tailwind": "^0.1.0", + "@ufb/ui": "^0.1.0", "axios": "^1.4.0", "axios-auth-refresh": "^3.3.6", "cookies-next": "^2.1.2", @@ -58,31 +74,29 @@ "devDependencies": { "@babel/core": "^7.22.1", "@rollup/plugin-commonjs": "^24.1.0", + "@svgr/webpack": "^8.1.0", "@swc/core": "^1.3.62", "@swc/jest": "^0.2.26", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", "@types/jest": "^29.5.2", - "@types/node": "^17.0.45", + "@types/node": "18.11.18", "@types/react": "^18.2.8", "@types/react-beautiful-dnd": "^13.1.4", "@types/react-datepicker": "^4.11.2", "@types/react-dom": "^18.2.4", - "@typescript-eslint/parser": "^5.59.9", + "@ufb/eslint-config": "^0.1.0", + "@ufb/prettier-config": "^0.1.0", "@ufb/tsconfig": "*", "autoprefixer": "^10.4.14", - "eslint": "^8.42.0", - "eslint-config-next": "^13.4.4", - "eslint-config-ufb": "*", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-testing-library": "^5.11.0", + "eslint": "^8.50.0", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "openapi-typescript": "^6.2.6", "postcss": "^8.4.24", "tailwindcss": "^3.3.2", "ts-toolbelt": "^9.6.0", - "typescript": "^4.9.5" + "typescript": "^5.2.2" } } diff --git a/apps/web/src/components/cards/ChannelCard/ChannelCard.tsx b/apps/web/src/components/cards/ChannelCard/ChannelCard.tsx index 57cac7ff2..26583c635 100644 --- a/apps/web/src/components/cards/ChannelCard/ChannelCard.tsx +++ b/apps/web/src/components/cards/ChannelCard/ChannelCard.tsx @@ -13,14 +13,15 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon, IconNameType } from '@ufb/ui'; import { useMemo } from 'react'; -import { ColorType } from '@/types/color.type'; +import type { IconNameType } from '@ufb/ui'; +import { Icon } from '@ufb/ui'; + +import type { ColorType } from '@/types/color.type'; interface IProps extends React.PropsWithChildren { isChecked?: boolean; - onClick?: () => void; value?: React.ReactNode; rightChildren?: React.ReactNode; color: ColorType; @@ -29,10 +30,7 @@ interface IProps extends React.PropsWithChildren { } const ChannelCard: React.FC = (props) => { - const { isChecked, onClick, value, rightChildren, color, iconName, name } = - props; - - const isBtn = useMemo(() => typeof onClick !== 'undefined', [isChecked]); + const { isChecked, value, rightChildren, color, iconName, name } = props; const { bg, icon } = useMemo(() => { switch (color) { @@ -48,16 +46,12 @@ const ChannelCard: React.FC = (props) => { return (
diff --git a/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx b/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx index 658b8e4b4..eb8dfc763 100644 --- a/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx +++ b/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Header, flexRender } from '@tanstack/react-table'; +import type { Header } from '@tanstack/react-table'; +import { flexRender } from '@tanstack/react-table'; import { useTranslation } from 'next-i18next'; import DownloadButton from '@/containers/tables/FeedbackTable/DownloadButton'; @@ -52,7 +53,7 @@ const CheckedTableHead: React.FC = (props) => { flexRender(header?.column.columnDef.header, header.getContext())} -
+
{t('text.select-count', { count })} @@ -62,7 +63,7 @@ const CheckedTableHead: React.FC = (props) => { > {t('button.select-cancel')} -
+
{download && ( <> = (props) => { count={download.ids.length} isHead /> -
+
)} diff --git a/apps/web/src/components/etc/Dialog/Dialog_back.tsx b/apps/web/src/components/etc/Dialog/Dialog_back.tsx index 5ebbaa8fe..e29ff37f5 100644 --- a/apps/web/src/components/etc/Dialog/Dialog_back.tsx +++ b/apps/web/src/components/etc/Dialog/Dialog_back.tsx @@ -13,6 +13,7 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { useId } from 'react'; import { FloatingFocusManager, FloatingOverlay, @@ -23,10 +24,11 @@ import { useInteractions, useRole, } from '@floating-ui/react'; -import { IIconProps, Icon } from '@ufb/ui'; -import { useId } from 'react'; import { useTranslation } from 'react-i18next'; +import type { IIconProps } from '@ufb/ui'; +import { Icon } from '@ufb/ui'; + export interface IDialogProps extends React.PropsWithChildren { title: string; description?: string; @@ -80,13 +82,13 @@ const Dialog: React.FC = (props) => { aria-labelledby={labelId} aria-describedby={descriptionId} {...getFloatingProps()} - className="bg-primary rounded p-5 min-w-[480px] border" + className="bg-primary min-w-[480px] rounded border p-5" >

{title}

{icon && ( -
+
)} diff --git a/apps/web/src/components/etc/Dialog/PopoverModalContent.tsx b/apps/web/src/components/etc/Dialog/PopoverModalContent.tsx index cbf01cdd3..904bf48b7 100644 --- a/apps/web/src/components/etc/Dialog/PopoverModalContent.tsx +++ b/apps/web/src/components/etc/Dialog/PopoverModalContent.tsx @@ -13,14 +13,15 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { useTranslation } from 'react-i18next'; + +import type { IIconProps } from '@ufb/ui'; import { - IIconProps, Icon, PopoverContent, PopoverHeading, usePopoverContext, } from '@ufb/ui'; -import { useTranslation } from 'react-i18next'; export interface IDialogProps extends React.PropsWithChildren { title: string; @@ -45,7 +46,7 @@ const PopoverModalContent: React.FC = (props) => { {title}
{icon && ( -
+
)} diff --git a/apps/web/src/components/etc/IssueCircle/IssueCircle.tsx b/apps/web/src/components/etc/IssueCircle/IssueCircle.tsx index 98163d846..d7b7b7dd6 100644 --- a/apps/web/src/components/etc/IssueCircle/IssueCircle.tsx +++ b/apps/web/src/components/etc/IssueCircle/IssueCircle.tsx @@ -46,7 +46,7 @@ const IssueCircle: React.FC = ({ issueKey }) => { return (
diff --git a/apps/web/src/components/etc/PopoverModalContent/PopoverModalContent.tsx b/apps/web/src/components/etc/PopoverModalContent/PopoverModalContent.tsx index ad12b1879..709f72a02 100644 --- a/apps/web/src/components/etc/PopoverModalContent/PopoverModalContent.tsx +++ b/apps/web/src/components/etc/PopoverModalContent/PopoverModalContent.tsx @@ -13,14 +13,15 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { useTranslation } from 'react-i18next'; + +import type { IIconProps } from '@ufb/ui'; import { - IIconProps, Icon, PopoverContent, PopoverHeading, usePopoverContext, } from '@ufb/ui'; -import { useTranslation } from 'react-i18next'; export interface IDialogProps extends React.PropsWithChildren { title: string; @@ -45,7 +46,7 @@ const PopoverModalContent: React.FC = (props) => { {title}
{icon && ( -
+
)} diff --git a/apps/web/src/components/etc/Popper/Popper.tsx b/apps/web/src/components/etc/Popper/Popper.tsx index c22f1a2bd..939ec0de7 100644 --- a/apps/web/src/components/etc/Popper/Popper.tsx +++ b/apps/web/src/components/etc/Popper/Popper.tsx @@ -13,8 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Popper as MUIPopper, PopperPlacementType } from '@mui/base'; -import React, { Dispatch, SetStateAction, useRef } from 'react'; +import type { Dispatch, SetStateAction } from 'react'; +import React, { useRef } from 'react'; +import type { PopperPlacementType } from '@mui/base'; +import { Popper as MUIPopper } from '@mui/base'; import { useClickAway } from 'react-use'; interface IProps { @@ -50,7 +52,7 @@ const Popper: React.FC = (props) => { placement: placement ?? 'bottom-end', modifiers: [{ name: 'offset', options: { offset: [0, offset] } }], }} - className="border rounded bg-primary z-20" + className="bg-primary z-20 rounded border" ref={containerRef} > {children} diff --git a/apps/web/src/components/etc/SelectBox/SelectBox.tsx b/apps/web/src/components/etc/SelectBox/SelectBox.tsx index 2ca191966..aa58a067d 100644 --- a/apps/web/src/components/etc/SelectBox/SelectBox.tsx +++ b/apps/web/src/components/etc/SelectBox/SelectBox.tsx @@ -13,8 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ +import type { Props } from 'react-select'; +import ReactSelect from 'react-select'; + import { Badge, Icon } from '@ufb/ui'; -import ReactSelect, { Props } from 'react-select'; export type SelectOptionType = | { id?: number; key: any; name: string; [key: string]: any } @@ -68,7 +70,7 @@ function SelectBox(
diff --git a/apps/web/src/components/etc/SelectBox/SelectBoxCreatable.tsx b/apps/web/src/components/etc/SelectBox/SelectBoxCreatable.tsx index d407df5b4..b5d06a3eb 100644 --- a/apps/web/src/components/etc/SelectBox/SelectBoxCreatable.tsx +++ b/apps/web/src/components/etc/SelectBox/SelectBoxCreatable.tsx @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ +import type { GroupBase } from 'react-select'; +import type { CreatableProps as Props } from 'react-select/creatable'; +import ReactSelect from 'react-select/creatable'; + import { Badge, Icon } from '@ufb/ui'; -import { GroupBase } from 'react-select'; -import ReactSelect, { CreatableProps as Props } from 'react-select/creatable'; export type SelectOptionType = | { id?: number; key: any; name: string; [key: string]: any } @@ -68,7 +70,7 @@ function SelectBoxCreatable(
diff --git a/apps/web/src/components/etc/SelectBoxWithIcon/SelectBoxWithIcon.tsx b/apps/web/src/components/etc/SelectBoxWithIcon/SelectBoxWithIcon.tsx index 39937e303..746ef9dc5 100644 --- a/apps/web/src/components/etc/SelectBoxWithIcon/SelectBoxWithIcon.tsx +++ b/apps/web/src/components/etc/SelectBoxWithIcon/SelectBoxWithIcon.tsx @@ -15,10 +15,8 @@ */ import { components } from 'react-select'; -import SelectBox, { - ISelectBoxProps, - SelectOptionType, -} from '../SelectBox/SelectBox'; +import type { ISelectBoxProps, SelectOptionType } from '../SelectBox/SelectBox'; +import SelectBox from '../SelectBox/SelectBox'; interface IProps extends ISelectBoxProps { SingleValue?: { diff --git a/apps/web/src/components/etc/ShareButton/ShareButton.tsx b/apps/web/src/components/etc/ShareButton/ShareButton.tsx index a530c66b9..7447f1969 100644 --- a/apps/web/src/components/etc/ShareButton/ShareButton.tsx +++ b/apps/web/src/components/etc/ShareButton/ShareButton.tsx @@ -13,10 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon, toast } from '@ufb/ui'; -import { MouseEventHandler } from 'react'; +import type { MouseEventHandler } from 'react'; import { useTranslation } from 'react-i18next'; +import { Icon, toast } from '@ufb/ui'; + interface IProps { pathname: string; } diff --git a/apps/web/src/components/etc/TableCheckbox/TableCheckbox.tsx b/apps/web/src/components/etc/TableCheckbox/TableCheckbox.tsx index f5bc9af30..d2d607b5b 100644 --- a/apps/web/src/components/etc/TableCheckbox/TableCheckbox.tsx +++ b/apps/web/src/components/etc/TableCheckbox/TableCheckbox.tsx @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { HTMLProps, useEffect, useRef } from 'react'; +import type { HTMLProps } from 'react'; +import { useEffect, useRef } from 'react'; interface IProps extends HTMLProps { indeterminate?: boolean; diff --git a/apps/web/src/components/etc/TableLoadingRow/TableLoadingRow.tsx b/apps/web/src/components/etc/TableLoadingRow/TableLoadingRow.tsx index 692aee3e8..c95e075c0 100644 --- a/apps/web/src/components/etc/TableLoadingRow/TableLoadingRow.tsx +++ b/apps/web/src/components/etc/TableLoadingRow/TableLoadingRow.tsx @@ -21,8 +21,8 @@ const TableLoadingRow: React.FC = ({ colSpan }) => { return ( -
-
+
+
diff --git a/apps/web/src/components/etc/TablePagination/TablePagination.tsx b/apps/web/src/components/etc/TablePagination/TablePagination.tsx index 2ff7962b8..ac8a2fb19 100644 --- a/apps/web/src/components/etc/TablePagination/TablePagination.tsx +++ b/apps/web/src/components/etc/TablePagination/TablePagination.tsx @@ -13,9 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon } from '@ufb/ui'; import { useTranslation } from 'next-i18next'; +import { Icon } from '@ufb/ui'; + interface IProps extends React.PropsWithChildren { limit?: number; setLimit?: (limit: number) => void; diff --git a/apps/web/src/components/etc/TableResizer/TableResizer.tsx b/apps/web/src/components/etc/TableResizer/TableResizer.tsx index 01c028489..c0eea578b 100644 --- a/apps/web/src/components/etc/TableResizer/TableResizer.tsx +++ b/apps/web/src/components/etc/TableResizer/TableResizer.tsx @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Header, Table } from '@tanstack/react-table'; +import type { Header, Table } from '@tanstack/react-table'; + import { Icon } from '@ufb/ui'; interface IProps { @@ -40,7 +41,7 @@ const TableResizer: React.FC = ({ table, header }) => { >
diff --git a/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx b/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx index a15d827e8..08f60bea5 100644 --- a/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx +++ b/apps/web/src/components/etc/TableSearchInput/TableSearchInput.tsx @@ -13,21 +13,21 @@ * License for the specific language governing permissions and limitations * under the License. */ +import { useEffect, useMemo, useRef, useState } from 'react'; import { Combobox } from '@headlessui/react'; -import { Badge, Icon } from '@ufb/ui'; import { useTranslation } from 'next-i18next'; -import { useEffect, useMemo, useRef, useState } from 'react'; -import { PrimitiveFieldFormatEnumType } from '@/types/field.type'; -import { removeEmptyValueInObject } from '@/utils/remove-empty-value-in-object'; +import { Badge, Icon } from '@ufb/ui'; -import TableSearchInputPopover from './TableSearchInputPopover'; +import type { PrimitiveFieldFormatEnumType } from '@/types/field.type'; +import { removeEmptyValueInObject } from '@/utils/remove-empty-value-in-object'; import { objToQuery, objToStr, strToObj, strValueToObj, } from './table-search-input.service'; +import TableSearchInputPopover from './TableSearchInputPopover'; export type SearchItemType = { key: string; @@ -134,7 +134,7 @@ const TableSearchInput: React.FC = ({ return ( = ({ /> setInputValue(e.currentTarget.value)} value={inputValue} displayValue={() => inputValue} @@ -161,7 +161,7 @@ const TableSearchInput: React.FC = ({ /> {inputValue.length > 0 && ( )} - + {!editingName ? searchItems .filter( @@ -210,7 +210,7 @@ const TableSearchInput: React.FC = ({ {isOpenPopover && (
= ({ - ['p-3 cursor-pointer', active ? 'bg-secondary' : 'bg-primary'].join(' ') + ['cursor-pointer p-3', active ? 'bg-secondary' : 'bg-primary'].join(' ') } value={{ [key]: strValueToObj(editingValue, searchItem) }} > diff --git a/apps/web/src/components/etc/TableSearchInput/TableSearchInputPopover.tsx b/apps/web/src/components/etc/TableSearchInput/TableSearchInputPopover.tsx index 5aeacbb73..98d8f94af 100644 --- a/apps/web/src/components/etc/TableSearchInput/TableSearchInputPopover.tsx +++ b/apps/web/src/components/etc/TableSearchInput/TableSearchInputPopover.tsx @@ -13,16 +13,16 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon } from '@ufb/ui'; +import { useCallback, useState } from 'react'; import produce from 'immer'; import { useTranslation } from 'next-i18next'; -import { useCallback, useState } from 'react'; -import { DateRangeType } from '@/types/date-range.type'; +import { Icon } from '@ufb/ui'; +import type { DateRangeType } from '@/types/date-range.type'; import DateRangePicker from '../DateRangePicker'; import SelectBox from '../SelectBox'; -import { SearchItemType } from './TableSearchInput'; +import type { SearchItemType } from './TableSearchInput'; const BooleanOptions = [ { name: 'True', key: true }, @@ -84,7 +84,7 @@ const TableSearchInputPopover: React.FC = (props) => { return (
-
+

{t('text.search-filter')}

{columns.map((item) => ( -
+
{item.format === 'date' && (

{item.name}

diff --git a/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts b/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts index 006119e2a..2282778b2 100644 --- a/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts +++ b/apps/web/src/components/etc/TableSearchInput/table-search-input.service.ts @@ -16,8 +16,7 @@ import dayjs from 'dayjs'; import { DATE_FORMAT } from '@/constants/dayjs-format'; - -import { SearchItemType } from './TableSearchInput'; +import type { SearchItemType } from './TableSearchInput'; export const strToObj = (input: string, searchItems: SearchItemType[]) => { const splitValues = input.split(','); @@ -30,6 +29,7 @@ export const strToObj = (input: string, searchItems: SearchItemType[]) => { for (const mergedValue of mergedValues) { const [name, value] = mergedValue.split(':').map((v) => v.trim()); + if (!name || !value) continue; const column = searchItems.find((column) => column.name === name); @@ -47,11 +47,12 @@ export const strValueToObj = (value: string, searchItems: SearchItemType) => { switch (searchItems.format) { case 'boolean': return strToBoolean(value); - case 'date': + case 'date': { const [gte, lt] = value .split('~') .map((v) => dayjs(v, { format: DATE_FORMAT }).toDate()); return { gte, lt }; + } case 'issue': case 'issue_status': case 'select': @@ -88,9 +89,8 @@ export const objToStr = ( } case 'issue': if (Array.isArray(value)) { - const issueName = column.options?.find( - (v) => v.id === value[0], - )?.name; + const issueName = column.options?.find((v) => v.id === value[0]) + ?.name; return `${name}:${issueName}`; } else if (value?.name) { const issueName = value?.name; @@ -147,29 +147,32 @@ export const objToQuery = ( }; } break; - case 'issue_status': + case 'issue_status': { const statusId = value?.id ?? column.options?.find((v) => v.name === value)?.key; result[key] = statusId; break; - case 'issue': + } + case 'issue': { const issueId = value?.id ?? column.options?.find((v) => v.name === value)?.id; result[key] = [issueId]; break; - case 'multiSelect': + } + case 'multiSelect': { const optionKey1 = value?.key ?? column.options?.find((v) => v.name === value)?.key; if (!optionKey1) break; result[key] = [optionKey1]; break; - case 'select': + } + case 'select': { const optionKey2 = value?.key ?? column.options?.find((v) => v.name === value)?.key; if (!optionKey2) break; result[key] = optionKey2; break; - + } default: result[key] = value; break; diff --git a/apps/web/src/components/etc/TableSortIcon/TableSortIcon.tsx b/apps/web/src/components/etc/TableSortIcon/TableSortIcon.tsx index 2f5242b26..0bdbf87df 100644 --- a/apps/web/src/components/etc/TableSortIcon/TableSortIcon.tsx +++ b/apps/web/src/components/etc/TableSortIcon/TableSortIcon.tsx @@ -13,7 +13,8 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Column } from '@tanstack/react-table'; +import type { Column } from '@tanstack/react-table'; + import { Icon } from '@ufb/ui'; interface IProps extends React.PropsWithChildren { diff --git a/apps/web/src/components/etc/Tooltip/Tooltip.tsx b/apps/web/src/components/etc/Tooltip/Tooltip.tsx deleted file mode 100644 index 030d4deba..000000000 --- a/apps/web/src/components/etc/Tooltip/Tooltip.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright 2023 LINE Corporation - * - * LINE Corporation licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -import { Icon, Popover, PopoverContent, PopoverTrigger } from '@ufb/ui'; -import { useState } from 'react'; - -interface IProps { - title: string; - iconSize?: number; -} - -const Tooltip: React.FC = ({ title, iconSize = 14 }) => { - const [open, setOpen] = useState(false); - - return ( - - - setOpen(true)} - onMouseOut={() => setOpen(false)} - /> - - -

{title}

-
-
- ); -}; - -export default Tooltip; diff --git a/apps/web/src/components/etc/index.ts b/apps/web/src/components/etc/index.ts index 22d9e0c46..599092503 100644 --- a/apps/web/src/components/etc/index.ts +++ b/apps/web/src/components/etc/index.ts @@ -23,7 +23,6 @@ export { default as SelectBox } from './SelectBox'; export { default as ShareButton } from './ShareButton'; export { default as Popper } from './Popper'; export { default as DateRangePicker } from './DateRangePicker'; -export { default as Tooltip } from './Tooltip'; export { default as SelectBoxWithIcon } from './SelectBoxWithIcon'; export { default as TableLoadingRow } from './TableLoadingRow'; export { default as IssueCircle } from './IssueCircle'; diff --git a/apps/web/src/components/layouts/Header/Header.tsx b/apps/web/src/components/layouts/Header/Header.tsx index 57b000fee..ebaabc512 100644 --- a/apps/web/src/components/layouts/Header/Header.tsx +++ b/apps/web/src/components/layouts/Header/Header.tsx @@ -13,16 +13,16 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon } from '@ufb/ui'; +import { useEffect } from 'react'; import Image from 'next/image'; import Link from 'next/link'; import { useRouter } from 'next/router'; -import { useEffect } from 'react'; import { useStore } from 'zustand'; +import { Icon } from '@ufb/ui'; + import { Path } from '@/constants/path'; import themeStore from '@/zustand/theme.store'; - import HeaderName from './HeaderName'; import LocaleSelectBox from './LocaleSelectBox'; import ProfileBox from './ProfileBox'; @@ -38,10 +38,10 @@ const Header: React.FC = () => { }, [theme]); return ( -
+
{ width={24} height={24} /> - +
diff --git a/apps/web/src/components/layouts/Header/HeaderName.tsx b/apps/web/src/components/layouts/Header/HeaderName.tsx index ab6752805..ebdf51486 100644 --- a/apps/web/src/components/layouts/Header/HeaderName.tsx +++ b/apps/web/src/components/layouts/Header/HeaderName.tsx @@ -13,9 +13,10 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon } from '@ufb/ui'; -import { useRouter } from 'next/router'; import { useMemo } from 'react'; +import { useRouter } from 'next/router'; + +import { Icon } from '@ufb/ui'; import { useOAIQuery, useTenant } from '@/hooks'; @@ -41,7 +42,7 @@ const HeaderName: React.FC = () => { return (
-
+
{tenant?.siteName} @@ -50,7 +51,7 @@ const HeaderName: React.FC = () => { <>
-
+
= () => { value={router.locale} onChange={(v) => onToggleLanguageClick(v)} > - + {({ value }) => ( <> @@ -47,7 +48,7 @@ const LocaleSelectBox: React.FC = () => { )} - + {router.locales ?.filter((v) => v !== 'default') .map((v) => ( @@ -56,7 +57,7 @@ const LocaleSelectBox: React.FC = () => { value={v} className={({ selected }) => [ - 'select-none p-2 cursor-pointer hover:bg-secondary uppercase text-center font-extrabold', + 'hover:bg-secondary cursor-pointer select-none p-2 text-center font-extrabold uppercase', selected ? 'font-bold' : 'font-normal', ].join(' ') } diff --git a/apps/web/src/components/layouts/Header/ProfileBox.tsx b/apps/web/src/components/layouts/Header/ProfileBox.tsx index 74f1cddc4..5474e4e4f 100644 --- a/apps/web/src/components/layouts/Header/ProfileBox.tsx +++ b/apps/web/src/components/layouts/Header/ProfileBox.tsx @@ -13,11 +13,12 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon, Popover, PopoverContent, PopoverTrigger } from '@ufb/ui'; -import { useRouter } from 'next/router'; import { Fragment, useState } from 'react'; +import { useRouter } from 'next/router'; import { useTranslation } from 'react-i18next'; +import { Icon, Popover, PopoverContent, PopoverTrigger } from '@ufb/ui'; + import { useUser } from '@/hooks'; interface IProps {} @@ -34,7 +35,7 @@ const ProfileBox: React.FC = () => { setOpen((v) => !v)}>
@@ -47,7 +48,7 @@ const ProfileBox: React.FC = () => {
  • { router.push('/main/profile'); setOpen(false); @@ -56,7 +57,7 @@ const ProfileBox: React.FC = () => { {t('header.profile')}
  • { signOut(); setOpen(false); diff --git a/apps/web/src/components/layouts/SideNav/SideNav.tsx b/apps/web/src/components/layouts/SideNav/SideNav.tsx index e5bf0b929..032676ec3 100644 --- a/apps/web/src/components/layouts/SideNav/SideNav.tsx +++ b/apps/web/src/components/layouts/SideNav/SideNav.tsx @@ -13,12 +13,14 @@ * License for the specific language governing permissions and limitations * under the License. */ -import { Icon, IconNameType } from '@ufb/ui'; +import type { UrlObject } from 'url'; +import { useRef, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/router'; -import { useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { UrlObject } from 'url'; + +import type { IconNameType } from '@ufb/ui'; +import { Icon } from '@ufb/ui'; import { Path } from '@/constants/path'; import { useCurrentProjectId, usePermissions } from '@/hooks'; @@ -36,9 +38,9 @@ const SideNav: React.FC = () => { return (