🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

daji

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

daji - npm Package Compare versions

Comparing version
1.4.4
to
2.0.0
+83
doc/config.md
# 配置管理模块 (config.js)
## 1. 模块概述
配置管理模块用于处理工具的配置数据导入和导出功能,方便用户备份和恢复配置。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 配置备份 | 将当前所有配置数据备份到本地 |
| 配置导入 | 从本地备份文件导入配置数据 |
## 3. 命令格式
```bash
daji config [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --install | -i | 无 | 导入备份配置 |
| --backup | -b | 无 | 备份当前配置 |
## 5. 使用示例
### 5.1 备份配置
```bash
daji config --backup
# 或
daji config -b
```
执行此命令后,工具会将所有配置数据备份到 `backup/` 目录下。
### 5.2 导入配置
```bash
daji config --install
# 或
daji config -i
```
执行此命令后,工具会从当前目录的备份文件中导入配置数据。
## 6. 实现原理
1. **配置备份**:
- 遍历 `data/` 目录下的所有 JSON 配置文件
- 将每个配置文件复制到 `backup/` 目录下对应的子目录
- 保持原有的目录结构和文件名
2. **配置导入**:
- 遍历当前目录下的所有 JSON 配置文件
- 将每个配置文件复制到 `data/` 目录下对应的子目录
- 覆盖原有配置文件
## 7. 数据结构
配置数据存储在 `data/` 目录下,按功能模块分类:
```
data/
├── git/
│ └── config.json
├── host/
│ ├── config.json
│ └── selected.json
├── ios/
│ ├── config.json
│ └── pan.json
└── _fileList.json
```
## 8. 依赖关系
- `getfiles` - 文件获取库
- `cfiles` - 文件操作库
- `../common/utils` - 通用工具函数
- `../data/_fileList.json` - 文件列表配置
# 日期时间处理模块 (date.js)
## 1. 模块概述
日期时间处理模块用于处理时间戳的转换和格式化,支持将时间戳转换为可读日期格式,以及将日期转换为时间戳。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 获取当前时间戳 | 获取当前时间的毫秒级时间戳 |
| 时间戳转日期 | 将毫秒级时间戳转换为可读日期格式 |
| 日期转时间戳 | 将指定日期转换为毫秒级时间戳 |
## 3. 命令格式
```bash
daji Date [cmd] [options]
# 或
daji d [cmd] [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --Timestamp | -t | 日期字符串 | 将指定日期转换为时间戳 |
## 5. 使用示例
### 5.1 获取当前时间戳和日期
```bash
daji Date
# 或
daji d
```
执行此命令后,工具会输出当前时间的毫秒级时间戳和对应的可读日期格式。
### 5.2 将时间戳转换为日期
```bash
daji Date 1609459200000
# 或
daji d 1609459200000
```
执行此命令后,工具会将指定的时间戳转换为可读日期格式(YYYY-MM-DD HH:mm:ss)。
### 5.3 将日期转换为时间戳
```bash
daji Date --Timestamp "2021-01-01"
# 或
daji Date -t "2021-01-01"
# 或
daji d -t "2021-01-01"
```
执行此命令后,工具会将指定的日期转换为毫秒级时间戳。
### 5.4 指定时间转换为时间戳
```bash
daji Date "12:00:00" --Timestamp "2021-01-01"
# 或
daji Date "12:00:00" -t "2021-01-01"
```
执行此命令后,工具会将指定的日期和时间转换为毫秒级时间戳。
## 6. 实现原理
1. **获取当前时间戳**:
- 使用 `Date.parse(new Date())` 获取当前时间的毫秒级时间戳
- 使用 `moment` 库将时间戳格式化为可读日期
2. **时间戳转日期**:
- 检查输入是否为有效的数字字符串
- 使用 `moment` 库将时间戳转换为指定格式的日期字符串
3. **日期转时间戳**:
- 接收日期字符串和可选的时间字符串
- 使用 `moment` 库将日期时间字符串转换为毫秒级时间戳
## 7. 依赖关系
- `moment` - 日期时间处理库
- `../common/utils` - 通用工具函数
## 8. 格式说明
### 8.1 输入格式
- **时间戳**:13位数字字符串,例如 `1609459200000`
- **日期字符串**:YYYY-MM-DD 格式,例如 `2021-01-01`
- **时间字符串**:HH:mm:ss 格式,例如 `12:00:00`
### 8.2 输出格式
- **时间戳**:13位数字,例如 `1609459200000`
- **日期格式**:YYYY-MM-DD HH:mm:ss,例如 `2021-01-01 00:00:00`
# Git账号管理模块 (git.js)
## 1. 模块概述
Git账号管理模块用于管理和切换Git用户账号,方便开发者在不同项目间快速切换Git身份。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 查看Git账号信息 | 查看当前Git账号的用户名和邮箱 |
| 切换Git账号 | 从配置的账号列表中选择并切换Git账号 |
| 管理Git账号配置 | 导入、导出和更新Git账号配置 |
## 3. 命令格式
```bash
daji gitConfig [cmd] [options]
# 或
daji git [cmd] [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --info | 无 | all 或 无 | 查看Git账号信息,all表示查看所有配置 |
| --switchGit | -s | 无 | 切换Git账号 |
| --config | 无 | 无 | 配置Git账号 |
## 5. 使用示例
### 5.1 查看当前Git账号信息
```bash
daji git --info
# 或
daji git
```
执行此命令后,工具会输出当前Git账号的用户名和邮箱。
### 5.2 查看所有Git账号配置
```bash
daji git --info all
# 或
daji gitConfig --info all
```
执行此命令后,工具会输出所有已配置的Git账号信息。
### 5.3 切换Git账号
```bash
daji git --switchGit
# 或
daji git -s
# 或
daji gitConfig -s
```
执行此命令后,工具会显示已配置的Git账号列表,用户可以选择要切换的账号。
### 5.4 配置Git账号
```bash
daji git --config
# 或
daji gitConfig --config
```
执行此命令后,工具会提供以下配置选项:
- 导入Git账号配置
- 导出Git账号配置
- 更新Git账号配置
## 6. 实现原理
1. **查看Git账号信息**:
- 使用 `git config user.name` 和 `git config user.email` 命令获取当前Git账号信息
- 如果指定了 `all` 参数,则输出所有已配置的Git账号
2. **切换Git账号**:
- 读取 `data/git/config.json` 中的账号配置
- 显示账号列表供用户选择
- 使用 `git config --global user.name` 和 `git config --global user.email` 命令更新Git配置
3. **管理Git账号配置**:
- **导入配置**:从本地文件导入Git账号配置
- **导出配置**:将当前Git账号配置导出到本地文件
- **更新配置**:修改已配置的Git账号信息
## 7. 数据结构
Git账号配置存储在 `data/git/config.json` 文件中,格式如下:
```json
{
"账号1": {
"name": "用户名1",
"email": "邮箱1"
},
"账号2": {
"name": "用户名2",
"email": "邮箱2"
}
}
```
## 8. 依赖关系
- `../common/utils` - 通用工具函数
- `../common/_gitQuestion` - Git相关交互问题
- `../common/appListManage` - App列表管理
- `../data/git/config.json` - Git账号配置
# Host切换功能模块 (host.js)
## 1. 模块概述
Host切换功能模块用于管理和切换系统的Host文件,方便开发者在不同的开发环境间快速切换。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 查看Host信息 | 查看当前Host文件内容或所有已配置的Host |
| 切换Host | 从配置的Host列表中选择并切换Host |
| 重置Host | 清空Host文件内容 |
| 管理Host配置 | 导入、导出和创建Host配置 |
## 3. 命令格式
```bash
daji switchHost [cmd] [options]
# 或
daji host [cmd] [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --info | 无 | all 或 无 | 查看Host信息,all表示查看所有配置 |
| --switchHost | -s | 无 | 切换Host |
| --reset | -r | 无 | 重置Host文件内容 |
| --config | 无 | 无 | 配置Host |
## 5. 使用示例
### 5.1 查看当前Host信息
```bash
daji host --info
# 或
daji host
```
执行此命令后,工具会输出当前Host文件的内容。
### 5.2 查看所有Host配置
```bash
daji host --info all
# 或
daji switchHost --info all
```
执行此命令后,工具会输出所有已配置的Host信息。
### 5.3 切换Host
```bash
daji host --switchHost
# 或
daji host -s
# 或
daji switchHost -s
```
执行此命令后,工具会显示已配置的Host列表,用户可以选择要切换的Host。
### 5.4 重置Host
```bash
daji host --reset
# 或
daji host -r
# 或
daji switchHost -r
```
执行此命令后,工具会清空Host文件内容。
### 5.5 配置Host
```bash
daji host --config
# 或
daji switchHost --config
```
执行此命令后,工具会提供以下配置选项:
- 导入Host配置
- 导出Host配置
- 创建Host配置
## 6. 实现原理
1. **查看Host信息**:
- 读取系统Host文件内容并输出
- 如果指定了 `all` 参数,则输出所有已配置的Host
2. **切换Host**:
- 读取 `data/host/config.json` 中的Host配置
- 显示Host列表供用户选择
- 将选中的Host内容写入系统Host文件
3. **重置Host**:
- 将系统Host文件内容清空,只保留基本说明
- 清空已选择的Host记录
4. **管理Host配置**:
- **导入配置**:从本地文件导入Host配置
- **导出配置**:将当前Host配置导出到本地文件
- **创建配置**:从当前目录的txt文件创建Host配置
## 7. 数据结构
Host配置存储在 `data/host/config.json` 文件中,格式如下:
```json
{
"配置名称1": "Host内容1",
"配置名称2": "Host内容2"
}
```
已选择的Host记录存储在 `data/host/selected.json` 文件中,格式如下:
```json
["配置名称1", "配置名称2"]
```
## 8. 依赖关系
- `../common/utils` - 通用工具函数
- `../common/_HostQuestion` - Host相关交互问题
- `../common/appListManage` - App列表管理
- `../data/host/config.json` - Host配置
- `../data/host/selected.json` - 已选择的Host记录
# iOS模拟器管理模块 (ios.js)
## 1. 模块概述
iOS模拟器管理模块用于管理和操作iOS模拟器,支持启动模拟器、安装应用、打开指定URL等功能。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 启动模拟器 | 启动iOS模拟器 |
| 安装应用 | 在模拟器上安装应用 |
| 启动指定应用 | 启动模拟器并打开指定应用 |
| 打开URL | 在模拟器上打开指定URL |
| 转换URL | 转换URL格式 |
| 管理应用列表 | 添加、查看、移除和更新应用列表 |
| 配置管理 | 导入、导出和重置配置 |
## 3. 命令格式
```bash
daji ios [cmd] [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --start | -s | 应用名称或none | 启动模拟器,可指定应用或none表示仅启动模拟器 |
| --install | -i | 无 | 安装应用 |
| --yanxuan | -y | 无 | 启动模拟器并打开严选app |
| --url | -u | URL地址 | 在模拟器上打开指定URL |
| --translate | -t | URL地址 | 转换URL格式 |
| --add | 无 | 无 | 添加应用到列表 |
| --info | 无 | 应用名称 | 查看应用信息 |
| --remove | 无 | 应用名称 | 从列表中移除应用 |
| --update | 无 | 应用名称 | 更新应用信息 |
| --config | 无 | 无 | 配置管理 |
## 5. 使用示例
### 5.1 启动模拟器
```bash
# 启动模拟器并选择应用
daji ios --start
# 或
daji ios -s
# 仅启动模拟器,不打开应用
daji ios --start none
# 或
daji ios -s none
# 启动模拟器并打开指定应用
daji ios --start 应用名称
# 或
daji ios -s 应用名称
```
### 5.2 安装应用
```bash
daji ios --install
# 或
daji ios -i
```
执行此命令后,工具会显示应用列表,用户可以选择要安装的应用。
### 5.3 启动严选app
```bash
daji ios --yanxuan
# 或
daji ios -y
```
执行此命令后,工具会启动模拟器并打开严选app。
### 5.4 打开URL
```bash
# 在选择的应用中打开URL
daji ios --url https://example.com
# 或
daji ios -u https://example.com
# 在Safari中打开URL
daji ios safari --url https://example.com
# 或
daji ios safari -u https://example.com
# 在指定应用中打开URL
daji ios 应用名称 --url https://example.com
# 或
daji ios 应用名称 -u https://example.com
```
### 5.5 转换URL
```bash
daji ios --translate https://example.com
# 或
daji ios -t https://example.com
# 使用指定应用转换URL
daji ios 应用名称 --translate https://example.com
# 或
daji ios 应用名称 -t https://example.com
```
### 5.6 管理应用列表
```bash
# 添加应用
daji ios --add
# 查看应用信息
daji ios --info 应用名称
# 移除应用
daji ios --remove 应用名称
# 更新应用
daji ios --update 应用名称
```
### 5.7 配置管理
```bash
daji ios --config
```
执行此命令后,工具会提供以下配置选项:
- 导出配置
- 导入配置
- 自定义配置
- 重置配置
- 使用当前目录文件
## 6. 实现原理
1. **启动模拟器**:
- 使用 `xcrun simctl` 命令启动iOS模拟器
- 根据参数决定是否打开应用
- 如果指定了应用名称,则启动该应用
2. **安装应用**:
- 显示已配置的应用列表
- 用户选择要安装的应用
- 使用 `xcrun simctl install` 命令安装应用
3. **打开URL**:
- 根据参数决定在哪个应用中打开URL
- 转换URL格式(如果需要)
- 使用 `xcrun simctl openurl` 命令打开URL
4. **管理应用列表**:
- 添加应用:将应用信息添加到配置文件
- 查看应用:显示指定应用的信息
- 移除应用:从配置文件中移除应用
- 更新应用:修改配置文件中的应用信息
5. **配置管理**:
- 导出配置:将当前配置导出到本地文件
- 导入配置:从本地文件导入配置
- 自定义配置:手动编辑配置
- 重置配置:恢复默认配置
- 使用当前目录文件:使用当前目录的配置文件
## 7. 依赖关系
- `../common/iosTools` - iOS工具函数
- `../common/_IOSQuestion` - iOS相关交互问题
- `../common/appListManage` - App列表管理
- `../common/utils` - 通用工具函数
# IP地址获取模块 (ip.js)
## 1. 模块概述
IP地址获取模块用于获取当前设备的IP地址信息,包括IPv4和IPv6地址,以及主机名和系统信息。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 获取IP地址 | 获取当前设备的IPv4和IPv6地址 |
| 获取主机名 | 获取当前设备的主机名 |
| 获取系统信息 | 获取当前设备的系统类型和版本 |
## 3. 命令格式
```bash
daji ip [cmd] [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --ip | -p | 无 | 获取IP地址信息 |
## 5. 使用示例
### 5.1 获取IP地址信息
```bash
daji ip
# 或
daji ip --ip
# 或
daji ip -p
```
执行此命令后,工具会输出当前设备的IP地址信息,包括IPv4和IPv6地址、主机名和系统信息。
## 6. 输出格式
```json
{
"ipv4": ["192.168.1.100", "10.0.0.1"],
"ipv6": ["fe80::1", "2001:0db8::1"],
"hostName": "MyMacBook",
"system": "Darwin",
"release": "20.6.0"
}
```
## 7. 实现原理
- 使用Node.js的`os`模块获取网络接口信息
- 遍历所有网络接口,收集IPv4和IPv6地址
- 获取主机名和系统信息
- 将所有信息格式化为JSON输出
## 8. 依赖关系
- 无外部依赖,仅使用Node.js内置的`os`模块
# 密码生成模块 (password.js)
## 1. 模块概述
密码生成模块用于生成随机密码,支持自定义密码长度和包含的字符类型,如数字、符号、大写字母和小写字母。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 生成随机密码 | 生成指定长度和字符类型的随机密码 |
| 自定义字符类型 | 可以选择包含或不包含数字、符号、大写字母和小写字母 |
| 自定义密码长度 | 可以指定密码的长度,默认12位 |
## 3. 命令格式
```bash
daji password [options]
# 或
daji pwd [options]
```
## 4. 选项说明
| 选项 | 缩写 | 参数 | 描述 |
|------|------|------|------|
| --numbers | -n | 无 | 包含数字 |
| --symbols | -s | 无 | 包含符号 |
| --length | -l | 数字 | 密码长度,默认12位 |
| --uppercase | -u | 无 | 包含大写字母 |
| --lowercase | -d | 布尔值 | 包含小写字母,默认true |
| --all | -a | 数字 | 包含所有字符类型(数字、符号、大小写字母)并指定长度 |
## 5. 使用示例
### 5.1 生成默认密码
```bash
daji password
# 或
daji pwd
```
执行此命令后,工具会生成一个默认包含小写字母、长度为12位的随机密码。
### 5.2 生成包含数字和符号的密码
```bash
daji password -n -s
# 或
daji pwd -n -s
```
执行此命令后,工具会生成一个包含小写字母、数字和符号,长度为12位的随机密码。
### 5.3 生成指定长度的密码
```bash
daji password -l 16
# 或
daji pwd -l 16
```
执行此命令后,工具会生成一个长度为16位的随机密码。
### 5.4 生成包含所有字符类型的密码
```bash
daji password -n -s -u -l 20
# 或
daji pwd -n -s -u -l 20
```
执行此命令后,工具会生成一个包含小写字母、大写字母、数字和符号,长度为20位的随机密码。
### 5.5 生成不包含小写字母的密码
```bash
daji password -n -s -u -d false
# 或
daji pwd -n -s -u -d false
```
执行此命令后,工具会生成一个包含大写字母、数字和符号,不包含小写字母的随机密码。
### 5.6 生成包含所有字符类型的密码(简化方式)
```bash
daji password -a 16
# 或
daji pwd -a 16
```
执行此命令后,工具会生成一个包含小写字母、大写字母、数字和符号,长度为16位的随机密码。这是`daji password -n -s -u -l 16`的简化写法。
## 6. 实现原理
1. **字符集构建**:
- 根据用户指定的选项构建字符集
- 默认包含小写字母
- 根据选项决定是否包含数字、符号和大写字母
2. **密码生成**:
- 根据指定的长度,从构建好的字符集中随机选择字符
- 生成指定长度的密码字符串
3. **输出结果**:
- 将生成的密码输出到控制台
## 7. 依赖关系
- 无外部依赖,仅使用Node.js内置的Math.random()和fs模块
## 8. 输出示例
```
# 默认密码(只包含小写字母)
kggvjffzdkld
# 包含数字、符号和大写字母,长度16位
emNkZ7|>W#(L<sly
# 只包含数字和符号,长度8位
180%#[30
# 只包含大写字母和数字,长度10位
3JSTY5G4RI
```
# 路径处理模块 (path.js)
## 1. 模块概述
路径处理模块用于显示当前工作目录的路径,方便用户在命令行中查看当前位置。
## 2. 功能说明
| 功能 | 描述 |
|------|------|
| 显示当前路径 | 显示当前工作目录的绝对路径 |
## 3. 命令格式
```bash
daji path [cmd] [options]
```
## 4. 使用示例
### 4.1 显示当前路径
```bash
daji path
```
执行此命令后,工具会输出当前工作目录的绝对路径。
## 5. 实现原理
- 使用`child_process`模块执行系统命令`pwd`
- 捕获命令输出并显示给用户
## 6. 依赖关系
- 无外部依赖,仅使用Node.js内置的`child_process`模块
# Daji 项目架构说明
## 1. 项目概述
妲己(Daji)是一个命令行工具,定位为开发助手脚本,用于快速创建项目、调试和执行各种开发相关任务。
### 核心功能
- host 切换
- git 账号切换
- 查看IP地址
- 启动iOS模拟器
- 时间戳转换
- 工具设置配置项操作(导入导出)
## 2. 目录结构
```
Daji/
├── bin/
│ └── index.js # 项目入口文件
├── common/ # 通用组件和工具
│ ├── _GitQuestion.js # Git相关交互问题
│ ├── _HostQuestion.js # Host相关交互问题
│ ├── _IOSQuestion.js # iOS相关交互问题
│ ├── appListManage.js # App列表管理
│ ├── iosTools.js # iOS工具函数
│ ├── loading.js # 加载动画
│ ├── msgColor.js # 消息颜色处理
│ └── utils.js # 通用工具函数
├── data/ # 配置数据存储
│ ├── git/ # Git配置数据
│ ├── host/ # Host配置数据
│ ├── ios/ # iOS配置数据
│ └── _fileList.json # 文件列表
├── lib/ # 核心功能模块
│ ├── config.js # 配置管理
│ ├── date.js # 日期时间处理
│ ├── git.js # Git账号管理
│ ├── host.js # Host切换功能
│ ├── ios.js # iOS模拟器管理
│ ├── ip.js # IP地址获取
│ ├── path.js # 路径处理
│ ├── project.js # 项目管理
│ └── test.js # 测试模块
├── utils/ # UI和交互工具
│ ├── baseUI.js # 基础UI组件
│ ├── bottom-bar.js # 底部栏组件
│ └── readline.js # 命令行交互
├── .gitignore # Git忽略文件
├── package.json # 项目依赖配置
└── readme.md # 项目说明文档
```
## 3. 核心模块说明
### 3.1 入口模块 (bin/index.js)
- 基于 Commander.js 实现命令行交互
- 定义所有可用命令和选项
- 导入并调用各个功能模块
### 3.2 功能模块 (lib/)
| 模块 | 主要功能 | 对应命令 |
|------------|------------------------------------------|-------------------------|
| config.js | 配置项导入导出 | `daji config` |
| date.js | 时间戳转换 | `daji Date` 或 `daji d` |
| git.js | Git账号切换与管理 | `daji gitConfig` 或 `daji git` |
| host.js | Host文件切换与管理 | `daji switchHost` 或 `daji host` |
| ios.js | iOS模拟器管理 | `daji ios` |
| ip.js | IP地址获取 | `daji ip` |
| path.js | 当前路径信息显示 | `daji path` |
| project.js | 项目管理(已作废) | - |
| test.js | 测试模块(已作废) | - |
### 3.3 通用组件 (common/)
- 提供各种交互问题模板
- 实现加载动画和消息颜色处理
- 封装通用工具函数
### 3.4 数据存储 (data/)
- 按功能模块分类存储配置数据
- 支持配置项的导入导出
- 持久化保存用户设置
### 3.5 UI工具 (utils/)
- 实现命令行界面组件
- 处理用户输入和交互
- 提供底部状态栏等增强功能
## 4. 工作流程
1. 用户在命令行执行 `daji` 命令
2. `bin/index.js` 解析命令和选项
3. 根据命令调用对应的功能模块(如 `lib/ios.js`)
4. 功能模块调用通用组件和工具完成具体操作
5. 读取或写入数据到 `data/` 目录
6. 向用户返回结果或提示
## 5. 配置管理
- 所有配置数据存储在 `data/` 目录下
- 支持通过 `config` 命令导入导出配置
- 每个功能模块有独立的配置文件
- 配置文件采用 JSON 格式
## 6. 扩展机制
- 新增功能模块只需在 `lib/` 目录下创建新文件
- 在 `bin/index.js` 中注册新命令
- 配置数据自动存储到 `data/` 目录
- 可以复用 `common/` 和 `utils/` 中的工具函数
## 7. 技术栈
- Node.js
- Commander.js (命令行框架)
- 原生Node.js API
- 无其他外部依赖
## 8. 模块文档
详细的模块说明请参考各个模块的独立文档:
- [config.md](config.md) - 配置管理模块
- [date.md](date.md) - 日期时间处理模块
- [git.md](git.md) - Git账号管理模块
- [host.md](host.md) - Host切换功能模块
- [ios.md](ios.md) - iOS模拟器管理模块
- [ip.md](ip.md) - IP地址获取模块
- [path.md](path.md) - 路径处理模块
- [password.md](password.md) - 密码生成模块
# Daji 项目升级分析报告
## 1. 项目概述
Daji 是一个命令行工具,用于辅助开发工作,包括 host 切换、git 账号切换、查看 IP 地址、启动 iOS 模拟器、时间戳转换等功能。该项目已有 6 年历史,使用的依赖和 Node.js API 可能与最新的 Node.js 22.x 版本不兼容。
## 2. 依赖分析
| 依赖名称 | 当前版本 | 最新版本 | 状态 | 建议 |
|----------|----------|----------|------|------|
| commander | 2.14.1 | 12.x | 严重过时 | 升级到最新版本 |
| inquirer | 5.1.0 | 12.x | 严重过时 | 升级到最新版本 |
| colors-cli | 1.0.13 | 1.0.32 | 过时 | 升级到最新版本 |
| lodash | 4.3.0 | 4.17.21 | 较旧 | 升级到最新版本 |
| moment | 2.24.0 | 2.30.1 | 较旧 | 考虑替换为 dayjs 或内置 API |
| getfiles | 1.1.0 | 无 | 可能不再维护 | 替换为 Node.js 内置 fs 模块 |
| cfiles | 1.0.3 | 无 | 可能不再维护 | 替换为 Node.js 内置 fs 模块 |
| ansi-escapes | 3.0.0 | 4.3.2 | 过时 | 升级到最新版本 |
| mute-stream | 0.0.7 | 1.0.0 | 严重过时 | 升级到最新版本 |
| through | 2.3.6 | 2.3.8 | 较旧 | 考虑替换为内置流 API |
| cmdify | 0.0.4 | 0.0.4 | 不再维护 | 替换为内置 path 模块 |
## 3. 核心模块升级建议
### 3.1 入口模块 (bin/index.js)
**问题**:
- 使用了过时的 commander 版本 (2.14.1)
- 命令定义方式与新版本不兼容
- 重复调用 program.parse(process.argv)
**建议**:
- 升级 commander 到最新版本 (12.x)
- 重写命令定义,使用新版本的 API
- 移除重复的 program.parse() 调用
### 3.2 配置管理模块 (lib/config.js)
**问题**:
- 使用了 getfiles 和 cfiles 第三方库
- 异步操作处理方式可以优化
- 使用了过时的 API
**建议**:
- 替换 getfiles 和 cfiles 为 Node.js 内置的 fs/promises 模块
- 优化异步操作,使用更简洁的语法
- 升级文件操作 API 到最新版本
### 3.3 日期时间处理模块 (lib/date.js)
**问题**:
- 使用了 moment 库,体积较大
- 可以使用更轻量级的替代方案
**建议**:
- 考虑替换为 dayjs 库(更轻量级)
- 或使用 Node.js 内置的 Intl.DateTimeFormat API
- 保留核心功能,优化代码结构
### 3.4 Git 账号管理模块 (lib/git.js)
**问题**:
- 使用了 child_process.exec(),安全性较低
- 依赖外部命令,可能在不同环境下表现不一致
**建议**:
- 考虑使用更安全的 child_process.execSync() 或 promisify 包装的异步版本
- 优化错误处理
- 升级代码结构
### 3.5 Host 切换功能模块 (lib/host.js)
**问题**:
- 直接修改系统 Host 文件,需要管理员权限
- 使用了过时的文件操作 API
**建议**:
- 优化权限处理,添加适当的错误提示
- 升级文件操作 API 到最新版本
- 增强安全性检查
### 3.6 iOS 模拟器管理模块 (lib/ios.js)
**问题**:
- 依赖 xcrun 命令,仅适用于 macOS
- 使用了过时的 inquirer 版本
- 代码结构较为复杂
**建议**:
- 保持核心功能,优化代码结构
- 升级 inquirer 到最新版本
- 增强错误处理和跨平台兼容性
### 3.7 IP 地址获取模块 (lib/ip.js)
**问题**:
- 代码结构简单,可以进一步优化
- 使用了 JSON.stringify 输出,格式固定
**建议**:
- 优化代码结构,使用更简洁的语法
- 考虑添加更多网络信息
- 保持核心功能不变
### 3.8 路径处理模块 (lib/path.js)
**问题**:
- 使用了 child_process.exec('pwd'),效率较低
- 可以直接使用 Node.js 内置 API
**建议**:
- 替换为 process.cwd() 或 path.resolve()
- 简化代码结构
## 4. Node.js 22.x 兼容性问题
### 4.1 已移除的 API
| API | 状态 | 建议替换方案 |
|-----|------|--------------|
| Buffer() 构造函数 | 已废弃 | Buffer.alloc() 或 Buffer.from() |
| fs.exists() | 已废弃 | fs.promises.access() |
| crypto.createCipher() | 已废弃 | crypto.createCipheriv() |
| crypto.createDecipher() | 已废弃 | crypto.createDecipheriv() |
### 4.2 不推荐使用的 API
| API | 状态 | 建议替换方案 |
|-----|------|--------------|
| child_process.exec() | 不推荐 | child_process.execSync() 或 promisify 包装 |
| fs.readFile() 回调形式 | 不推荐 | fs.promises.readFile() |
| fs.writeFile() 回调形式 | 不推荐 | fs.promises.writeFile() |
### 4.3 新增的有用 API
| API | 用途 | 建议使用场景 |
|-----|------|--------------|
| fs/promises 模块 | 异步文件操作 | 所有文件操作场景 |
| util.promisify() | 回调转 Promise | 处理旧版 API |
| process.cwd() | 获取当前工作目录 | 替代 pwd 命令 |
| os.networkInterfaces() | 获取网络接口信息 | IP 地址获取 |
| Intl.DateTimeFormat | 日期时间格式化 | 替代 moment 库 |
## 5. 升级计划
### 5.1 第一阶段:依赖升级
1. 升级核心依赖到最新版本
- commander: ^12.0.0
- inquirer: ^12.0.0
- colors-cli: ^1.0.32
- lodash: ^4.17.21
2. 替换过时依赖
- 替换 getfiles 和 cfiles 为 Node.js 内置 fs 模块
- 考虑替换 moment 为 dayjs 或内置 API
- 替换 cmdify 为 path 模块
### 5.2 第二阶段:API 升级
1. 升级文件操作 API
- 替换所有回调形式的 fs 操作为 Promise 形式
- 使用 fs/promises 模块进行文件操作
2. 升级子进程 API
- 替换 child_process.exec() 为更安全的 API
- 优化错误处理
3. 升级命令行界面
- 使用新版本 commander API 重写命令定义
- 优化用户交互体验
### 5.3 第三阶段:代码重构
1. 优化代码结构
- 统一代码风格
- 优化异步操作处理
- 增强错误处理
2. 移除冗余代码
- 移除已废弃的功能
- 简化复杂模块
3. 增强安全性
- 添加输入验证
- 优化权限处理
- 增强错误提示
### 5.4 第四阶段:测试和验证
1. 在 Node.js 22.x 环境下测试所有功能
2. 验证跨平台兼容性
3. 测试边界情况
4. 优化性能
## 6. 预期收益
1. **兼容性**:支持最新的 Node.js 22.x 版本
2. **安全性**:使用更安全的 API,减少潜在漏洞
3. **性能**:优化代码结构,提高执行效率
4. **可维护性**:使用最新的依赖和 API,便于后续维护和扩展
5. **用户体验**:优化命令行界面,提供更好的交互体验
## 7. 风险评估
1. **依赖兼容性风险**:升级依赖可能导致 API 不兼容,需要重写部分代码
2. **功能回归风险**:修改核心功能可能导致原有功能失效
3. **跨平台兼容性风险**:不同操作系统下的行为可能不一致
4. **测试覆盖风险**:需要全面测试所有功能,确保升级后正常工作
## 8. 结论
Daji 项目需要进行全面升级,以支持最新的 Node.js 22.x 版本。升级工作包括依赖升级、API 升级、代码重构和测试验证。通过升级,可以提高项目的兼容性、安全性、性能和可维护性,为用户提供更好的使用体验。
建议按照升级计划分阶段进行,确保每一步都经过充分测试,减少风险。同时,保持核心功能不变,专注于升级底层依赖和 API,确保用户的使用习惯不受影响。
const utils = require('../common/utils');
const log = utils.msg;
/**
* 生成随机密码
* @param {string} cmd - 命令参数
* @param {object} options - 命令选项
*/
function passwordTools(cmd, options) {
let { numbers: includeNumbers, symbols: includeSymbols, length = 12, uppercase: includeUppercase, lowercase: includeLowercase, all: includeAll } = options;
// 如果指定了all选项,覆盖其他选项,包含所有字符类型
if (includeAll) {
includeNumbers = true;
includeSymbols = true;
includeUppercase = true;
includeLowercase = true;
length = includeAll;
}
// 定义字符集
const lowercaseLetters = 'abcdefghijklmnopqrstuvwxyz';
const uppercaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const numbers = '0123456789';
const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
// 根据参数构建字符集
let charSet = '';
// 将includeLowercase转换为布尔值
const shouldIncludeLowercase = includeLowercase !== false && includeLowercase !== 'false';
// 默认包含小写字母
if (shouldIncludeLowercase) {
charSet += lowercaseLetters;
}
// 如果指定了大写字母,添加到字符集
if (includeUppercase) {
charSet += uppercaseLetters;
}
// 如果指定了数字,添加到字符集
if (includeNumbers) {
charSet += numbers;
}
// 如果指定了符号,添加到字符集
if (includeSymbols) {
charSet += symbols;
}
// 如果字符集为空,使用默认字符集
if (!charSet) {
charSet = lowercaseLetters;
}
// 生成指定长度的密码
let password = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charSet.length);
password += charSet[randomIndex];
}
// 输出密码
log.info(password);
}
module.exports = passwordTools;
+90
-105
#!/usr/bin/env node
const program = require('commander'),
appInfo = require('./../package.json'),
project = require('../lib/project.js'),
ios = require('../lib/ios.js'),
host = require('../lib/host.js');
ip = require('../lib/ip.js'),
git = require('../lib/git.js'),
test = require('../lib/test.js'),
_path = require('../lib/path.js'),
config = require('../lib/config'),
date = require('../lib/date'),
const { Command } = require('commander');
const appInfo = require('./../package.json');
// 暂时注释掉ios模块,因为它依赖于已移除的through模块
// const ios = require('../lib/ios.js');
const host = require('../lib/host.js');
const ip = require('../lib/ip.js');
const git = require('../lib/git.js');
const _path = require('../lib/path.js');
const config = require('../lib/config');
const date = require('../lib/date');
const password = require('../lib/password');
const color = require('colors-cli/toxic');
color = require('colors-cli/toxic');
// 创建 commander 实例
const program = new Command();
// 配置程序信息
program
// .allowUnknownOption()//不报错误
.name('daji')
.version(`daji@${appInfo.version}`, '-v, --version')
.usage('妲己是个小能手,什么都可以做,目前还正在学习ing'.x31 + ' [options] <package>')
.description(`目前正在测试ing,而且此工具基本不对外`.x33 + `当前版本${appInfo.version}`)
.parse(process.argv);
.description(`目前正在测试ing,而且此工具基本不对外`.x33 + `当前版本${appInfo.version}`);
// 创建工程 作废
// program
// .command('project [cmd]')
// .alias('p')
// .description('this is my test project '.x29)
// .option('-i, --init [type]', '创建工程')
// .option('-t, --test [type]', '测试')
// .action(function (cmd, options) {
// const a = typeof options.name === 'string' ? options.name : ''
// project(cmd, options);
// }).on('--help', function () {
// console.log('welcome for Daji');
// });
// ios 模拟器
// ios 模拟器命令 - 暂时注释,因为依赖已移除的through模块
/*
program
.command('ios [cmd]')
.description('this is my ios simulator'.x29)
.command('ios')
.description('这个是基于xcode的模拟器,用来快速在对应iphone上调试H5页面,初期启动需要1分钟左右来安装客户端'.x29)
.option('-s --start [type]', '启动模拟器')
.option('-i --install [type]', '安装客户端(每个simulator的安装包是独立的,所以需要保持simulator的激活状态)')
// .option('-d --delete [type]', '卸载客户端')
.option('-y --yanxuan [type]', '启动模拟器并打开严选app')
.option('-u --url [type]', '必须跟参数,直接打开参数所带的H5地址')
.option('-t --translate [type]', 'encode url地址,用于生辰更直接在客户端内执行的命令')
// .option('--init [type]', '初始化appList')
.option('-s, --start [type]', '启动模拟器')
.option('-i, --install [type]', '安装客户端(每个simulator的安装包是独立的,所以需要保持simulator的激活状态)')
.option('-y, --yanxuan [type]', '启动模拟器并打开严选app')
.option('-u, --url [type]', '必须跟参数,直接打开参数所带的H5地址')
.option('-t, --translate [type]', 'encode url地址,用于生成更直接在客户端内执行的命令')
.option('--add [type]', '对本地list添加app信息')
.option('--info [type]', '获取指定app的信息')
.option('--remove [type]', '移除指定app')
.option('--update [type]', '更新指定app信息')
.option('--remove [type]', '移除指定app')
.option('--info [type]', '获取指定app的信息')
.option('--config [type]', '同步配置项')
.action(function (cmd, options) {
.action((options, command) => {
// 获取额外的参数作为cmd
const cmd = command.args[0];
ios(cmd, options);
}).on('--help', function () {
console.log('ios simulator'.x29);
})
});
*/
// host 切换命令
program
.command('switchHost [cmd]')
.command('switchHost')
.alias('host')
.description('简易host切换工具'.x29)
.alias('host')
.option('-s --switchHost [type]', '选择切换Host')
.option('-r --reset [type]', '清空 Host 文件内容(重置)')
.option('-s, --switchHost [type]', '选择切换Host')
.option('-r, --reset [type]', '清空 Host 文件内容(重置)')
.option('--info [type]', '查看当前Host信息')
.option('--config [type]', '配置文件操作')
.action((cmd, options) => {
.action((options, command) => {
const cmd = command.args[0];
host(cmd, options);
}).on('--help', () => {
console.log('SwitchHost'.x29);
})
});
// git 配置命令
program
.command('gitConfig [cmd]')
.command('gitConfig')
.alias('git')
.description('git相关指令'.x29)
.option('--info [type]', '查看git当前账户信息')
.option('-s --switchGit [type]', '切换账户')
.option('-s, --switchGit [type]', '切换账户')
.option('--config [type]', '操作配置')
.description('git相关指令'.x29)
.action(function (cmd, options) {
.action((options, command) => {
const cmd = command.args[0];
git(cmd, options);
}).on('--help', function () {
console.log('切换配置');
})
});
// ip 命令
program
.command('ip [cmd]')
.option('-p --ip [type]', '获取ip')
.command('ip')
.description('get this mac\'s ip'.x29)
.action(function (cmd, options) {
.option('-p, --ip [type]', '获取ip')
.action((options, command) => {
const cmd = command.args[0];
ip(cmd, options);
}).on('--help', () => {
console.log('获取ip');
})
});
// path 命令
program
.command('path [cmd]')
.command('path')
.description('当前路径信息'.x29)
.action((cmd, options) => {
.action((options, command) => {
const cmd = command.args[0];
_path(cmd, options);
}).on('--help', () => {
// console.log('获取路径信息');
})
});
// config 命令
program
.command('config [cmd]')
.command('config')
.description('配置项的相关操作'.x29)
.option('-i --install [type]', '将当前目录记录的配置文件全部导入工具')
.option('-b --backup [type]', '将当前配置项全部进行备份')
.action((cmd, options) => {
.option('-i, --install [type]', '将当前目录记录的配置文件全部导入工具')
.option('-b, --backup [type]', '将当前配置项全部进行备份')
.action((options, command) => {
const cmd = command.args[0];
config(cmd, options);
}).on('--help', () => {
// console.log('获取路径信息');
})
});
// date 命令
program
.command('Date [cmd]')
.command('Date')
.alias('d')
.description('时间戳转换工具'.x29)
.option('-t --Timestamp [type]', '获取当前时间戳')
.action((cmd, options) => {
date(cmd, options)
}).on('--help', () => {
// console.log('获取路径信息');
})
// program
// .command('testCode [cmd]')
// .alias('test')
// .option('-i --init [type]', '查看当前信息')
.option('-t, --Timestamp [type]', '获取当前时间戳')
.action((options, command) => {
const cmd = command.args[0];
date(cmd, options);
});
// .description('just test code'.x29)
// .action(function (cmd, options) {
// test(cmd, options);
// }).on('--help', function () {
// console.log('testCode');
// })
// password 命令
program
.command('password')
.alias('pwd')
.description('密码生成工具'.x29)
.option('-n, --numbers', '包含数字')
.option('-s, --symbols', '包含符号')
.option('-l, --length <number>', '密码长度,默认12位', 12)
.option('-u, --uppercase', '包含大写字母')
.option('-d, --lowercase <boolean>', '包含小写字母,默认true', true)
.option('-a, --all <number>', '包含所有字符类型(数字、符号、大小写字母)并指定长度')
.action((options, command) => {
const cmd = command.args[0];
password(cmd, options);
});
//默认不传参数输出help
// 默认显示帮助
if (!process.argv[2]) {
// console.log('test 木有参数');
program.help();
}
}
// 解析命令行参数
program.parse(process.argv);
// host
const utils = require('daji/common/utils');
const utils = require('./utils');

