electerm-data-tool 1.0.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/LICENSE +21 -0
- package/README.md +264 -0
- package/package.json +63 -0
- package/src/common/app-props.js +24 -0
- package/src/common/log.js +1 -0
- package/src/common/pass-enc.js +53 -0
- package/src/common/uid.js +5 -0
- package/src/common/version-compare.js +25 -0
- package/src/index.js +234 -0
- package/src/migrate/index.js +85 -0
- package/src/migrate/migrate-1-to-2.js +117 -0
- package/src/migrate/v1.25.0.js +48 -0
- package/src/migrate/v1.27.17.js +66 -0
- package/src/migrate/v1.3.9.js +44 -0
- package/src/migrate/v1.32.36.js +44 -0
- package/src/migrate/v1.34.20.js +43 -0
- package/src/migrate/v1.34.59.js +32 -0
- package/src/migrate/v1.5.13.js +57 -0
- package/src/migrate/v1.7.0.js +36 -0
- package/src/migrate/version-upgrade.js +39 -0
- package/src/nedb.js +52 -0
- package/src/sqlite.js +132 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 electerm
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Electerm Data Tool
|
|
2
|
+
|
|
3
|
+
A command-line utility for managing Electerm application data, including database migration from v1 (NeDB) to v2 (SQLite) and data export functionality.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔄 **Database Migration**: Migrate Electerm data from v1 (NeDB) to v2 (SQLite)
|
|
8
|
+
- 📤 **Data Export**: Export all Electerm data to a single JSON file with decrypted passwords
|
|
9
|
+
- 📊 **Database Info**: Display information about your current Electerm database
|
|
10
|
+
- 🔐 **Password Decryption**: Automatically decrypt passwords during export for readable backups
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### Quick Start with npx (Recommended)
|
|
15
|
+
|
|
16
|
+
No installation required! Run the tool directly using `npx`:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx electerm-data-tool migrate
|
|
20
|
+
npx electerm-data-tool export ~/backup.json
|
|
21
|
+
npx electerm-data-tool info
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Global Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g electerm-data-tool
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
### Command Overview
|
|
33
|
+
|
|
34
|
+
**Using npx (no installation required):**
|
|
35
|
+
```bash
|
|
36
|
+
npx electerm-data-tool [command] [options]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Using globally installed version:**
|
|
40
|
+
```bash
|
|
41
|
+
electerm-data-tool [command] [options]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Available commands:
|
|
45
|
+
|
|
46
|
+
- `migrate` - Migrate database from v1 to v2
|
|
47
|
+
- `export <path>` - Export all data to JSON file
|
|
48
|
+
- `info` - Display database information
|
|
49
|
+
- `--help` - Show help information
|
|
50
|
+
- `--version` - Show version number
|
|
51
|
+
|
|
52
|
+
### 1. Database Migration
|
|
53
|
+
|
|
54
|
+
Migrate your Electerm database from v1 (NeDB) to v2 (SQLite):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
electerm-data-tool migrate
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This command will:
|
|
61
|
+
- Check if migration is needed
|
|
62
|
+
- Migrate all data from NeDB files to SQLite database
|
|
63
|
+
- Create backups of original NeDB files with timestamp
|
|
64
|
+
- Perform any necessary data upgrades
|
|
65
|
+
|
|
66
|
+
**Note**: Requires Node.js 22.0.0 or higher for SQLite support.
|
|
67
|
+
|
|
68
|
+
### 2. Data Export
|
|
69
|
+
|
|
70
|
+
Export all Electerm data to a JSON file with decrypted passwords:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
electerm-data-tool export /path/to/backup.json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Example:
|
|
77
|
+
```bash
|
|
78
|
+
electerm-data-tool export ~/electerm-backup-2025-09-03.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The exported JSON will contain:
|
|
82
|
+
- All bookmarks with decrypted passwords
|
|
83
|
+
- Bookmark groups and folder structure
|
|
84
|
+
- Terminal themes
|
|
85
|
+
- Quick commands
|
|
86
|
+
- Profiles
|
|
87
|
+
- Configuration settings
|
|
88
|
+
- And all other Electerm data
|
|
89
|
+
|
|
90
|
+
**Important**: The exported file contains plain-text passwords. Store it securely and delete when no longer needed.
|
|
91
|
+
|
|
92
|
+
### 3. Database Information
|
|
93
|
+
|
|
94
|
+
View information about your current Electerm database:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
electerm-data-tool info
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This will show:
|
|
101
|
+
- Database type (v1 NeDB or v2 SQLite)
|
|
102
|
+
- Number of records in each table
|
|
103
|
+
- Migration recommendations if applicable
|
|
104
|
+
|
|
105
|
+
## Database Detection
|
|
106
|
+
|
|
107
|
+
The tool automatically detects whether you're using:
|
|
108
|
+
|
|
109
|
+
- **v1 Database (NeDB)**: Original file-based database format
|
|
110
|
+
- **v2 Database (SQLite)**: New SQLite-based format (Node.js 22+ required)
|
|
111
|
+
|
|
112
|
+
When exporting data:
|
|
113
|
+
- If v1 database is detected, uses NeDB module for data access
|
|
114
|
+
- If v2 database is detected, uses SQLite module for data access
|
|
115
|
+
- Passwords are automatically decrypted in both cases
|
|
116
|
+
|
|
117
|
+
## Data Structure
|
|
118
|
+
|
|
119
|
+
### Export Format
|
|
120
|
+
|
|
121
|
+
The exported JSON follows this structure:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"bookmarks": [...],
|
|
126
|
+
"bookmarkGroups": [...],
|
|
127
|
+
"terminalThemes": [...],
|
|
128
|
+
"quickCommands": [...],
|
|
129
|
+
"profiles": [...],
|
|
130
|
+
"config": {...},
|
|
131
|
+
"addressBookmarks": [...],
|
|
132
|
+
"lastStates": [...],
|
|
133
|
+
"data": [...],
|
|
134
|
+
"log": [...],
|
|
135
|
+
"dbUpgradeLog": [...]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Password Handling
|
|
140
|
+
|
|
141
|
+
- Passwords stored in Electerm are encrypted using a simple character-based encryption
|
|
142
|
+
- During export, passwords are automatically decrypted to plain text
|
|
143
|
+
- The `passwordEncrypted` flag is removed from exported data
|
|
144
|
+
- Exported passwords are human-readable for backup purposes
|
|
145
|
+
|
|
146
|
+
## Requirements
|
|
147
|
+
|
|
148
|
+
- **Node.js**: 16.0.0 or higher
|
|
149
|
+
- **For SQLite (v2)**: Node.js 22.0.0 or higher
|
|
150
|
+
- **Dependencies**:
|
|
151
|
+
- `commander` - CLI framework
|
|
152
|
+
- `@yetzt/nedb` - NeDB database support
|
|
153
|
+
- `nanoid` - ID generation
|
|
154
|
+
|
|
155
|
+
## File Locations
|
|
156
|
+
|
|
157
|
+
The tool operates on Electerm data stored in the standard locations:
|
|
158
|
+
|
|
159
|
+
**Database Files:**
|
|
160
|
+
- NeDB (v1): `~/.electerm/users/{username}/electerm.{table}.nedb`
|
|
161
|
+
- SQLite (v2): `~/.electerm/users/{username}/electerm.db`
|
|
162
|
+
|
|
163
|
+
**Backup Files:**
|
|
164
|
+
During migration, original NeDB files are renamed with timestamp:
|
|
165
|
+
- `electerm.bookmarks.nedb-{timestamp}.bak`
|
|
166
|
+
|
|
167
|
+
## Examples
|
|
168
|
+
|
|
169
|
+
### Complete Migration Workflow
|
|
170
|
+
|
|
171
|
+
**Using npx (recommended):**
|
|
172
|
+
```bash
|
|
173
|
+
# 1. Check current database status
|
|
174
|
+
npx electerm-data-tool info
|
|
175
|
+
|
|
176
|
+
# 2. Export current data as backup
|
|
177
|
+
npx electerm-data-tool export ~/electerm-backup-before-migration.json
|
|
178
|
+
|
|
179
|
+
# 3. Perform migration
|
|
180
|
+
npx electerm-data-tool migrate
|
|
181
|
+
|
|
182
|
+
# 4. Verify migration succeeded
|
|
183
|
+
npx electerm-data-tool info
|
|
184
|
+
|
|
185
|
+
# 5. Export migrated data to verify
|
|
186
|
+
npx electerm-data-tool export ~/electerm-backup-after-migration.json
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Using globally installed version:**
|
|
190
|
+
```bash
|
|
191
|
+
# 1. Check current database status
|
|
192
|
+
electerm-data-tool info
|
|
193
|
+
|
|
194
|
+
# 2. Export current data as backup
|
|
195
|
+
electerm-data-tool export ~/electerm-backup-before-migration.json
|
|
196
|
+
|
|
197
|
+
# 3. Perform migration
|
|
198
|
+
electerm-data-tool migrate
|
|
199
|
+
|
|
200
|
+
# 4. Verify migration succeeded
|
|
201
|
+
electerm-data-tool info
|
|
202
|
+
|
|
203
|
+
# 5. Export migrated data to verify
|
|
204
|
+
electerm-data-tool export ~/electerm-backup-after-migration.json
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Using with npm scripts
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Quick migration
|
|
211
|
+
npm run migrate
|
|
212
|
+
|
|
213
|
+
# Quick export
|
|
214
|
+
npm run export ~/backup.json
|
|
215
|
+
|
|
216
|
+
# Quick info
|
|
217
|
+
npm run info
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Troubleshooting
|
|
221
|
+
|
|
222
|
+
### Migration Issues
|
|
223
|
+
|
|
224
|
+
**"Migration not needed"**: Your database is already v2 or no v1 files exist.
|
|
225
|
+
|
|
226
|
+
**SQLite errors**: Ensure you're using Node.js 22.0.0 or higher.
|
|
227
|
+
|
|
228
|
+
**Permission errors**: Ensure you have read/write access to Electerm data directory.
|
|
229
|
+
|
|
230
|
+
### Export Issues
|
|
231
|
+
|
|
232
|
+
**Empty export**: Check that Electerm has been run and contains data.
|
|
233
|
+
|
|
234
|
+
**Encrypted passwords in export**: The tool should automatically decrypt passwords. If you see encrypted text, there may be an issue with the decryption module.
|
|
235
|
+
|
|
236
|
+
### General Issues
|
|
237
|
+
|
|
238
|
+
**Command not found**: If installed globally, ensure npm global bin directory is in your PATH.
|
|
239
|
+
|
|
240
|
+
**Module errors**: Run `npm install` to ensure all dependencies are installed.
|
|
241
|
+
|
|
242
|
+
## Security Considerations
|
|
243
|
+
|
|
244
|
+
- **Exported files contain plain-text passwords** - store securely
|
|
245
|
+
- **Delete export files** after use if they're temporary backups
|
|
246
|
+
- **File permissions** - exported files inherit system default permissions
|
|
247
|
+
- **Local processing only** - no data is transmitted over network
|
|
248
|
+
|
|
249
|
+
## Contributing
|
|
250
|
+
|
|
251
|
+
1. Fork the repository
|
|
252
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
253
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
254
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
255
|
+
5. Open a Pull Request
|
|
256
|
+
|
|
257
|
+
## Related Projects
|
|
258
|
+
|
|
259
|
+
- [Electerm](https://github.com/electerm/electerm) - The main Electerm terminal application
|
|
260
|
+
- [Electerm Documentation](https://electerm.html5beta.com/) - Official documentation
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "electerm-data-tool",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "electerm data export/migrate tool",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"electerm-data-tool": "./src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"migrate": "node src/index.js migrate",
|
|
11
|
+
"export": "node src/index.js export",
|
|
12
|
+
"info": "node src/index.js info",
|
|
13
|
+
"update": "node -r dotenv/config bin/update-version.js",
|
|
14
|
+
"lint": "standard",
|
|
15
|
+
"fix": "standard --fix"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/electerm/electerm-data-tool.git"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"electerm",
|
|
23
|
+
"data",
|
|
24
|
+
"tool",
|
|
25
|
+
"migrate",
|
|
26
|
+
"export"
|
|
27
|
+
],
|
|
28
|
+
"author": "ZHAO Xudong <zxdong@gmail.com>",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/electerm/electerm-data-tool/issues"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"src",
|
|
35
|
+
"LICENSE",
|
|
36
|
+
"README.md"
|
|
37
|
+
],
|
|
38
|
+
"homepage": "https://github.com/electerm/electerm-data-tool#readme",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@yetzt/nedb": "^1.8.0",
|
|
41
|
+
"commander": "^14.0.0",
|
|
42
|
+
"lodash": "^4.17.21",
|
|
43
|
+
"nanoid": "^3.3.8"
|
|
44
|
+
},
|
|
45
|
+
"standard": {
|
|
46
|
+
"ignore": [
|
|
47
|
+
"*.html",
|
|
48
|
+
"/res/",
|
|
49
|
+
"/temp",
|
|
50
|
+
"/data",
|
|
51
|
+
"/public"
|
|
52
|
+
],
|
|
53
|
+
"parserOptions": {
|
|
54
|
+
"requireConfigFile": false,
|
|
55
|
+
"sourceType": "module"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"axios": "^1.11.0",
|
|
60
|
+
"dotenv": "^17.2.2",
|
|
61
|
+
"standard": "^17.1.2"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const os = require('os')
|
|
3
|
+
const version = '1.101.16'
|
|
4
|
+
|
|
5
|
+
function getAppPath () {
|
|
6
|
+
const home = os.homedir()
|
|
7
|
+
const platform = process.platform
|
|
8
|
+
if (platform === 'darwin') {
|
|
9
|
+
// macOS
|
|
10
|
+
return path.join(home, 'Library', 'Application Support')
|
|
11
|
+
} else if (platform === 'win32') {
|
|
12
|
+
// Windows
|
|
13
|
+
return process.env.APPDATA || path.join(home, 'AppData', 'Roaming')
|
|
14
|
+
} else {
|
|
15
|
+
// Linux and others
|
|
16
|
+
return path.join(home, '.config')
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.appPath = process.env.APP_PATH || getAppPath()
|
|
21
|
+
exports.defaultUserName = 'default_user'
|
|
22
|
+
exports.packInfo = {
|
|
23
|
+
version
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = console
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Password encryption/decryption utilities
|
|
3
|
+
* Based on electerm's pass-enc.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const enc = (str) => {
|
|
7
|
+
if (typeof str !== 'string') {
|
|
8
|
+
return str
|
|
9
|
+
}
|
|
10
|
+
return str.split('').map((s, i) => {
|
|
11
|
+
return String.fromCharCode((s.charCodeAt(0) + i + 1) % 65536)
|
|
12
|
+
}).join('')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const dec = (str) => {
|
|
16
|
+
if (typeof str !== 'string') {
|
|
17
|
+
return str
|
|
18
|
+
}
|
|
19
|
+
return str.split('').map((s, i) => {
|
|
20
|
+
return String.fromCharCode((s.charCodeAt(0) - i - 1 + 65536) % 65536)
|
|
21
|
+
}).join('')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Decrypt password in an object
|
|
26
|
+
* @param {object} obj
|
|
27
|
+
*/
|
|
28
|
+
function decObj (obj) {
|
|
29
|
+
if (obj.passwordEncrypted && obj.password) {
|
|
30
|
+
obj.password = dec(obj.password)
|
|
31
|
+
delete obj.passwordEncrypted
|
|
32
|
+
}
|
|
33
|
+
return obj
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Encrypt password in an object
|
|
38
|
+
* @param {object} obj
|
|
39
|
+
*/
|
|
40
|
+
function encObj (obj) {
|
|
41
|
+
if (!obj.passwordEncrypted && obj.password) {
|
|
42
|
+
obj.password = enc(obj.password)
|
|
43
|
+
obj.passwordEncrypted = true
|
|
44
|
+
}
|
|
45
|
+
return obj
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
enc,
|
|
50
|
+
dec,
|
|
51
|
+
encObj,
|
|
52
|
+
decObj
|
|
53
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* version compare
|
|
3
|
+
* @param {string} a
|
|
4
|
+
* @param {string} b
|
|
5
|
+
* @return {number}
|
|
6
|
+
*/
|
|
7
|
+
// compare version '1.0.0' '12.0.3'
|
|
8
|
+
// return 1 when a > b
|
|
9
|
+
// return -1 when a < b
|
|
10
|
+
// return 0 when a === b
|
|
11
|
+
module.exports = exports.default = function (a, b) {
|
|
12
|
+
const ar = a.split('.').map(n => Number(n.replace('v', '')))
|
|
13
|
+
const br = b.split('.').map(n => Number(n.replace('v', '')))
|
|
14
|
+
let res = 0
|
|
15
|
+
for (let i = 0, len = br.length; i < len; i++) {
|
|
16
|
+
if (br[i] < ar[i]) {
|
|
17
|
+
res = 1
|
|
18
|
+
break
|
|
19
|
+
} else if (br[i] > ar[i]) {
|
|
20
|
+
res = -1
|
|
21
|
+
break
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return res
|
|
25
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Electerm Data Tool - Command Line Interface
|
|
5
|
+
* Provides tools to migrate and export electerm data
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { Command } = require('commander')
|
|
9
|
+
const { writeFileSync } = require('fs')
|
|
10
|
+
const { resolve } = require('path')
|
|
11
|
+
const { migrate } = require('./migrate/migrate-1-to-2')
|
|
12
|
+
const log = require('./common/log')
|
|
13
|
+
const pkg = require('../package.json')
|
|
14
|
+
|
|
15
|
+
const program = new Command()
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the major version number from Node.js version string
|
|
19
|
+
* @returns {number} Major version number
|
|
20
|
+
*/
|
|
21
|
+
function getNodeMajorVersion () {
|
|
22
|
+
const nodeVersion = process.version
|
|
23
|
+
return parseInt(nodeVersion.slice(1).split('.')[0])
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
program
|
|
27
|
+
.name('electerm-data-tool')
|
|
28
|
+
.description('CLI tool for electerm data migration and export')
|
|
29
|
+
.version(pkg.version)
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Migration command - migrates from NeDB (v1) to SQLite (v2)
|
|
33
|
+
*/
|
|
34
|
+
program
|
|
35
|
+
.command('migrate')
|
|
36
|
+
.description('Migrate electerm database from v1 (NeDB) to v2 (SQLite)')
|
|
37
|
+
.action(async () => {
|
|
38
|
+
try {
|
|
39
|
+
// Check Node.js version requirement for SQLite
|
|
40
|
+
const majorVersion = getNodeMajorVersion()
|
|
41
|
+
|
|
42
|
+
if (majorVersion < 22) {
|
|
43
|
+
console.error('❌ Migration requires Node.js v22.0.0 or higher for SQLite support')
|
|
44
|
+
console.error(` Current version: ${process.version}`)
|
|
45
|
+
console.error(' Please upgrade Node.js and try again.')
|
|
46
|
+
console.error(' You can still use the export function with your current Node.js version.')
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
log.info('Starting migration process...')
|
|
51
|
+
await migrate()
|
|
52
|
+
log.info('Migration completed successfully!')
|
|
53
|
+
console.log('✅ Migration from NeDB to SQLite completed successfully!')
|
|
54
|
+
} catch (error) {
|
|
55
|
+
log.error('Migration failed:', error)
|
|
56
|
+
console.error('❌ Migration failed:', error.message)
|
|
57
|
+
process.exit(1)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Export command - exports all electerm data to a JSON file
|
|
63
|
+
*/
|
|
64
|
+
program
|
|
65
|
+
.command('export')
|
|
66
|
+
.description('Export all electerm data to a JSON file')
|
|
67
|
+
.argument('<output-path>', 'Path to the output JSON file')
|
|
68
|
+
.action(async (outputPath) => {
|
|
69
|
+
try {
|
|
70
|
+
log.info('Starting data export...')
|
|
71
|
+
|
|
72
|
+
// Check if migration is needed to determine which database to use
|
|
73
|
+
const { checkMigrate } = require('./migrate/migrate-1-to-2')
|
|
74
|
+
const shouldMigrate = checkMigrate()
|
|
75
|
+
|
|
76
|
+
let dbModule
|
|
77
|
+
let dbType
|
|
78
|
+
|
|
79
|
+
if (shouldMigrate) {
|
|
80
|
+
// v1 database (NeDB) detected
|
|
81
|
+
dbModule = require('./nedb')
|
|
82
|
+
dbType = 'NeDB (v1)'
|
|
83
|
+
log.info('Detected v1 database, using NeDB for export')
|
|
84
|
+
} else {
|
|
85
|
+
// v2 database (SQLite) or no data
|
|
86
|
+
try {
|
|
87
|
+
dbModule = require('./sqlite')
|
|
88
|
+
dbType = 'SQLite (v2)'
|
|
89
|
+
log.info('Using SQLite database for export')
|
|
90
|
+
} catch (error) {
|
|
91
|
+
log.error('Failed to load SQLite module:', error.message)
|
|
92
|
+
console.error('❌ Failed to load database module')
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { dbAction, tables } = dbModule
|
|
98
|
+
const exportData = {}
|
|
99
|
+
|
|
100
|
+
// Import password decryption utilities
|
|
101
|
+
const { decObj } = require('./common/pass-enc')
|
|
102
|
+
|
|
103
|
+
// Helper function to decrypt passwords in data objects
|
|
104
|
+
const decryptPasswords = (data) => {
|
|
105
|
+
if (Array.isArray(data)) {
|
|
106
|
+
return data.map(item => {
|
|
107
|
+
if (item && typeof item === 'object') {
|
|
108
|
+
return decObj({ ...item })
|
|
109
|
+
}
|
|
110
|
+
return item
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
return data
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Export all tables
|
|
117
|
+
for (const table of tables) {
|
|
118
|
+
try {
|
|
119
|
+
log.info(`Exporting table: ${table}`)
|
|
120
|
+
const data = await dbAction(table, 'find', {})
|
|
121
|
+
|
|
122
|
+
// Decrypt passwords in the data
|
|
123
|
+
const decryptedData = decryptPasswords(data)
|
|
124
|
+
|
|
125
|
+
exportData[table] = decryptedData || []
|
|
126
|
+
log.info(`Exported ${decryptedData?.length || 0} records from ${table}`)
|
|
127
|
+
} catch (error) {
|
|
128
|
+
log.warn(`Failed to export table ${table}:`, error.message)
|
|
129
|
+
exportData[table] = []
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Also try to export config if it exists in the data table
|
|
134
|
+
try {
|
|
135
|
+
const configData = await dbAction('data', 'findOne', { _id: 'config' })
|
|
136
|
+
if (configData && configData.value) {
|
|
137
|
+
exportData.config = configData.value
|
|
138
|
+
log.info('Exported config data')
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
log.warn('Failed to export config data:', error.message)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log(`📊 Database Type: ${dbType}`)
|
|
145
|
+
|
|
146
|
+
// Resolve the output path
|
|
147
|
+
const resolvedPath = resolve(process.cwd(), outputPath)
|
|
148
|
+
|
|
149
|
+
// Write the JSON file
|
|
150
|
+
const jsonString = JSON.stringify(exportData, null, 2)
|
|
151
|
+
writeFileSync(resolvedPath, jsonString, 'utf8')
|
|
152
|
+
|
|
153
|
+
const totalRecords = Object.values(exportData).reduce((sum, table) => {
|
|
154
|
+
return sum + (Array.isArray(table) ? table.length : 0)
|
|
155
|
+
}, 0)
|
|
156
|
+
|
|
157
|
+
log.info(`Export completed. ${totalRecords} total records exported to ${resolvedPath}`)
|
|
158
|
+
console.log('✅ Export completed successfully!')
|
|
159
|
+
console.log(`📄 ${totalRecords} total records exported to: ${resolvedPath}`)
|
|
160
|
+
} catch (error) {
|
|
161
|
+
log.error('Export failed:', error)
|
|
162
|
+
console.error('❌ Export failed:', error.message)
|
|
163
|
+
process.exit(1)
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Info command - displays information about the current electerm data
|
|
169
|
+
*/
|
|
170
|
+
program
|
|
171
|
+
.command('info')
|
|
172
|
+
.description('Display information about the current electerm data')
|
|
173
|
+
.action(async () => {
|
|
174
|
+
try {
|
|
175
|
+
// Check if migration is needed to determine which database to use
|
|
176
|
+
const { checkMigrate } = require('./migrate/migrate-1-to-2')
|
|
177
|
+
const shouldMigrate = checkMigrate()
|
|
178
|
+
|
|
179
|
+
let dbModule
|
|
180
|
+
let dbType
|
|
181
|
+
|
|
182
|
+
if (shouldMigrate) {
|
|
183
|
+
// v1 database (NeDB) detected
|
|
184
|
+
dbModule = require('./nedb')
|
|
185
|
+
dbType = 'NeDB (v1) - Migration recommended'
|
|
186
|
+
|
|
187
|
+
// Check Node.js version for migration capability
|
|
188
|
+
const majorVersion = getNodeMajorVersion()
|
|
189
|
+
|
|
190
|
+
console.log('⚠️ v1 database detected.')
|
|
191
|
+
if (majorVersion >= 22) {
|
|
192
|
+
console.log(' Run \'electerm-data-tool migrate\' to upgrade to v2')
|
|
193
|
+
} else {
|
|
194
|
+
console.log(` Migration requires Node.js v22.0.0+ (current: ${process.version})`)
|
|
195
|
+
console.log(' Please upgrade Node.js to enable migration to v2')
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
// v2 database (SQLite) or no data
|
|
199
|
+
try {
|
|
200
|
+
dbModule = require('./sqlite')
|
|
201
|
+
dbType = 'SQLite (v2)'
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error('❌ Failed to read database:', error.message)
|
|
204
|
+
process.exit(1)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const { dbAction, tables } = dbModule
|
|
209
|
+
console.log('📊 Electerm Data Information')
|
|
210
|
+
console.log(`Database Type: ${dbType}`)
|
|
211
|
+
console.log('='.repeat(40))
|
|
212
|
+
|
|
213
|
+
let totalRecords = 0
|
|
214
|
+
for (const table of tables) {
|
|
215
|
+
try {
|
|
216
|
+
const data = await dbAction(table, 'find', {})
|
|
217
|
+
const count = data?.length || 0
|
|
218
|
+
totalRecords += count
|
|
219
|
+
console.log(`${table.padEnd(20)}: ${count} records`)
|
|
220
|
+
} catch (error) {
|
|
221
|
+
console.log(`${table.padEnd(20)}: Error reading table`)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log('='.repeat(40))
|
|
226
|
+
console.log(`Total Records: ${totalRecords}`)
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('❌ Failed to read data:', error.message)
|
|
229
|
+
process.exit(1)
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// Parse command line arguments
|
|
234
|
+
program.parse()
|