douyin-downloader 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/bin/dydl.d.ts +2 -0
- package/dist/bin/dydl.js +17 -0
- package/dist/bin/dydl.js.map +1 -0
- package/dist/src/cli/commands/check.d.ts +10 -0
- package/dist/src/cli/commands/check.js +102 -0
- package/dist/src/cli/commands/check.js.map +1 -0
- package/dist/src/cli/commands/info.d.ts +10 -0
- package/dist/src/cli/commands/info.js +106 -0
- package/dist/src/cli/commands/info.js.map +1 -0
- package/dist/src/cli/commands/list.d.ts +10 -0
- package/dist/src/cli/commands/list.js +85 -0
- package/dist/src/cli/commands/list.js.map +1 -0
- package/dist/src/cli/commands/login.d.ts +10 -0
- package/dist/src/cli/commands/login.js +158 -0
- package/dist/src/cli/commands/login.js.map +1 -0
- package/dist/src/cli/commands/open.d.ts +10 -0
- package/dist/src/cli/commands/open.js +141 -0
- package/dist/src/cli/commands/open.js.map +1 -0
- package/dist/src/cli/commands/video.d.ts +10 -0
- package/dist/src/cli/commands/video.js +209 -0
- package/dist/src/cli/commands/video.js.map +1 -0
- package/dist/src/cli/index.d.ts +15 -0
- package/dist/src/cli/index.js +134 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/progress-display.d.ts +80 -0
- package/dist/src/cli/progress-display.js +225 -0
- package/dist/src/cli/progress-display.js.map +1 -0
- package/dist/src/cli/utils.d.ts +31 -0
- package/dist/src/cli/utils.js +171 -0
- package/dist/src/cli/utils.js.map +1 -0
- package/dist/src/douyin/auth/cookie-path.d.ts +22 -0
- package/dist/src/douyin/auth/cookie-path.js +72 -0
- package/dist/src/douyin/auth/cookie-path.js.map +1 -0
- package/dist/src/douyin/auth/cookie-storage.d.ts +19 -0
- package/dist/src/douyin/auth/cookie-storage.js +65 -0
- package/dist/src/douyin/auth/cookie-storage.js.map +1 -0
- package/dist/src/douyin/auth/errors.d.ts +28 -0
- package/dist/src/douyin/auth/errors.js +49 -0
- package/dist/src/douyin/auth/errors.js.map +1 -0
- package/dist/src/douyin/auth/getDefaultCookiePath.d.ts +24 -0
- package/dist/src/douyin/auth/getDefaultCookiePath.js +90 -0
- package/dist/src/douyin/auth/getDefaultCookiePath.js.map +1 -0
- package/dist/src/douyin/auth/index.d.ts +16 -0
- package/dist/src/douyin/auth/index.js +68 -0
- package/dist/src/douyin/auth/index.js.map +1 -0
- package/dist/src/douyin/auth/isValidCookie.d.ts +18 -0
- package/dist/src/douyin/auth/isValidCookie.js +60 -0
- package/dist/src/douyin/auth/isValidCookie.js.map +1 -0
- package/dist/src/douyin/auth/loadAndValidateCookie.d.ts +17 -0
- package/dist/src/douyin/auth/loadAndValidateCookie.js +45 -0
- package/dist/src/douyin/auth/loadAndValidateCookie.js.map +1 -0
- package/dist/src/douyin/auth/loadCookie.d.ts +17 -0
- package/dist/src/douyin/auth/loadCookie.js +79 -0
- package/dist/src/douyin/auth/loadCookie.js.map +1 -0
- package/dist/src/douyin/auth/login.d.ts +33 -0
- package/dist/src/douyin/auth/login.js +157 -0
- package/dist/src/douyin/auth/login.js.map +1 -0
- package/dist/src/douyin/auth/saveCookie.d.ts +17 -0
- package/dist/src/douyin/auth/saveCookie.js +89 -0
- package/dist/src/douyin/auth/saveCookie.js.map +1 -0
- package/dist/src/douyin/auth/validate.d.ts +11 -0
- package/dist/src/douyin/auth/validate.js +104 -0
- package/dist/src/douyin/auth/validate.js.map +1 -0
- package/dist/src/douyin/browser/manager.d.ts +54 -0
- package/dist/src/douyin/browser/manager.js +344 -0
- package/dist/src/douyin/browser/manager.js.map +1 -0
- package/dist/src/douyin/download/download-manager.d.ts +25 -0
- package/dist/src/douyin/download/download-manager.js +107 -0
- package/dist/src/douyin/download/download-manager.js.map +1 -0
- package/dist/src/douyin/download/error-handler.d.ts +49 -0
- package/dist/src/douyin/download/error-handler.js +160 -0
- package/dist/src/douyin/download/error-handler.js.map +1 -0
- package/dist/src/douyin/download/index.d.ts +39 -0
- package/dist/src/douyin/download/index.js +156 -0
- package/dist/src/douyin/download/index.js.map +1 -0
- package/dist/src/douyin/download/path-formatter.d.ts +42 -0
- package/dist/src/douyin/download/path-formatter.js +107 -0
- package/dist/src/douyin/download/path-formatter.js.map +1 -0
- package/dist/src/douyin/download/video-downloader.d.ts +35 -0
- package/dist/src/douyin/download/video-downloader.js +223 -0
- package/dist/src/douyin/download/video-downloader.js.map +1 -0
- package/dist/src/douyin/index.d.ts +19 -0
- package/dist/src/douyin/index.js +52 -0
- package/dist/src/douyin/index.js.map +1 -0
- package/dist/src/douyin/info/batch-processor.d.ts +15 -0
- package/dist/src/douyin/info/batch-processor.js +65 -0
- package/dist/src/douyin/info/batch-processor.js.map +1 -0
- package/dist/src/douyin/info/browser-manager.d.ts +56 -0
- package/dist/src/douyin/info/browser-manager.js +225 -0
- package/dist/src/douyin/info/browser-manager.js.map +1 -0
- package/dist/src/douyin/info/error-handler.d.ts +36 -0
- package/dist/src/douyin/info/error-handler.js +172 -0
- package/dist/src/douyin/info/error-handler.js.map +1 -0
- package/dist/src/douyin/info/fetch-video-detail.d.ts +14 -0
- package/dist/src/douyin/info/fetch-video-detail.js +247 -0
- package/dist/src/douyin/info/fetch-video-detail.js.map +1 -0
- package/dist/src/douyin/info/index.d.ts +29 -0
- package/dist/src/douyin/info/index.js +85 -0
- package/dist/src/douyin/info/index.js.map +1 -0
- package/dist/src/douyin/info/text-processor.d.ts +15 -0
- package/dist/src/douyin/info/text-processor.js +47 -0
- package/dist/src/douyin/info/text-processor.js.map +1 -0
- package/dist/src/douyin/info/user.d.ts +26 -0
- package/dist/src/douyin/info/user.js +237 -0
- package/dist/src/douyin/info/user.js.map +1 -0
- package/dist/src/douyin/parser/containsDouyinLink.d.ts +18 -0
- package/dist/src/douyin/parser/containsDouyinLink.js +27 -0
- package/dist/src/douyin/parser/containsDouyinLink.js.map +1 -0
- package/dist/src/douyin/parser/extract-links.d.ts +23 -0
- package/dist/src/douyin/parser/extract-links.js +79 -0
- package/dist/src/douyin/parser/extract-links.js.map +1 -0
- package/dist/src/douyin/parser/extractDouyinLinks.d.ts +18 -0
- package/dist/src/douyin/parser/extractDouyinLinks.js +58 -0
- package/dist/src/douyin/parser/extractDouyinLinks.js.map +1 -0
- package/dist/src/douyin/parser/index.d.ts +35 -0
- package/dist/src/douyin/parser/index.js +70 -0
- package/dist/src/douyin/parser/index.js.map +1 -0
- package/dist/src/douyin/parser/link-patterns.d.ts +34 -0
- package/dist/src/douyin/parser/link-patterns.js +121 -0
- package/dist/src/douyin/parser/link-patterns.js.map +1 -0
- package/dist/src/douyin/parser/parse-batch.d.ts +26 -0
- package/dist/src/douyin/parser/parse-batch.js +67 -0
- package/dist/src/douyin/parser/parse-batch.js.map +1 -0
- package/dist/src/douyin/parser/parseDouyinLinks.d.ts +30 -0
- package/dist/src/douyin/parser/parseDouyinLinks.js +164 -0
- package/dist/src/douyin/parser/parseDouyinLinks.js.map +1 -0
- package/dist/src/douyin/parser/resolve-links.d.ts +25 -0
- package/dist/src/douyin/parser/resolve-links.js +131 -0
- package/dist/src/douyin/parser/resolve-links.js.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +72 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/types.d.ts +217 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/browser.d.ts +73 -0
- package/dist/src/utils/browser.js +96 -0
- package/dist/src/utils/browser.js.map +1 -0
- package/dist/src/utils/error.d.ts +160 -0
- package/dist/src/utils/error.js +334 -0
- package/dist/src/utils/error.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +41 -0
- package/dist/src/utils/fetch.js +155 -0
- package/dist/src/utils/fetch.js.map +1 -0
- package/dist/src/utils/file.d.ts +46 -0
- package/dist/src/utils/file.js +189 -0
- package/dist/src/utils/file.js.map +1 -0
- package/dist/src/utils/index.d.ts +11 -0
- package/dist/src/utils/index.js +29 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/logger.d.ts +161 -0
- package/dist/src/utils/logger.js +286 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/performance.d.ts +98 -0
- package/dist/src/utils/performance.js +292 -0
- package/dist/src/utils/performance.js.map +1 -0
- package/dist/src/utils/retry.d.ts +56 -0
- package/dist/src/utils/retry.js +127 -0
- package/dist/src/utils/retry.js.map +1 -0
- package/package.json +61 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* 通用檔案操作工具
|
4
|
+
* 提供檔案系統操作功能,如下載檔案、獲取安全檔案名等
|
5
|
+
*/
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
exports.downloadFile = downloadFile;
|
11
|
+
exports.getSafeFilename = getSafeFilename;
|
12
|
+
exports.getTimestampedFilename = getTimestampedFilename;
|
13
|
+
exports.ensureDirectoryExists = ensureDirectoryExists;
|
14
|
+
exports.getAppDataDir = getAppDataDir;
|
15
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
16
|
+
const path_1 = __importDefault(require("path"));
|
17
|
+
const os_1 = __importDefault(require("os")); // Import os module
|
18
|
+
const logger_1 = require("./logger"); // Use the utils logger
|
19
|
+
const fetch_1 = require("./fetch"); // Use the shared fetch
|
20
|
+
/**
|
21
|
+
* 下載檔案
|
22
|
+
* @param url 檔案 URL
|
23
|
+
* @param destPath 目標路徑
|
24
|
+
* @param options 下載選項
|
25
|
+
* @returns Promise<string> 下載完成的檔案路徑
|
26
|
+
*/
|
27
|
+
async function downloadFile(url, destPath, options = {}) {
|
28
|
+
let writer = null;
|
29
|
+
try {
|
30
|
+
// 確保目錄存在
|
31
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(destPath));
|
32
|
+
// 創建寫入流
|
33
|
+
writer = fs_extra_1.default.createWriteStream(destPath);
|
34
|
+
// 發送請求
|
35
|
+
const response = await (0, fetch_1.enhancedFetch)(url, {
|
36
|
+
headers: options.headers,
|
37
|
+
timeout: options.timeout
|
38
|
+
});
|
39
|
+
if (!response.ok) {
|
40
|
+
throw new Error(`下載失敗: ${response.status} ${response.statusText}`);
|
41
|
+
}
|
42
|
+
// 獲取總大小
|
43
|
+
const contentLength = response.headers.get('content-length');
|
44
|
+
const totalSize = contentLength ? parseInt(contentLength, 10) : undefined;
|
45
|
+
let downloaded = 0;
|
46
|
+
// 如果響應體不是可讀流,則直接寫入
|
47
|
+
if (!response.body) {
|
48
|
+
const buffer = await response.arrayBuffer();
|
49
|
+
writer.write(Buffer.from(buffer));
|
50
|
+
writer.end();
|
51
|
+
if (options.onProgress && totalSize !== undefined) {
|
52
|
+
options.onProgress(totalSize, totalSize);
|
53
|
+
}
|
54
|
+
return destPath;
|
55
|
+
}
|
56
|
+
// 創建讀取流
|
57
|
+
const reader = response.body.getReader();
|
58
|
+
// 處理進度
|
59
|
+
const processChunk = async () => {
|
60
|
+
const { done, value } = await reader.read();
|
61
|
+
if (done) {
|
62
|
+
// Ensure writer is closed before resolving
|
63
|
+
return new Promise((resolve) => {
|
64
|
+
if (writer) {
|
65
|
+
writer.end(resolve);
|
66
|
+
}
|
67
|
+
else {
|
68
|
+
resolve();
|
69
|
+
}
|
70
|
+
});
|
71
|
+
}
|
72
|
+
if (value) {
|
73
|
+
downloaded += value.length;
|
74
|
+
// Wait for the write to complete to handle backpressure
|
75
|
+
await new Promise((resolve, reject) => {
|
76
|
+
if (writer) {
|
77
|
+
writer.write(Buffer.from(value), (err) => {
|
78
|
+
if (err)
|
79
|
+
reject(err);
|
80
|
+
else
|
81
|
+
resolve();
|
82
|
+
});
|
83
|
+
}
|
84
|
+
else {
|
85
|
+
reject(new Error("Writer is not available"));
|
86
|
+
}
|
87
|
+
});
|
88
|
+
if (options.onProgress) {
|
89
|
+
options.onProgress(downloaded, totalSize);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
return processChunk();
|
93
|
+
};
|
94
|
+
await processChunk();
|
95
|
+
logger_1.utilsLogger.debug(`檔案已下載至 ${destPath}`);
|
96
|
+
return destPath;
|
97
|
+
}
|
98
|
+
catch (error) {
|
99
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
100
|
+
logger_1.utilsLogger.error(`下載檔案 ${url} 至 ${destPath} 失敗:`, err);
|
101
|
+
// 確保關閉寫入流
|
102
|
+
if (writer && !writer.closed) {
|
103
|
+
writer.close();
|
104
|
+
}
|
105
|
+
// 如果檔案已經創建但下載失敗,則刪除它
|
106
|
+
try {
|
107
|
+
if (await fs_extra_1.default.pathExists(destPath)) {
|
108
|
+
await fs_extra_1.default.unlink(destPath);
|
109
|
+
logger_1.utilsLogger.debug(`刪除不完整的下載檔案: ${destPath}`);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
catch (unlinkError) {
|
113
|
+
const unlinkErr = unlinkError instanceof Error ? unlinkError : new Error(String(unlinkError));
|
114
|
+
logger_1.utilsLogger.error(`刪除不完整的下載檔案 ${destPath} 失敗:`, unlinkErr);
|
115
|
+
}
|
116
|
+
throw new Error(`下載檔案失敗: ${err.message}`);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
/**
|
120
|
+
* 獲取安全的檔案名(替換非法字符)
|
121
|
+
* @param filename 原始檔案名
|
122
|
+
* @returns 安全的檔案名
|
123
|
+
*/
|
124
|
+
function getSafeFilename(filename) {
|
125
|
+
if (!filename)
|
126
|
+
return 'untitled';
|
127
|
+
// 替換非法字符
|
128
|
+
return filename
|
129
|
+
.replace(/[\\/:*?"<>|]/g, '_') // 替換 Windows/Unix 不允許的字符
|
130
|
+
.replace(/\s+/g, ' ') // 將連續空白字符替換為單個空格
|
131
|
+
.trim() // 去除首尾空白字符
|
132
|
+
.slice(0, 200); // Limit filename length to avoid issues
|
133
|
+
}
|
134
|
+
/**
|
135
|
+
* 建立帶有時間戳的檔案名
|
136
|
+
* @param name 檔案名(不含副檔名)
|
137
|
+
* @param ext 副檔名(不含句點)
|
138
|
+
* @returns 格式化的檔案名
|
139
|
+
*/
|
140
|
+
function getTimestampedFilename(name, ext) {
|
141
|
+
const timestamp = new Date().toISOString().replace(/[:-]/g, '').split('.')[0];
|
142
|
+
const safeName = getSafeFilename(name);
|
143
|
+
const safeExt = ext.replace(/[^a-zA-Z0-9]/g, ''); // Sanitize extension
|
144
|
+
return `${timestamp}-${safeName}.${safeExt}`;
|
145
|
+
}
|
146
|
+
/**
|
147
|
+
* 確保目錄存在,如果不存在則創建
|
148
|
+
* @param dirPath 目錄路徑
|
149
|
+
*/
|
150
|
+
async function ensureDirectoryExists(dirPath) {
|
151
|
+
try {
|
152
|
+
await fs_extra_1.default.ensureDir(dirPath);
|
153
|
+
logger_1.utilsLogger.debug(`目錄已確保存在: ${dirPath}`);
|
154
|
+
}
|
155
|
+
catch (error) {
|
156
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
157
|
+
logger_1.utilsLogger.error(`創建目錄 ${dirPath} 失敗:`, err);
|
158
|
+
// Consider throwing a specific AppError here
|
159
|
+
throw new Error(`無法創建目錄 ${dirPath}: ${err.message}`);
|
160
|
+
}
|
161
|
+
}
|
162
|
+
/**
|
163
|
+
* 獲取應用數據目錄
|
164
|
+
* 根據作業系統選擇適當的目錄
|
165
|
+
* @param appName 應用程式名稱,用於創建子目錄
|
166
|
+
* @returns 資料目錄路徑
|
167
|
+
*/
|
168
|
+
function getAppDataDir(appName = 'douyin-downloader') {
|
169
|
+
let dir;
|
170
|
+
const homedir = os_1.default.homedir();
|
171
|
+
switch (process.platform) {
|
172
|
+
case 'win32':
|
173
|
+
// Windows: %APPDATA%\[appName]
|
174
|
+
dir = path_1.default.join(process.env.APPDATA || path_1.default.join(homedir, 'AppData', 'Roaming'), appName);
|
175
|
+
break;
|
176
|
+
case 'darwin':
|
177
|
+
// macOS: ~/Library/Application Support/[appName]
|
178
|
+
dir = path_1.default.join(homedir, 'Library', 'Application Support', appName);
|
179
|
+
break;
|
180
|
+
default:
|
181
|
+
// Linux/其他: ~/.config/[appName] or ~/.local/share/[appName]
|
182
|
+
dir = path_1.default.join(process.env.XDG_CONFIG_HOME || path_1.default.join(homedir, '.config'), appName);
|
183
|
+
// Fallback to .local/share if .config doesn't exist or isn't standard?
|
184
|
+
// Or just stick to .config as a common practice.
|
185
|
+
break;
|
186
|
+
}
|
187
|
+
return dir;
|
188
|
+
}
|
189
|
+
//# sourceMappingURL=file.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/utils/file.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* 通用工具模組入口
|
4
|
+
* 重新導出所有共享的工具函數和類
|
5
|
+
*/
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
7
|
+
if (k2 === undefined) k2 = k;
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
11
|
+
}
|
12
|
+
Object.defineProperty(o, k2, desc);
|
13
|
+
}) : (function(o, m, k, k2) {
|
14
|
+
if (k2 === undefined) k2 = k;
|
15
|
+
o[k2] = m[k];
|
16
|
+
}));
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
19
|
+
};
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
21
|
+
__exportStar(require("./logger"), exports);
|
22
|
+
__exportStar(require("./error"), exports);
|
23
|
+
__exportStar(require("./fetch"), exports);
|
24
|
+
__exportStar(require("./file"), exports); // Includes downloadFile, getSafeFilename, getTimestampedFilename, ensureDirectoryExists, getAppDataDir
|
25
|
+
__exportStar(require("./retry"), exports);
|
26
|
+
__exportStar(require("./browser"), exports);
|
27
|
+
__exportStar(require("./performance"), exports);
|
28
|
+
// Add other shared utils here if created later
|
29
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,2CAAyB;AACzB,0CAAwB;AACxB,0CAAwB;AACxB,yCAAuB,CAAC,uGAAuG;AAC/H,0CAAwB;AACxB,4CAA0B;AAC1B,gDAA8B;AAC9B,+CAA+C"}
|
@@ -0,0 +1,161 @@
|
|
1
|
+
/**
|
2
|
+
* 通用日誌工具
|
3
|
+
* 提供統一的日誌輸出功能,支持不同的日誌級別、格式化和範圍
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* 日誌級別枚舉
|
7
|
+
*/
|
8
|
+
export declare enum LogLevel {
|
9
|
+
DEBUG = 0,
|
10
|
+
INFO = 1,
|
11
|
+
WARN = 2,
|
12
|
+
ERROR = 3,
|
13
|
+
NONE = 4
|
14
|
+
}
|
15
|
+
/**
|
16
|
+
* 日誌級別名稱映射
|
17
|
+
*/
|
18
|
+
export declare const LOG_LEVEL_NAMES: Record<LogLevel, string>;
|
19
|
+
/**
|
20
|
+
* 日誌選項接口
|
21
|
+
*/
|
22
|
+
export interface LoggerOptions {
|
23
|
+
scope?: string;
|
24
|
+
level?: LogLevel;
|
25
|
+
formatter?: LogFormatter;
|
26
|
+
transports?: LogTransport[];
|
27
|
+
metadata?: Record<string, any>;
|
28
|
+
}
|
29
|
+
/**
|
30
|
+
* 日誌記錄接口
|
31
|
+
*/
|
32
|
+
export interface LogEntry {
|
33
|
+
timestamp: Date;
|
34
|
+
level: LogLevel;
|
35
|
+
levelName: string;
|
36
|
+
scope: string;
|
37
|
+
message: string;
|
38
|
+
data: any[];
|
39
|
+
metadata?: Record<string, any>;
|
40
|
+
}
|
41
|
+
/**
|
42
|
+
* 日誌格式化器類型
|
43
|
+
*/
|
44
|
+
export type LogFormatter = (entry: LogEntry) => string;
|
45
|
+
/**
|
46
|
+
* 日誌輸出目標接口
|
47
|
+
*/
|
48
|
+
export interface LogTransport {
|
49
|
+
log(entry: LogEntry): void;
|
50
|
+
}
|
51
|
+
/**
|
52
|
+
* 控制台日誌輸出目標
|
53
|
+
*/
|
54
|
+
export declare class ConsoleTransport implements LogTransport {
|
55
|
+
/**
|
56
|
+
* 輸出日誌到控制台
|
57
|
+
* @param entry 日誌記錄
|
58
|
+
*/
|
59
|
+
log(entry: LogEntry): void;
|
60
|
+
/**
|
61
|
+
* 根據日誌級別獲取相應的控制台方法
|
62
|
+
* @param level 日誌級別
|
63
|
+
* @returns 控制台方法
|
64
|
+
*/
|
65
|
+
private getConsoleMethod;
|
66
|
+
}
|
67
|
+
/**
|
68
|
+
* 默認日誌格式化器
|
69
|
+
* @param entry 日誌記錄
|
70
|
+
* @returns 格式化後的日誌字符串
|
71
|
+
*/
|
72
|
+
export declare const defaultFormatter: LogFormatter;
|
73
|
+
/**
|
74
|
+
* Logger 類
|
75
|
+
* 日誌工具類,用於統一管理和格式化日誌輸出
|
76
|
+
*/
|
77
|
+
export declare class Logger {
|
78
|
+
private scope;
|
79
|
+
private level;
|
80
|
+
private formatter;
|
81
|
+
private transports;
|
82
|
+
private metadata?;
|
83
|
+
/**
|
84
|
+
* 創建 Logger 實例
|
85
|
+
* @param options 日誌選項
|
86
|
+
*/
|
87
|
+
constructor(options?: LoggerOptions);
|
88
|
+
/**
|
89
|
+
* 創建日誌記錄
|
90
|
+
* @param level 日誌級別
|
91
|
+
* @param message 日誌消息
|
92
|
+
* @param data 附加數據
|
93
|
+
* @returns 日誌記錄
|
94
|
+
*/
|
95
|
+
private createLogEntry;
|
96
|
+
/**
|
97
|
+
* 輸出日誌
|
98
|
+
* @param level 日誌級別
|
99
|
+
* @param message 日誌消息
|
100
|
+
* @param data 附加數據
|
101
|
+
*/
|
102
|
+
private log;
|
103
|
+
/**
|
104
|
+
* 輸出調試日誌
|
105
|
+
* @param message 日誌消息
|
106
|
+
* @param data 附加數據
|
107
|
+
*/
|
108
|
+
debug(message: string, ...data: any[]): void;
|
109
|
+
/**
|
110
|
+
* 輸出信息日誌
|
111
|
+
* @param message 日誌消息
|
112
|
+
* @param data 附加數據
|
113
|
+
*/
|
114
|
+
info(message: string, ...data: any[]): void;
|
115
|
+
/**
|
116
|
+
* 輸出警告日誌
|
117
|
+
* @param message 日誌消息
|
118
|
+
* @param data 附加數據
|
119
|
+
*/
|
120
|
+
warn(message: string, ...data: any[]): void;
|
121
|
+
/**
|
122
|
+
* 輸出錯誤日誌
|
123
|
+
* @param message 錯誤消息
|
124
|
+
* @param error 錯誤對象
|
125
|
+
* @param data 附加數據
|
126
|
+
*/
|
127
|
+
error(message: string, error?: Error | unknown, ...data: any[]): void;
|
128
|
+
/**
|
129
|
+
* 設置日誌級別
|
130
|
+
* @param level 日誌級別
|
131
|
+
* @returns 當前 Logger 實例 (用於鏈式調用)
|
132
|
+
*/
|
133
|
+
setLevel(level: LogLevel): Logger;
|
134
|
+
/**
|
135
|
+
* 添加元數據
|
136
|
+
* @param metadata 元數據對象
|
137
|
+
* @returns 當前 Logger 實例 (用於鏈式調用)
|
138
|
+
*/
|
139
|
+
addMetadata(metadata: Record<string, any>): Logger;
|
140
|
+
/**
|
141
|
+
* 創建一個子日誌記錄器,繼承父日誌記錄器的配置
|
142
|
+
* @param subScope 子日誌範圍
|
143
|
+
* @param metadata 附加元數據
|
144
|
+
* @returns 子日誌記錄器實例
|
145
|
+
*/
|
146
|
+
createSubLogger(subScope: string, metadata?: Record<string, any>): Logger;
|
147
|
+
}
|
148
|
+
/**
|
149
|
+
* 創建一個日誌記錄器
|
150
|
+
* @param scope 日誌範圍
|
151
|
+
* @param options 日誌選項
|
152
|
+
* @returns Logger 實例
|
153
|
+
*/
|
154
|
+
export declare function createLogger(scope: string, options?: LoggerOptions): Logger;
|
155
|
+
export declare const rootLogger: Logger;
|
156
|
+
export declare const authLogger: Logger;
|
157
|
+
export declare const parserLogger: Logger;
|
158
|
+
export declare const infoLogger: Logger;
|
159
|
+
export declare const downloadLogger: Logger;
|
160
|
+
export declare const cliLogger: Logger;
|
161
|
+
export declare const utilsLogger: Logger;
|
@@ -0,0 +1,286 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* 通用日誌工具
|
4
|
+
* 提供統一的日誌輸出功能,支持不同的日誌級別、格式化和範圍
|
5
|
+
*/
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
+
exports.utilsLogger = exports.cliLogger = exports.downloadLogger = exports.infoLogger = exports.parserLogger = exports.authLogger = exports.rootLogger = exports.Logger = exports.defaultFormatter = exports.ConsoleTransport = exports.LOG_LEVEL_NAMES = exports.LogLevel = void 0;
|
8
|
+
exports.createLogger = createLogger;
|
9
|
+
/**
|
10
|
+
* 日誌級別枚舉
|
11
|
+
*/
|
12
|
+
var LogLevel;
|
13
|
+
(function (LogLevel) {
|
14
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
15
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
16
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
17
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
18
|
+
LogLevel[LogLevel["NONE"] = 4] = "NONE"; // 用於完全禁用日誌
|
19
|
+
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
20
|
+
/**
|
21
|
+
* 日誌級別名稱映射
|
22
|
+
*/
|
23
|
+
exports.LOG_LEVEL_NAMES = {
|
24
|
+
[LogLevel.DEBUG]: 'DEBUG',
|
25
|
+
[LogLevel.INFO]: 'INFO',
|
26
|
+
[LogLevel.WARN]: 'WARN',
|
27
|
+
[LogLevel.ERROR]: 'ERROR',
|
28
|
+
[LogLevel.NONE]: 'NONE'
|
29
|
+
};
|
30
|
+
/**
|
31
|
+
* 控制台日誌輸出目標
|
32
|
+
*/
|
33
|
+
class ConsoleTransport {
|
34
|
+
/**
|
35
|
+
* 輸出日誌到控制台
|
36
|
+
* @param entry 日誌記錄
|
37
|
+
*/
|
38
|
+
log(entry) {
|
39
|
+
const method = this.getConsoleMethod(entry.level);
|
40
|
+
// 確保傳遞給控制台方法的是字符串,避免類型錯誤
|
41
|
+
method(entry.message);
|
42
|
+
}
|
43
|
+
/**
|
44
|
+
* 根據日誌級別獲取相應的控制台方法
|
45
|
+
* @param level 日誌級別
|
46
|
+
* @returns 控制台方法
|
47
|
+
*/
|
48
|
+
getConsoleMethod(level) {
|
49
|
+
switch (level) {
|
50
|
+
case LogLevel.DEBUG:
|
51
|
+
return console.debug;
|
52
|
+
case LogLevel.INFO:
|
53
|
+
return console.info;
|
54
|
+
case LogLevel.WARN:
|
55
|
+
return console.warn;
|
56
|
+
case LogLevel.ERROR:
|
57
|
+
return console.error;
|
58
|
+
default:
|
59
|
+
return console.log;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
exports.ConsoleTransport = ConsoleTransport;
|
64
|
+
/**
|
65
|
+
* 默認日誌格式化器
|
66
|
+
* @param entry 日誌記錄
|
67
|
+
* @returns 格式化後的日誌字符串
|
68
|
+
*/
|
69
|
+
const defaultFormatter = (entry) => {
|
70
|
+
const timestamp = entry.timestamp.toISOString();
|
71
|
+
const scope = entry.scope ? `[${entry.scope}]` : '';
|
72
|
+
const level = `[${exports.LOG_LEVEL_NAMES[entry.level]}]`;
|
73
|
+
let message = `${timestamp} ${level} ${scope}: ${entry.message}`;
|
74
|
+
// 格式化附加數據
|
75
|
+
if (entry.data && entry.data.length > 0) {
|
76
|
+
try {
|
77
|
+
const dataStr = entry.data.map(item => {
|
78
|
+
if (item instanceof Error) {
|
79
|
+
return item.stack || item.message;
|
80
|
+
}
|
81
|
+
if (typeof item === 'object' && item !== null) {
|
82
|
+
// Handle circular references safely
|
83
|
+
try {
|
84
|
+
return JSON.stringify(item, null, 2);
|
85
|
+
}
|
86
|
+
catch (jsonError) {
|
87
|
+
return `[無法序列化對象: ${jsonError}]`;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
return String(item);
|
91
|
+
}).join(' ');
|
92
|
+
if (dataStr.trim()) {
|
93
|
+
message += ` ${dataStr}`;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
catch (e) {
|
97
|
+
message += ` [無法格式化附加數據: ${e}]`;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
// 添加元數據
|
101
|
+
if (entry.metadata && Object.keys(entry.metadata).length > 0) {
|
102
|
+
try {
|
103
|
+
message += ` (metadata: ${JSON.stringify(entry.metadata)})`;
|
104
|
+
}
|
105
|
+
catch (e) {
|
106
|
+
message += ` [無法格式化元數據: ${e}]`;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
return message;
|
110
|
+
};
|
111
|
+
exports.defaultFormatter = defaultFormatter;
|
112
|
+
/**
|
113
|
+
* Logger 類
|
114
|
+
* 日誌工具類,用於統一管理和格式化日誌輸出
|
115
|
+
*/
|
116
|
+
class Logger {
|
117
|
+
scope;
|
118
|
+
level;
|
119
|
+
formatter;
|
120
|
+
transports;
|
121
|
+
metadata;
|
122
|
+
/**
|
123
|
+
* 創建 Logger 實例
|
124
|
+
* @param options 日誌選項
|
125
|
+
*/
|
126
|
+
constructor(options = {}) {
|
127
|
+
this.scope = options.scope || '';
|
128
|
+
// Determine default level first
|
129
|
+
let defaultLevel = options.level ?? (process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG);
|
130
|
+
// --- Check args for silent mode override ---
|
131
|
+
// This check runs when the logger instance (including rootLogger) is created
|
132
|
+
const args = process.argv;
|
133
|
+
const commandIndex = args.findIndex(arg => ['info', 'list'].includes(arg));
|
134
|
+
const hasOutputFileOption = args.includes('-f') || args.includes('--file');
|
135
|
+
if (commandIndex !== -1 && ['info', 'list'].includes(args[commandIndex]) && !hasOutputFileOption) {
|
136
|
+
// Override default level if silent mode is detected
|
137
|
+
defaultLevel = LogLevel.NONE;
|
138
|
+
// We could potentially override console here too, but let's try logger level first
|
139
|
+
}
|
140
|
+
// ---
|
141
|
+
this.level = defaultLevel;
|
142
|
+
this.formatter = options.formatter || exports.defaultFormatter;
|
143
|
+
this.transports = options.transports || [new ConsoleTransport()];
|
144
|
+
this.metadata = options.metadata;
|
145
|
+
}
|
146
|
+
/**
|
147
|
+
* 創建日誌記錄
|
148
|
+
* @param level 日誌級別
|
149
|
+
* @param message 日誌消息
|
150
|
+
* @param data 附加數據
|
151
|
+
* @returns 日誌記錄
|
152
|
+
*/
|
153
|
+
createLogEntry(level, message, data) {
|
154
|
+
return {
|
155
|
+
timestamp: new Date(),
|
156
|
+
level,
|
157
|
+
levelName: exports.LOG_LEVEL_NAMES[level],
|
158
|
+
scope: this.scope,
|
159
|
+
message,
|
160
|
+
data,
|
161
|
+
metadata: this.metadata
|
162
|
+
};
|
163
|
+
}
|
164
|
+
/**
|
165
|
+
* 輸出日誌
|
166
|
+
* @param level 日誌級別
|
167
|
+
* @param message 日誌消息
|
168
|
+
* @param data 附加數據
|
169
|
+
*/
|
170
|
+
log(level, message, ...data) {
|
171
|
+
// 檢查日誌級別
|
172
|
+
if (level < this.level) {
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
// 創建日誌記錄
|
176
|
+
const entry = this.createLogEntry(level, message, data);
|
177
|
+
// 格式化日誌
|
178
|
+
const formattedMessage = this.formatter(entry);
|
179
|
+
// 更新日誌記錄中的消息
|
180
|
+
entry.message = formattedMessage;
|
181
|
+
// 輸出到所有目標
|
182
|
+
for (const transport of this.transports) {
|
183
|
+
try {
|
184
|
+
transport.log(entry);
|
185
|
+
}
|
186
|
+
catch (error) {
|
187
|
+
// 避免日誌輸出錯誤破壞程序流程
|
188
|
+
console.error('日誌輸出失敗:', error);
|
189
|
+
}
|
190
|
+
}
|
191
|
+
}
|
192
|
+
/**
|
193
|
+
* 輸出調試日誌
|
194
|
+
* @param message 日誌消息
|
195
|
+
* @param data 附加數據
|
196
|
+
*/
|
197
|
+
debug(message, ...data) {
|
198
|
+
this.log(LogLevel.DEBUG, message, ...data);
|
199
|
+
}
|
200
|
+
/**
|
201
|
+
* 輸出信息日誌
|
202
|
+
* @param message 日誌消息
|
203
|
+
* @param data 附加數據
|
204
|
+
*/
|
205
|
+
info(message, ...data) {
|
206
|
+
this.log(LogLevel.INFO, message, ...data);
|
207
|
+
}
|
208
|
+
/**
|
209
|
+
* 輸出警告日誌
|
210
|
+
* @param message 日誌消息
|
211
|
+
* @param data 附加數據
|
212
|
+
*/
|
213
|
+
warn(message, ...data) {
|
214
|
+
this.log(LogLevel.WARN, message, ...data);
|
215
|
+
}
|
216
|
+
/**
|
217
|
+
* 輸出錯誤日誌
|
218
|
+
* @param message 錯誤消息
|
219
|
+
* @param error 錯誤對象
|
220
|
+
* @param data 附加數據
|
221
|
+
*/
|
222
|
+
error(message, error, ...data) {
|
223
|
+
const errorObj = error instanceof Error ? error : undefined;
|
224
|
+
const additionalData = error instanceof Error ? data : [error, ...data];
|
225
|
+
if (errorObj) {
|
226
|
+
this.log(LogLevel.ERROR, message, errorObj, ...additionalData);
|
227
|
+
}
|
228
|
+
else {
|
229
|
+
this.log(LogLevel.ERROR, message, ...additionalData);
|
230
|
+
}
|
231
|
+
}
|
232
|
+
/**
|
233
|
+
* 設置日誌級別
|
234
|
+
* @param level 日誌級別
|
235
|
+
* @returns 當前 Logger 實例 (用於鏈式調用)
|
236
|
+
*/
|
237
|
+
setLevel(level) {
|
238
|
+
this.level = level;
|
239
|
+
return this;
|
240
|
+
}
|
241
|
+
/**
|
242
|
+
* 添加元數據
|
243
|
+
* @param metadata 元數據對象
|
244
|
+
* @returns 當前 Logger 實例 (用於鏈式調用)
|
245
|
+
*/
|
246
|
+
addMetadata(metadata) {
|
247
|
+
this.metadata = { ...this.metadata, ...metadata };
|
248
|
+
return this;
|
249
|
+
}
|
250
|
+
/**
|
251
|
+
* 創建一個子日誌記錄器,繼承父日誌記錄器的配置
|
252
|
+
* @param subScope 子日誌範圍
|
253
|
+
* @param metadata 附加元數據
|
254
|
+
* @returns 子日誌記錄器實例
|
255
|
+
*/
|
256
|
+
createSubLogger(subScope, metadata) {
|
257
|
+
const newScope = this.scope ? `${this.scope}:${subScope}` : subScope;
|
258
|
+
return new Logger({
|
259
|
+
scope: newScope,
|
260
|
+
level: this.level,
|
261
|
+
formatter: this.formatter,
|
262
|
+
transports: this.transports,
|
263
|
+
metadata: { ...this.metadata, ...metadata }
|
264
|
+
});
|
265
|
+
}
|
266
|
+
}
|
267
|
+
exports.Logger = Logger;
|
268
|
+
/**
|
269
|
+
* 創建一個日誌記錄器
|
270
|
+
* @param scope 日誌範圍
|
271
|
+
* @param options 日誌選項
|
272
|
+
* @returns Logger 實例
|
273
|
+
*/
|
274
|
+
function createLogger(scope, options = {}) {
|
275
|
+
return new Logger({ ...options, scope });
|
276
|
+
}
|
277
|
+
// 創建默認的根日誌記錄器
|
278
|
+
exports.rootLogger = createLogger('app'); // Changed default scope name
|
279
|
+
// 導出特定模組的日誌記錄器 (可以根據需要調整或移除)
|
280
|
+
exports.authLogger = exports.rootLogger.createSubLogger('auth');
|
281
|
+
exports.parserLogger = exports.rootLogger.createSubLogger('parser');
|
282
|
+
exports.infoLogger = exports.rootLogger.createSubLogger('info');
|
283
|
+
exports.downloadLogger = exports.rootLogger.createSubLogger('download');
|
284
|
+
exports.cliLogger = exports.rootLogger.createSubLogger('cli');
|
285
|
+
exports.utilsLogger = exports.rootLogger.createSubLogger('utils'); // Added utils logger
|
286
|
+
//# sourceMappingURL=logger.js.map
|