@@ -6,0 +6,0 @@ const inquirer = require('inquirer');

// host
const utils = require('daji/common/utils');
const utils = require('./utils');

@@ -6,0 +6,0 @@ const inquirer = require('inquirer');

@@ -5,3 +5,4 @@ /*

const msg = require('./msgColor');
const fs = require('fs');
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');

@@ -16,84 +17,49 @@ const process = require('child_process');

common.prototype.file = {
set: function (file, message, opation) {
return new Promise((resolve, reject) => {
const dir = path.resolve(__dirname, file);
fs.appendFile(dir, message, (err) => {
if (err) {
reject(err);
}
resolve();
});
})
// 追加文件内容
set: async function (file, message) {
const dir = path.resolve(__dirname, file);
await fs.appendFile(dir, message);
},
reset: function (file, message) {
return new Promise((resolve, reject) => {
const dir = path.resolve(__dirname, file);
fs.writeFile(dir, message, (err) => {
if (err) {
reject(err);
}
resolve();
});
});
// 写入文件内容(覆盖)
reset: async function (file, message) {
const dir = path.resolve(__dirname, file);
await fs.writeFile(dir, message, 'utf8');
},
read: function (file) {
return new Promise((resolve, reject) => {
const dir = path.resolve(__dirname, file);
fs.readFile(dir, 'utf8', (err, data) => {
if (err) {
reject(err);
}
resolve(data);
});
});
// 读取文件内容
read: async function (file) {
const dir = path.resolve(__dirname, file);
return await fs.readFile(dir, 'utf8');
},
readdir: function (path) {
return new Promise((resolve, reject) => {
fs.readdir(path, (err, fd) => {
if (err) {
reject(err);
}
resolve();
});
});
// 读取目录内容
readdir: async function (dirPath) {
return await fs.readdir(dirPath);
},
readdirSync: function (path, callback) {
return new Promise((resolove, reject) => {
const file = fs.readdirSync(path);
resolve(file);
});
// 同步读取目录内容
readdirSync: function (dirPath) {
return fsSync.readdirSync(dirPath);
},
// 获取指定目录下指定文件合集(内部调用方法)
getFile: function (root, fileType) {
console.log(root);
return new Promise((resolve, reject) => {
const file = fs.readdirSync(root);
const array = file.filter((name) => {
const arr = name.split('.');
return fileType.includes(arr[arr.length - 1])
})
resolve(array);
})
// 获取指定目录下指定文件合集
getFile: async function (root, fileType) {
const files = await fs.readdir(root);
return files.filter((name) => {
const arr = name.split('.');
return fileType.includes(arr[arr.length - 1]);
});
},
open: function (file) {
return new Promise((resolve, reject) => {
fs.open(file, 0666, (err, d) => {
if (err) {
throw err
}
resolve()
});
})
// 打开文件
open: async function (file) {
await fs.open(file, 0o666);
},
create: function (file, message, callback) {
const _this = this;
// 创建文件
async create(file, message) {
const array = file.split('/');
const name = array[array.length - 1];
if (name.indexOf('.') < 0) {

@@ -104,63 +70,40 @@ console.error('当前目录地址格式错误');

var root = file.substring(0, file.indexOf(name));
common.exists({
path: file,
callback: function (data) {
if (data) {
console.error(file + '对应目录文件已存在,创建失败');
} else {
common.mkdirSync(root, () => {
_this.reset(file, message).then(callback());
});
}
}
});
const root = file.substring(0, file.indexOf(name));
try {
// 检查文件是否存在
await fs.access(file);
console.error(`${file}对应目录文件已存在,创建失败`);
} catch (err) {
// 文件不存在,创建目录和文件
await fs.mkdir(root, { recursive: true });
await this.reset(file, message);
}
},
// 创建目录
mkdirSync: function (root) {
return new Promise((resolve, reject) => {
fs.mkdir(root, 0777, (err) => {
if (err) {
// console.error(root + ' =>对应目录已存在');
reject(err);
} else {
// console.tip(root + '=> 目录已创建完成');
}
resolve();
});
});
try {
fsSync.mkdirSync(root, { recursive: true });
} catch (err) {
// 目录已存在,忽略错误
}
},
// 判断文件是否存在
hasFile: async (obj) => {
return new Promise((resolve, reject) => {
fs.stat(obj.path, false, (err, stats) => {
if (!!stats) {
resolve(stats)
} else {
reject();
}
})
})
try {
return await fs.stat(obj.path);
} catch (err) {
throw err;
}
},
// 读取文件
readFile: (obj) => {
return new Promise((resolve, reject) => {
let dir = obj.path;
if (obj.isAbsolute) {
dir = path.resolve(__dirname, obj.path);
}
fs.readFile(dir, obj.encode || 'utf8', (err, file) => {
if (err) {
reject(err);
} else {
resolve(file);
}
// resolve(err, file);
// obj.callback(err, file);
});
})
readFile: async (obj) => {
let dir = obj.path;
if (obj.isAbsolute) {
dir = path.resolve(__dirname, obj.path);
}
return await fs.readFile(dir, obj.encode || 'utf8');
},

@@ -174,3 +117,3 @@

const dir = path.resolve(__dirname, file);
const fileStr = fs.readFileSync(dir);
const fileStr = fsSync.readFileSync(dir, 'utf8');
return JSON.parse(fileStr);

@@ -177,0 +120,0 @@ }

@@ -1,17 +0,25 @@

const path = require('path')
const process = require('child_process');
const getFile = require('getfiles');
const cFile = require('cfiles');
const path = require('path');
const fs = require('fs').promises;
const utils = require('../common/utils');
const _fileList = require('../data/_fileList.json');
const question = require('../common/_gitQuestion');
const appListManage = require('../common/appListManage');
const _gitConfig = require('../data/git/config.json');
const log = utils.msg;
const _defaultConfigFileName = 'gitConfig.json';
const _defaultConfigFileName = 'gitConfig.json'
const _getFile = new getFile();
// 选择设置、删除、清空
// 递归遍历目录,获取所有JSON文件
async function getJsonFiles(dirPath) {
const entries = await fs.readdir(dirPath, { withFileTypes: true });
let files = [];
for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name);
if (entry.isDirectory()) {
const subFiles = await getJsonFiles(fullPath);
files = [...files, ...subFiles];
} else if (entry.isFile() && entry.name.endsWith('.json')) {
files.push(fullPath);
}
}
return files;
}

@@ -22,15 +30,16 @@ class App {

this.state = {
cmd, options
}
cmd,
options
};
}
init() {
const { options, cmd } = this.state;
const { options } = this.state;
const { install, backup } = options;
if (install) {
console.log('导入备份')
console.log('导入备份');
this.doImportBack();
} else if (backup) {
this.doBackUp()
this.doBackUp();
}

@@ -41,21 +50,25 @@ }

async doBackUp() {
const _cFile = new cFile();
const fileList = await this.getList({
root: '../data',
absolute: true,
});
try {
const dataDir = path.resolve(__dirname, '../data');
const fileList = await getJsonFiles(dataDir);
const fileListLength = fileList.length
for (let i = 0; i < fileListLength; i += 1) {
const _json = path.parse(fileList[i]);
if (_json.name.indexOf('_') < 0) {
const _url = path.format({
root: './',
dir: `backup/${_json.dir.split('/').pop()}`,
base: _json.base
})
utils.file.readFile({ path: fileList[i] }).then((data) => {
_cFile.create(path.resolve(_url), data)
})
for (const filePath of fileList) {
const parsedPath = path.parse(filePath);
if (parsedPath.name.indexOf('_') < 0) {
const relativeDir = path.relative(dataDir, parsedPath.dir);
const backupDir = path.join('./backup', relativeDir);
const backupPath = path.join(backupDir, parsedPath.base);
// 确保备份目录存在
await fs.mkdir(backupDir, { recursive: true });
// 读取并写入文件
const data = await fs.readFile(filePath, 'utf8');
await fs.writeFile(backupPath, data, 'utf8');
}
}
log.success('备份完成');
} catch (error) {
log.error(`备份失败: ${error.message}`);
}

@@ -66,40 +79,29 @@ }

async doImportBack() {
const fileList = await this.getList({ root: './' });
for (let i = 0; i < fileList.length; i += 1) {
const _json = path.parse(fileList[i]);
const root = path.resolve(__dirname, )
utils.file.readFile({ path: fileList[i]}).then((data)=>{
utils.file.reset(`../data/${_json.dir.split('/').pop()}/${_json.base}`,data)
})
try {
const backupDir = path.resolve('./backup');
const fileList = await getJsonFiles(backupDir);
for (const filePath of fileList) {
const parsedPath = path.parse(filePath);
const relativeDir = path.relative(backupDir, parsedPath.dir);
const dataPath = path.join(__dirname, '../data', relativeDir, parsedPath.base);
// 确保数据目录存在
await fs.mkdir(path.dirname(dataPath), { recursive: true });
// 读取并写入文件
const data = await fs.readFile(filePath, 'utf8');
await fs.writeFile(dataPath, data, 'utf8');
}
log.success('导入完成');
} catch (error) {
log.error(`导入失败: ${error.message}`);
}
}
getList(param) {
const { root, absolute } = param;
let _root = root;
if (absolute) {
_root = path.resolve(__dirname, root)
}
return new Promise((resolve) => {
_getFile.getResult({
root: _root,
suffix: ['json'],
callback: function (arr) {
resolve(arr)
}
});
})
}
}
module.exports = (cmd, options) => {
const app = new App({ cmd, options });
app.init();
}

@@ -1,14 +0,24 @@

const path = require('path')
const moment = require('moment');
const process = require('child_process');
const path = require('path');
const utils = require('../common/utils');
const log = utils.msg;
// 格式化日期
function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds);
}
// 选择设置、删除、清空
class App {

@@ -18,5 +28,5 @@ constructor(props) {

this.state = {
cmd, options
}
cmd,
options
};
}

@@ -27,49 +37,40 @@

const { Timestamp } = options;
const _d = Date.parse(new Date())
const now = new Date();
const currentTimestamp = now.getTime();
if (!!cmd && /^\d*$/.test(cmd)) {
// 如果cmd是数字字符串,视为时间戳
if (cmd && /^\d+$/.test(cmd)) {
try {
const _cmd = parseInt(cmd, 10)
log.info(moment(_cmd).format('YYYY-MM-DD HH:mm:ss'))
const timestamp = parseInt(cmd, 10);
const date = new Date(timestamp);
log.info(formatDate(date));
} catch (error) {
log.error('时间戳格式不对')
log.error('时间戳格式不对');
}
} else {
if (!!Timestamp) {
let _time = '00:00:00';
if (!!cmd) {
_time = cmd;
}
console.log(`${Timestamp} ${_time}`)
log.info(moment(`${Timestamp} ${_time}`).format('x'));
} else if (Timestamp) {
// 将日期字符串转换为时间戳
let timeStr = '00:00:00';
if (cmd) {
timeStr = cmd;
}
const dateStr = `${Timestamp} ${timeStr}`;
const date = new Date(dateStr);
if (isNaN(date.getTime())) {
log.error('日期格式不对,请使用YYYY-MM-DD HH:mm:ss格式');
} else {
log.info(_d)
log.info(moment(_d).format('YYYY-MM-DD HH:mm:ss'))
log.info(date.getTime());
}
} else {
// 输出当前时间戳和格式化日期
log.info(currentTimestamp);
log.info(formatDate(now));
}
}
}
module.exports = (cmd, options) => {
const app = new App({ cmd, options });
app.init();
}
+32
-29

@@ -1,36 +0,39 @@

const os = require("os");
function ipTools (cmd, opations) {
const hostName = os.hostname();
const ifaces = os.networkInterfaces();
const ipv4 = [];
const ipv6=[];
for (var x in ifaces) {
for (var y in ifaces[x]) {
var object = ifaces[x][y];
if (object["family"] === 'IPv4') {
ipv4.push(object.address);
} else if (object["family"] === 'IPv6'){
ipv6.push(object.address);
}
/**
* 获取当前设备的IP地址信息
* @param {string} cmd - 命令参数
* @param {object} options - 命令选项
*/
function ipTools(cmd, options) {
const hostName = os.hostname();
const ifaces = os.networkInterfaces();
const ipv4 = [];
const ipv6 = [];
// 遍历所有网络接口
for (const interfaceName in ifaces) {
const interfaces = ifaces[interfaceName];
for (const networkInterface of interfaces) {
if (networkInterface.family === 'IPv4' && !networkInterface.internal) {
ipv4.push(networkInterface.address);
} else if (networkInterface.family === 'IPv6' && !networkInterface.internal) {
ipv6.push(networkInterface.address);
}
}
var json = {
ipv4,
ipv6,
hostName,
system: os.type(),
release: os.release(),
};
return console.log( JSON.stringify(json,'',4) );
}
// 构建结果对象
const result = {
ipv4,
ipv6,
hostName,
system: os.type(),
release: os.release()
};
// 输出格式化的JSON结果
console.log(JSON.stringify(result, null, 4));
}
module.exports = ipTools;

