td-web-cli 0.1.5 → 0.1.7

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.
@@ -1,78 +0,0 @@
1
- import { Command } from 'commander';
2
- import { select, Separator } from '@inquirer/prompts';
3
- import { excel2json } from './excel2json/index.js';
4
- import { logger, loggerError } from '../../utils/index.js';
5
-
6
- /**
7
- * 国际化模块主入口
8
- * 提供多个国际化相关功能的交互式选择
9
- * @param program Commander命令行实例,用于传递参数和配置
10
- */
11
- export async function i18n(program: Command) {
12
- try {
13
- logger.info('国际化模块启动,等待用户选择功能');
14
-
15
- // 定义可用功能选项
16
- const moduleChoices = [
17
- {
18
- name: '提取词条',
19
- value: 'extractEntry',
20
- description: '从所给路径中提取词条信息',
21
- },
22
- {
23
- name: 'json转excel',
24
- value: 'json2excel',
25
- description: '将json格式的词条信息转换为excel表格',
26
- },
27
- {
28
- name: 'excel转json',
29
- value: 'excel2json',
30
- description: '将excel表格转换为json格式的词条信息',
31
- },
32
- {
33
- name: 'json合并',
34
- value: 'jsonMerge',
35
- description: '合并多个json格式的词条信息文件',
36
- },
37
- ];
38
-
39
- // 交互式选择需要执行的功能
40
- const answer = await select({
41
- message: '请选择要执行的功能:',
42
- choices: [
43
- ...moduleChoices,
44
- new Separator(), // 分割线,方便未来扩展更多功能
45
- ],
46
- default: 'extractEntry', // 默认选项
47
- pageSize: 10, // 最大显示选项数
48
- loop: true, // 是否循环滚动选项
49
- });
50
-
51
- // 查找选择功能的名称,方便日志输出
52
- const selectedModule = moduleChoices.find((item) => item.value === answer);
53
-
54
- if (!selectedModule) {
55
- logger.warn('未选择有效功能,程序已退出');
56
- process.exit(0);
57
- }
58
-
59
- logger.info(`用户选择功能:${selectedModule.name}`);
60
-
61
- // 根据选择执行对应功能
62
- switch (answer) {
63
- case 'excel2json':
64
- logger.info(`${selectedModule.name}功能开始执行`);
65
- await excel2json(program);
66
- logger.info(`${selectedModule.name}功能执行完成`);
67
- break;
68
- default:
69
- logger.warn(`${selectedModule.name}功能暂未实现,程序已退出`);
70
- process.exit(0);
71
- }
72
- } catch (error: unknown) {
73
- // 记录错误日志,方便排查
74
- loggerError(error, logger);
75
- console.error('程序执行时发生异常,已记录日志,程序已退出');
76
- process.exit(1);
77
- }
78
- }
@@ -1,3 +0,0 @@
1
- export function run() {
2
- console.log('json转excel');
3
- }
@@ -1,3 +0,0 @@
1
- export function run() {
2
- console.log('json合并');
3
- }
@@ -1,352 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
- import { getData, postData } from '../api/index.js';
5
- import api from '../api/interface.js';
6
-
7
- /**
8
- * 获取当前时间戳字符串,格式为:YYYYMMDDHHMMSS
9
- * 例如:20260123135500 表示 2026年01月23日 13点55分00秒
10
- *
11
- * @returns {string} 格式化后的时间戳字符串
12
- */
13
- export function getTimestamp(): string {
14
- const now = new Date();
15
-
16
- /**
17
- * 辅助函数:将数字转换为长度为2的字符串,不足时左侧补0
18
- * @param n 需要格式化的数字
19
- * @returns {string} 补零后的字符串
20
- */
21
- const pad = (n: number): string => n.toString().padStart(2, '0');
22
-
23
- const year = now.getFullYear(); // 获取四位年份
24
- const month = pad(now.getMonth() + 1); // 获取月份(0-11),需+1,补零
25
- const day = pad(now.getDate()); // 获取日期,补零
26
- const hour = pad(now.getHours()); // 获取小时,补零
27
- const minute = pad(now.getMinutes()); // 获取分钟,补零
28
- const second = pad(now.getSeconds()); // 获取秒钟,补零
29
-
30
- // 拼接成完整时间戳字符串
31
- return `${year}${month}${day}${hour}${minute}${second}`;
32
- }
33
-
34
- /**
35
- * 日志级别类型
36
- */
37
- type LogLevel = 'INFO' | 'WARN' | 'ERROR';
38
-
39
- /**
40
- * 日志配置接口
41
- */
42
- interface LoggerOptions {
43
- /**
44
- * 日志目录,默认程序入口文件所在目录的上级目录的 logs 文件夹
45
- */
46
- logsDir?: string;
47
-
48
- /**
49
- * 日志文件名格式函数,接收当前日期,返回文件名字符串
50
- * 默认格式为 YYYYMMDD.txt
51
- */
52
- filenameFormatter?: (date: Date) => string;
53
-
54
- /**
55
- * 当前环境,默认 process.env.NODE_ENV
56
- */
57
- env?: string;
58
-
59
- /**
60
- * 程序入口文件绝对路径,用于确定日志目录位置
61
- */
62
- entryFilePath?: string;
63
- }
64
-
65
- /**
66
- * 获取程序入口文件路径(兼容 ES Module)
67
- * @returns 程序入口文件的绝对路径
68
- */
69
- function getEntryFilePath(): string {
70
- try {
71
- // 当前模块文件路径
72
- return fileURLToPath(import.meta.url);
73
- } catch {
74
- // 兜底:使用 process.argv[1]
75
- if (process.argv.length > 1) {
76
- return path.resolve(process.cwd(), process.argv[1]);
77
- }
78
- // 最终兜底
79
- return '';
80
- }
81
- }
82
-
83
- /**
84
- * 默认日志配置
85
- * logsDir 默认设置为程序入口文件所在目录的上级目录的 logs 文件夹
86
- */
87
- const defaultOptions: LoggerOptions = {
88
- logsDir: '',
89
- filenameFormatter: (date: Date) =>
90
- date.toISOString().slice(0, 10).replace(/-/g, '') + '.txt',
91
- env: process.env.NODE_ENV || 'production',
92
- entryFilePath: getEntryFilePath(),
93
- };
94
-
95
- /**
96
- * 格式化日志内容,支持字符串或对象
97
- * @param level 日志级别
98
- * @param message 日志内容,字符串或对象
99
- * @param date 当前时间
100
- * @returns 格式化后的日志字符串
101
- */
102
- function formatLogLine(level: LogLevel, message: unknown, date: Date): string {
103
- const timeStr = date.toISOString();
104
- let msgStr: string;
105
-
106
- if (typeof message === 'string') {
107
- msgStr = message;
108
- } else {
109
- try {
110
- msgStr = JSON.stringify(message, null, 2);
111
- } catch {
112
- msgStr = String(message);
113
- }
114
- }
115
-
116
- return `[${timeStr}] [${level}] ${msgStr}\n`;
117
- }
118
-
119
- /**
120
- * 统一日志处理类
121
- * 支持写入日志文件和控制台打印
122
- */
123
- export class Logger {
124
- private logsDir: string;
125
- private filenameFormatter: (date: Date) => string;
126
- private env: string;
127
-
128
- /**
129
- * 构造函数,初始化日志配置
130
- * @param options 配置项,可选
131
- */
132
- constructor(options?: LoggerOptions) {
133
- const opts = { ...defaultOptions, ...options };
134
-
135
- // 如果未传 logsDir,则默认设置为入口文件所在目录的上级目录的 logs 文件夹
136
- this.logsDir =
137
- opts.logsDir ||
138
- path.resolve(path.dirname(opts.entryFilePath!), '..', 'logs');
139
- this.filenameFormatter =
140
- opts.filenameFormatter ?? defaultOptions.filenameFormatter!;
141
- this.env = opts.env ?? defaultOptions.env!;
142
- }
143
-
144
- /**
145
- * 写日志主函数
146
- * @param level 日志级别
147
- * @param message 日志内容,支持字符串或对象
148
- * @param printConsole 是否打印到控制台,默认 false
149
- */
150
- log(level: LogLevel, message: unknown, printConsole = false): void {
151
- const now = new Date();
152
- const logLine = formatLogLine(level, message, now);
153
-
154
- // 根据调用时是否指定打印控制台,决定是否打印
155
- if (printConsole) {
156
- switch (level) {
157
- case 'INFO':
158
- console.info(logLine.trim());
159
- break;
160
- case 'WARN':
161
- console.warn(logLine.trim());
162
- break;
163
- case 'ERROR':
164
- console.error(logLine.trim());
165
- break;
166
- }
167
- }
168
-
169
- try {
170
- // 确保日志目录存在
171
- if (!fs.existsSync(this.logsDir)) {
172
- fs.mkdirSync(this.logsDir, { recursive: true });
173
- }
174
-
175
- const filename = this.filenameFormatter(now);
176
- const logFilePath = path.join(this.logsDir, filename);
177
-
178
- // 追加写入日志文件
179
- fs.appendFileSync(logFilePath, logLine, { encoding: 'utf8' });
180
- } catch (error: unknown) {
181
- // 仅在开发环境打印写日志异常堆栈,生产环境静默失败,避免影响主程序
182
- if (this.env === 'development') {
183
- console.error('日志写入异常:', normalizeError(error).stack);
184
- }
185
- }
186
- }
187
-
188
- /**
189
- * 记录信息级别日志
190
- * @param message 日志内容
191
- * @param printConsole 是否打印到控制台,默认 false
192
- */
193
- info(message: unknown, printConsole = false): void {
194
- this.log('INFO', message, printConsole);
195
- }
196
-
197
- /**
198
- * 记录警告级别日志
199
- * @param message 日志内容
200
- * @param printConsole 是否打印到控制台,默认 false
201
- */
202
- warn(message: unknown, printConsole = false): void {
203
- this.log('WARN', message, printConsole);
204
- }
205
-
206
- /**
207
- * 记录错误级别日志
208
- * @param message 日志内容
209
- * @param printConsole 是否打印到控制台,默认 false
210
- */
211
- error(message: unknown, printConsole = false): void {
212
- this.log('ERROR', message, printConsole);
213
- }
214
- }
215
-
216
- /**
217
- * 默认导出单例 logger,方便直接使用
218
- * 默认不打印控制台日志
219
- */
220
- export const logger = new Logger({
221
- env: process.env.NODE_ENV || 'development',
222
- });
223
-
224
- /**
225
- * 通用错误日志记录函数
226
- * @param error 捕获的错误对象
227
- * @param logger 日志对象,需包含 error 方法
228
- * @param prefix 日志前缀,方便区分来源,默认值为 '程序执行时发生错误'
229
- * @param printConsole 是否打印错误日志到控制台,默认 false
230
- */
231
- export function loggerError(
232
- error: unknown,
233
- logger: { error: (msg: string, printConsole?: boolean) => void },
234
- prefix = '程序执行时发生错误',
235
- printConsole = false
236
- ): void {
237
- logger.error(`${prefix}:${normalizeError(error).stack}`, printConsole);
238
- }
239
-
240
- /**
241
- * 将任意错误对象规范化为 Error 类型。
242
- * @param err - 可能是 Error、字符串或其他任意类型
243
- * @returns 标准的 Error 对象
244
- */
245
- export const normalizeError = (err: unknown): Error => {
246
- if (err instanceof Error) {
247
- // 已经是 Error 类型,直接返回
248
- return err;
249
- } else if (typeof err === 'string') {
250
- // 如果是字符串,创建新的 Error
251
- return new Error(err);
252
- } else {
253
- // 其他情况,返回通用错误
254
- return new Error('未知错误');
255
- }
256
- };
257
-
258
- /**
259
- * 语言工具接口返回的语言列表类型
260
- * 数组中每个元素包含语言名称、简写代码和长代码
261
- */
262
- export type LanguageTool = {
263
- name: string; // 语言名称,如 "English"
264
- code: string; // 语言简写代码,如 "en"
265
- longCode: string; // 语言长代码,如 "en-US"
266
- }[];
267
-
268
- /**
269
- * 获取支持的语言列表
270
- * 调用语言工具接口,返回所有支持的语言信息数组
271
- * @returns Promise<LanguageTool> 返回语言列表的 Promise
272
- * @throws 接口请求失败时抛出错误,错误信息包含接口地址和异常堆栈
273
- */
274
- export async function getLanguageTool(): Promise<LanguageTool> {
275
- const url = api.LANGUAGE_TOOL_V2_LANGUAGES;
276
- try {
277
- const res = await getData<LanguageTool>(url);
278
- return res;
279
- } catch (error) {
280
- // 捕获异常并包装错误信息,包含接口地址和堆栈信息
281
- throw new Error(`${url}接口报错:${normalizeError(error).stack}`);
282
- }
283
- }
284
-
285
- /**
286
- * 替换建议类型
287
- */
288
- export interface Replacement {
289
- value: string; // 建议替换的字符串
290
- }
291
-
292
- /**
293
- * 语言检测结果中的单条匹配错误信息
294
- */
295
- export interface Match {
296
- message: string; // 错误描述信息
297
- shortMessage: string; // 简短错误信息
298
- offset: number; // 错误在文本中的起始位置
299
- length: number; // 错误长度
300
- replacements: Replacement[]; // 建议的替换项数组
301
- sentence: string; // 出错的句子
302
- rule: {
303
- // 触发的规则信息
304
- id: string; // 规则ID
305
- description: string; // 规则描述
306
- };
307
- }
308
-
309
- /**
310
- * 语言检测接口返回的完整结果类型
311
- */
312
- export interface CheckResult {
313
- matches: Match[]; // 检测到的所有错误匹配项
314
- language: {
315
- // 语言信息
316
- name: string; // 语言名称
317
- code: string; // 语言代码
318
- };
319
- software: {
320
- // 使用的检测软件信息
321
- name: string; // 软件名称
322
- version: string; // 版本号
323
- premium: boolean; // 是否为付费版
324
- };
325
- }
326
-
327
- /**
328
- * 调用语言检测接口,检测文本中的语言错误
329
- * @param text 待检测文本
330
- * @param language 语言代码,默认 'en-US'
331
- * @returns Promise<CheckResult> 返回检测结果的 Promise
332
- * @throws 接口请求失败时抛出错误,错误信息包含接口地址和异常堆栈
333
- */
334
- export async function languageToolCheck(
335
- text: string,
336
- language = 'en-US'
337
- ): Promise<CheckResult> {
338
- const url = api.LANGUAGE_TOOL_V2_CHECK;
339
- const params = new URLSearchParams();
340
- params.append('text', text);
341
- params.append('language', language);
342
-
343
- try {
344
- const res = await postData<string, CheckResult>(url, params.toString(), {
345
- 'Content-Type': 'application/x-www-form-urlencoded',
346
- });
347
- return res;
348
- } catch (error) {
349
- // 捕获异常并包装错误信息,包含接口地址和堆栈信息
350
- throw new Error(`${url}接口报错:${normalizeError(error).stack}`);
351
- }
352
- }
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2019",
4
- "module": "nodenext",
5
- "outDir": "./dist",
6
- "rootDir": "./src",
7
- "esModuleInterop": true,
8
- "forceConsistentCasingInFileNames": true,
9
- "strict": true,
10
- "skipLibCheck": true
11
- }
12
- }