Skip to content

Commit

Permalink
Merge branch 'develop' into feature/only_reference_one_translation_file
Browse files Browse the repository at this point in the history
  • Loading branch information
jing12345678910 committed Sep 6, 2024
2 parents c58d91c + 0b50864 commit 206e7e4
Show file tree
Hide file tree
Showing 30 changed files with 287 additions and 148 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"sharp": "^0.33.3",
"tailwind-merge": "^2.2.2",
"ts-node": "^10.9.2",
"uuid": "^10.0.0"
"uuid": "^10.0.0",
"winston": "^3.14.2"
},
"devDependencies": {
"@babel/eslint-plugin": "^7.25.1",
Expand All @@ -70,6 +71,7 @@
"@types/jsonwebtoken": "^9.0.6",
"@types/node": "^22.4.2",
"@types/nodemailer": "^6.4.15",
"@types/pino": "^7.0.5",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
"@types/uuid": "^10.0.0",
Expand Down
1 change: 0 additions & 1 deletion scripts/update_version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,4 @@ try {
process.exit(1); // Info: (20240701 - Jacky) Exit the process with an error code
}

// Info:(20240701-Jacky) - Log the updated version
// Todo: (20240822 - Anna): [Beta] feat. Murky - 使用 logger
1 change: 1 addition & 0 deletions src/components/edit_bookmark_modal/edit_bookmark_modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useDashboardCtx } from '@/contexts/dashboard_context';
import useOuterClick from '@/lib/hooks/use_outer_click';
import { useGlobalCtx } from '@/contexts/global_context';
import { useTranslation } from 'next-i18next';
// import logger from '@/lib/utils/logger';