@@ -1,11 +0,7 @@

const process = require('child_process');
function pathTools (cmd, opations) {
process.exec(`pwd`, (err, stdout, stderr)=>{
console.log(stdout);
})
// 获取当前工作目录路径
function pathTools(cmd, options) {
// 使用process.cwd()替代pwd命令,更高效安全
console.log(process.cwd());
}
module.exports = pathTools;
{
"name": "daji",
"version": "1.4.4",
"version": "2.0.0",
"description": "",

@@ -13,3 +13,3 @@ "main": "index.js",

"type": "git",
"url": "git@github.com:cpu220/Daji.git"
"url": "git+ssh://git@github.com/cpu220/Daji.git"
},

@@ -20,13 +20,7 @@ "bin": {

"dependencies": {
"colors-cli": "~1.0.13",
"inquirer": "~5.1.0",
"commander": "~2.14.1",
"lodash": "^4.3.0",
"mute-stream": "0.0.7",
"ansi-escapes": "^3.0.0",
"cmdify": "^0.0.4",
"through": "^2.3.6",
"getfiles": "1.1.0",
"moment":"2.24.0",
"cfiles": "1.0.3"
"colors-cli": "^1.0.32",
"inquirer": "^12.0.0",
"commander": "^12.0.0",
"lodash": "^4.17.21",
"ansi-escapes": "^4.3.2"
},

@@ -37,2 +31,2 @@ "bugs": {

"homepage": "https://github.com/cpu220/Daji"
}
}