interface IAddBookmarkModal {
isModalVisible: boolean;
Expand Down
4 changes: 2 additions & 2 deletions src/components/journal_item/journal_item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,15 @@ const JournalItem = ({
};

const debitItem = lineItems
? (lineItems.filter((item) => item.debit)[0] ?? defaultItem)
? lineItems.filter((item) => item.debit)[0] ?? defaultItem
: defaultItem;
const debit = {
account: debitItem.account,
amount: numberWithCommas(debitItem.amount),
};

const creditItem = lineItems
? (lineItems.filter((item) => !item.debit)[0] ?? defaultItem)
? lineItems.filter((item) => !item.debit)[0] ?? defaultItem
: defaultItem;
const credit = {
account: creditItem.account,
Expand Down
2 changes: 1 addition & 1 deletion src/components/journal_list_body/journal_list_body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const JournalListBody = () => {
endDate: !(period ?? filteredPeriod).endTimeStamp
? undefined
: (period ?? filteredPeriod).endTimeStamp,
searchQuery: !(searchString ?? search) ? undefined : (searchString ?? search),
searchQuery: !(searchString ?? search) ? undefined : searchString ?? search,
},
});

Expand Down
2 changes: 1 addition & 1 deletion src/components/nav_bar/nav_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ const NavBar = () => {
</button>
<div className="mt-3 flex justify-center gap-0 px-16">
<div className="my-auto text-base font-semibold leading-6 tracking-normal text-button-text-secondary">
{signedIn ? (username ?? DEFAULT_DISPLAYED_USER_NAME) : ''}
{signedIn ? username ?? DEFAULT_DISPLAYED_USER_NAME : ''}
</div>
{/* Info: (20240809 - Shirley) edit name button */}
<button
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/global_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ export const GlobalProvider = ({ children }: IGlobalProvider) => {
const position = toastPosition ?? ToastPosition.TOP_CENTER; // Info:(20240513 - Julian) default position 'top-center'

// Info:(20240513 - Julian) 如果 closeable 為 false,則 autoClose、closeOnClick、draggable 都會被設為 false
const autoClose = closeable ? (isAutoClose ?? 5000) : false; // Info:(20240513 - Julian) default autoClose 5000ms
const autoClose = closeable ? isAutoClose ?? 5000 : false; // Info:(20240513 - Julian) default autoClose 5000ms

const closeOnClick = closeable; // Info:(20240513 - Julian) default closeOnClick true
const draggable = closeable; // Info:(20240513 - Julian) default draggable true
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/user_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {

const res = await selectCompanyAPI({
params: {
companyId: !company && !isPublic ? -1 : (company?.id ?? FREE_COMPANY_ID),
companyId: !company && !isPublic ? -1 : company?.id ?? FREE_COMPANY_ID,
},
});

Expand Down
2 changes: 0 additions & 2 deletions src/interfaces/voucher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ export interface IVoucherMetaData {
payment: IPayment;
}

// Deprecated: (20240524 - Murky) To Emily, To Julian IVoucher only contains lineItems
// I use IVoucherDataForSavingToDB
export interface IVoucher {
voucherIndex: string;
invoiceIndex: string; // 改在這裡
Expand Down
1 change: 0 additions & 1 deletion src/lib/utils/account/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ export function mappingAccountToSheetDisplay(
return sheetDisplay;
}

// Deprecated: (20240702 - Murky) Accounting logic need to be refactor, Income sum up should be done when update account tree
export function calculateIncomeStatementNetIncome(accounts: IAccountNode[]): IAccountNode[] {
const operatingRevenues = accounts.find((account) => account.code === '4000')?.amount || 0;
const operatingCosts = accounts.find((account) => account.code === '5000')?.amount || 0;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/utils/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
decryptFile,
getPrivateKeyByCompany,
} from '@/lib/utils/crypto';
import logger from '@/lib/utils/logger';
import logger from '@/lib/utils/logger_back';
import { STATUS_MESSAGE } from '@/constants/status_code';

export async function createFileFoldersIfNotExists(): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/utils/generate_user_icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
generateSavePath,
uploadFileToGoogleCloud,
} from '@/lib/utils/google_image_upload';
import logger from './logger';
import logger from '@/lib/utils/logger_back';

function isChinese(name: string): boolean {
return /[\u3400-\u9FBF]/.test(name);
Expand Down
50 changes: 0 additions & 50 deletions src/lib/utils/logger.ts

This file was deleted.

210 changes: 210 additions & 0 deletions src/lib/utils/logger_back.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { LOG_FOLDER } from '@/constants/file';
import { Prisma } from '@prisma/client';
import pino, { Logger } from 'pino';
import pretty from 'pino-pretty';
import { createStream } from 'rotating-file-stream';

const level: pino.Level = process.env.NODE_ENV === 'production' ? 'info' : 'trace';

// Info: (20240823 - Gibbs) 設定日誌文件的路徑
let logDirectory = './logs';

// Info: (20240823 - Gibbs) 獲取當前環境
const environment = process.env.NODE_ENV;
// Info: (20240823 - Gibbs) 不同環境不同資料夾
if (environment === 'production') {
logDirectory = `${LOG_FOLDER}/production`;
} else if (environment === 'development') {
logDirectory = `${LOG_FOLDER}//development`;
} else if (environment === 'test') {
logDirectory = `${LOG_FOLDER}/test`;
} else {
logDirectory = `${LOG_FOLDER}/others`;
}

// Info: (20240823 - Gibbs) 創建一個 rotating-file-stream,每七天創建一個新文件
const logStream = createStream(
(time) => {
if (!time) return `app-${environment}.log`; // Info: (20240823 - Gibbs) 初始文件名
const date = new Date(time);
return `app-${environment}-${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}.log`;
},
{
interval: '7d', // Info: (20240823 - Gibbs) 每七天創建一個新文件
path: logDirectory,
}
);

// Info: (20240828 - Murky) Console log 中會print出pretty的格式
const prettyStream = pretty({
colorize: true,
});

// Info: (20240828 - Gibbs) 使用 pino-multi-stream 來處理多個輸出
const streams = [
{ level, stream: logStream, sync: false }, // Info: (20240823 - Gibbs) 將日誌輸出到 rotating-file-stream
{ level, stream: prettyStream }, // Info: (20240823 - Murky) 將日誌輸出到 console
];

const loggerBack: Logger = pino({ level }, pino.multistream(streams));

export default loggerBack;

function getErrorCode(
error: Prisma.PrismaClientKnownRequestError | Prisma.PrismaClientInitializationError
): string | undefined {
if ('code' in error) {
return error.code;
} else if ('errorCode' in error) {
return error.errorCode;
}
return undefined;
}

/** (20240828 - Gibbs) 記錄錯誤和異常的詳細信息
* @param {number} [userId] - 用戶ID
* @param {string} errorType - 錯誤類型
* @param {string | Error} errorMessage - 錯誤訊息
*/
export function loggerError(userId: number, errorType: string, errorMessage: string | Error) {
const logData = { level: 'error', userId, errorType, errorMessage };
if (userId) {
logData.userId = userId;
}

if (typeof errorMessage === 'string') {
// Info: (20240905 - Gibbs) 已知指定錯誤訊息
logData.errorMessage = errorMessage;
/* Info: (20240905 - Gibbs) 已知指定錯誤訊息
* 處理 Prisma 錯誤, PrismaClientUnknownRequestError, PrismaClientRustPanicError, Prisma.PrismaClientValidationError 無 error code
* PrismaClientKnownRequestError: code, PrismaClientInitializationError: errorCode
*/
} else if (
errorMessage instanceof Prisma.PrismaClientKnownRequestError ||
errorMessage instanceof Prisma.PrismaClientInitializationError
) {
// Info: (20240905 - Gibbs) 轉換特定 Prisma code 錯誤, 其餘 Prisma code 錯誤給預設值
const errorCode = getErrorCode(errorMessage);
switch (errorCode) {
case 'P1008':
logData.errorMessage = 'Operations timed out!';
break;
case 'P1017':
logData.errorMessage = 'Server has closed the connection!';
break;
case 'P2002':
logData.errorMessage = 'Unique constraint failed!';
break;
case 'P2003':
logData.errorMessage = 'Foreign key constraint failed!';
break;
case 'P2004':
logData.errorMessage = 'A constraint failed on the database!';
break;
case 'P2005':
logData.errorMessage =
"The value stored in the database for the field is invalid for the field's type!";
break;
case 'P2011':
logData.errorMessage = 'Null constraint violation!';
break;
case 'P2021':
logData.errorMessage = 'The table does not exist in the current database!';
break;
case 'P2022':
logData.errorMessage = 'The column does not exist in the current database!';
break;
case 'P2024':
logData.errorMessage = 'Timed out fetching a new connection from the connection pool!';
break;
default:
logData.errorMessage = `Unhandled Prisma error code: ${errorCode},\n${errorMessage.message}`;
}
} else if (
errorMessage instanceof Prisma.PrismaClientUnknownRequestError ||
errorMessage instanceof Prisma.PrismaClientRustPanicError ||
errorMessage instanceof Prisma.PrismaClientValidationError
) {
// Info: (20240905 - Gibbs) 處理其餘 Prisma 錯誤
logData.errorMessage = `A Prisma error:\n${errorMessage.message}`;
} else if (errorMessage instanceof Error) {
// Info: (20240905 - Gibbs) 處理一般錯誤
logData.errorMessage = `Non Prisma error:\n${errorMessage.message}`;
}

return loggerBack.child(logData);
}

/** Info: (20240828 - Gibbs) 記錄請求和響應的詳細信息
* @param {number} [userId] - 用戶ID
* @param {string} url - 請求的URL
* @param {string} method - HTTP方法 (如GET, POST)
* @param {number} statusCode - 響應的HTTP狀態碼
* @param {object} params - 請求參數
* @param {string} userAgent - 用戶代理信息
* @param {string} ipAddress - 用戶的IP地址
*/
export function loggerRequest(
userId: number,
url: string,
method: string,
statusCode: number,
params: object,
userAgent: string,
ipAddress: string
) {
const logData = { level: 'info', userId, url, method, statusCode, params, userAgent, ipAddress };
if (userId) {
logData.userId = userId;
}
return loggerBack.child(logData);
}

/** Info: (20240828 - Gibbs) 記錄用戶行為
* @param {number} userId - 用戶ID
* @param {string} actionType - 操作類型
* @param {object} actionDetails - 操作詳細信息
*/
export function loggerUserAction(userId: number, actionType: string, actionDetails: object) {
return loggerBack.child({ level: 'info', userId, actionType, actionDetails });
}

/** Info: (20240828 - Gibbs) 記錄系統事件
* @param {string} eventType - 事件類型
* @param {object} details - 事件詳細信息
*/
export function loggerSystemEvent(eventType: string, details: object) {
return loggerBack.child({ level: 'info', eventType, details });
}

/** Info: (20240828 - Gibbs) 記錄性能數據
* @param {number} [userId] - 用戶ID
* @param {number} responseTime - 響應時間
* @param {object} queryPerformance - 查詢性能
* @param {number} resourceLoadTime - 資源加載時間
*/
export function loggerPerformance(
userId: number,
responseTime: number,
queryPerformance: object,
resourceLoadTime: number
) {
const logData = { level: 'info', userId, responseTime, queryPerformance, resourceLoadTime };
if (userId) {
logData.userId = userId;
}
return loggerBack.child(logData);
}

/** Info: (20240828 - Gibbs) 記錄安全相關事件
* @param {number} [userId] - 用戶ID
* @param {object} authProcess - 認證過程
* @param {object} securityEvent - 安全事件
*/
export function loggerSecurity(userId: number, authProcess: unknown, securityEvent: unknown) {
const logData = { level: 'warn', userId, authProcess, securityEvent };
if (userId) {
logData.userId = userId;
}
return loggerBack.child(logData);
}
2 changes: 1 addition & 1 deletion src/lib/utils/parse_image_form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from 'path';
import { NextApiRequest } from 'next';
import { FORMIDABLE_OPTIONS } from '@/constants/config';
import { FileFolder, getFileFolder } from '@/constants/file';
import logger from '@/lib/utils/logger';
import logger from '@/lib/utils/logger_back';

export const parseForm = async (
req: NextApiRequest,
Expand Down
Loading

0 comments on commit 206e7e4

Please sign in to comment.