error-ux-cli 1.0.0 → 1.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/index.js +48 -8
- package/lib/commands.js +1247 -730
- package/lib/dashboard.mjs +4 -4
- package/lib/dbExplorer.mjs +284 -0
- package/lib/git.js +91 -4
- package/lib/pgClient.js +102 -0
- package/lib/plugins.js +94 -0
- package/lib/storage.js +71 -3
- package/lib/utils.js +22 -10
- package/package.json +13 -6
package/lib/storage.js
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
const fs = require('fs/promises');
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Derives a consistent 32-byte key from a 128-char master key.
|
|
8
|
+
* @param {string} masterKey
|
|
9
|
+
* @returns {Buffer}
|
|
10
|
+
*/
|
|
11
|
+
function deriveKey(masterKey) {
|
|
12
|
+
// We use a constant salt because the masterKey itself is 128 chars
|
|
13
|
+
// and this needs to be deterministic for decryption.
|
|
14
|
+
return crypto.scryptSync(masterKey, 'error-ux-salt', 32);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function encrypt(text, masterKey) {
|
|
18
|
+
try {
|
|
19
|
+
const key = deriveKey(masterKey);
|
|
20
|
+
const iv = crypto.randomBytes(16);
|
|
21
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
22
|
+
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
23
|
+
encrypted += cipher.final('hex');
|
|
24
|
+
return iv.toString('hex') + ':' + encrypted;
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function decrypt(text, masterKey) {
|
|
31
|
+
try {
|
|
32
|
+
const textParts = text.split(':');
|
|
33
|
+
const iv = Buffer.from(textParts.shift(), 'hex');
|
|
34
|
+
const encryptedText = Buffer.from(textParts.join(':'), 'hex');
|
|
35
|
+
const key = deriveKey(masterKey);
|
|
36
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
|
37
|
+
let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
|
|
38
|
+
decrypted += decipher.final('utf8');
|
|
39
|
+
return decrypted;
|
|
40
|
+
} catch (e) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
4
44
|
|
|
5
45
|
const CONFIG_ENV_VAR = 'ERROR_UX_CONFIG_FILE';
|
|
6
46
|
const DEFAULT_CONFIG_FILE = path.join(os.homedir(), '.error-ux', 'config.json');
|
|
@@ -21,7 +61,7 @@ function normalizeConfig(config) {
|
|
|
21
61
|
}
|
|
22
62
|
|
|
23
63
|
if (!config.users || typeof config.users !== 'object') {
|
|
24
|
-
const oldName = String(config.name || '
|
|
64
|
+
const oldName = String(config.name || 'User').trim() || 'User';
|
|
25
65
|
config = {
|
|
26
66
|
activeUser: oldName,
|
|
27
67
|
users: {
|
|
@@ -31,7 +71,10 @@ function normalizeConfig(config) {
|
|
|
31
71
|
shortcuts: config.shortcuts || {},
|
|
32
72
|
activeRepo: config.activeRepo || null,
|
|
33
73
|
savedRepos: Array.isArray(config.savedRepos) ? config.savedRepos : [],
|
|
34
|
-
todo: Array.isArray(config.todo) ? config.todo : []
|
|
74
|
+
todo: Array.isArray(config.todo) ? config.todo : [],
|
|
75
|
+
projectLinks: config.projectLinks || {},
|
|
76
|
+
vault: config.vault || null,
|
|
77
|
+
localVault: config.localVault || null
|
|
35
78
|
}
|
|
36
79
|
}
|
|
37
80
|
};
|
|
@@ -50,6 +93,11 @@ function normalizeConfig(config) {
|
|
|
50
93
|
user.activeRepo = user.activeRepo || null;
|
|
51
94
|
user.news_api_key = user.news_api_key || null;
|
|
52
95
|
user.password_hash = user.password_hash || '';
|
|
96
|
+
user.projectLinks = user.projectLinks && typeof user.projectLinks === 'object' ? user.projectLinks : {};
|
|
97
|
+
user.vault = user.vault || null;
|
|
98
|
+
user.localVault = user.localVault || null;
|
|
99
|
+
user.settings = user.settings && typeof user.settings === 'object' ? user.settings : { dashboardVisible: true };
|
|
100
|
+
user.missions = user.missions && typeof user.missions === 'object' ? user.missions : {};
|
|
53
101
|
config.users[username] = user;
|
|
54
102
|
});
|
|
55
103
|
|
|
@@ -107,13 +155,33 @@ async function wipeAllData() {
|
|
|
107
155
|
return removed;
|
|
108
156
|
}
|
|
109
157
|
|
|
158
|
+
function getProjectLink(user, dirPath) {
|
|
159
|
+
if (!user || !user.projectLinks) return null;
|
|
160
|
+
const normalizedPath = path.resolve(dirPath);
|
|
161
|
+
return user.projectLinks[normalizedPath] || null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function saveProjectLink(user, dirPath, repo) {
|
|
165
|
+
if (!user) return;
|
|
166
|
+
if (!user.projectLinks) user.projectLinks = {};
|
|
167
|
+
const normalizedPath = path.resolve(dirPath);
|
|
168
|
+
user.projectLinks[normalizedPath] = {
|
|
169
|
+
name: repo.name,
|
|
170
|
+
url: repo.url
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
110
174
|
module.exports = {
|
|
111
175
|
CONFIG_ENV_VAR,
|
|
112
176
|
DEFAULT_CONFIG_FILE,
|
|
113
177
|
LEGACY_CONFIG_FILE,
|
|
114
178
|
getActiveUser,
|
|
115
179
|
getConfigFile,
|
|
180
|
+
getProjectLink,
|
|
181
|
+
saveProjectLink,
|
|
116
182
|
loadConfig,
|
|
117
183
|
saveConfig,
|
|
118
|
-
wipeAllData
|
|
184
|
+
wipeAllData,
|
|
185
|
+
encrypt,
|
|
186
|
+
decrypt
|
|
119
187
|
};
|
package/lib/utils.js
CHANGED
|
@@ -140,19 +140,25 @@ async function animateIntroName(name, width) {
|
|
|
140
140
|
console.log('');
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
function
|
|
143
|
+
function openResource(target) {
|
|
144
144
|
const platform = os.platform();
|
|
145
145
|
let command;
|
|
146
146
|
|
|
147
|
+
// Expand environment variables (e.g., %USERPROFILE% on Windows)
|
|
148
|
+
if (platform === 'win32') {
|
|
149
|
+
target = target.replace(/%([^%]+)%/g, (_, name) => process.env[name] || `%${name}%`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Use double quotes around the target to handle spaces in paths
|
|
147
153
|
switch (platform) {
|
|
148
154
|
case 'win32':
|
|
149
|
-
command = `start "" "${
|
|
155
|
+
command = `start "" "${target}"`;
|
|
150
156
|
break;
|
|
151
157
|
case 'darwin':
|
|
152
|
-
command = `open "${
|
|
158
|
+
command = `open "${target}"`;
|
|
153
159
|
break;
|
|
154
160
|
case 'linux':
|
|
155
|
-
command = `xdg-open "${
|
|
161
|
+
command = `xdg-open "${target}"`;
|
|
156
162
|
break;
|
|
157
163
|
default:
|
|
158
164
|
console.error(`Unsupported platform: ${platform}`);
|
|
@@ -161,17 +167,23 @@ function openBrowser(url) {
|
|
|
161
167
|
|
|
162
168
|
exec(command, (error) => {
|
|
163
169
|
if (error) {
|
|
164
|
-
console.error(`Failed to open
|
|
170
|
+
console.error(`Failed to open: ${error.message}`);
|
|
165
171
|
}
|
|
166
172
|
});
|
|
167
173
|
}
|
|
168
174
|
|
|
169
|
-
function
|
|
175
|
+
function isValidResource(target) {
|
|
176
|
+
// 1. Check if it's a valid URL
|
|
170
177
|
try {
|
|
171
|
-
new URL(
|
|
178
|
+
new URL(target);
|
|
172
179
|
return true;
|
|
173
180
|
} catch (e) {
|
|
174
|
-
|
|
181
|
+
// 2. Not a URL, check if it's a valid local path
|
|
182
|
+
try {
|
|
183
|
+
return fs.existsSync(target);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
175
187
|
}
|
|
176
188
|
}
|
|
177
189
|
|
|
@@ -373,8 +385,8 @@ module.exports = {
|
|
|
373
385
|
printAnimatedLines,
|
|
374
386
|
typeAnimatedLines,
|
|
375
387
|
animateIntroName,
|
|
376
|
-
|
|
377
|
-
|
|
388
|
+
openResource,
|
|
389
|
+
isValidResource,
|
|
378
390
|
isSystemFolder,
|
|
379
391
|
loadEnv,
|
|
380
392
|
saveEnvValue,
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "error-ux-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Premium Cyberpunk Administrative Cockpit & Developer Productivity CLI",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"error-ux-cli": "index.js"
|
|
7
|
+
"error-ux-cli": "index.js",
|
|
8
|
+
"error-ux": "index.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
11
|
"start": "node index.js",
|
|
@@ -13,12 +14,17 @@
|
|
|
13
14
|
"files": [
|
|
14
15
|
"index.js",
|
|
15
16
|
"lib",
|
|
16
|
-
"README.md"
|
|
17
|
+
"README.md",
|
|
18
|
+
"package.json"
|
|
17
19
|
],
|
|
18
20
|
"keywords": [
|
|
19
21
|
"cli",
|
|
20
|
-
"
|
|
21
|
-
"productivity"
|
|
22
|
+
"cyberpunk",
|
|
23
|
+
"productivity",
|
|
24
|
+
"workflow",
|
|
25
|
+
"admin",
|
|
26
|
+
"automation",
|
|
27
|
+
"mission"
|
|
22
28
|
],
|
|
23
29
|
"author": "Aniruth",
|
|
24
30
|
"license": "MIT",
|
|
@@ -27,6 +33,7 @@
|
|
|
27
33
|
},
|
|
28
34
|
"dependencies": {
|
|
29
35
|
"ink": "^7.0.0",
|
|
36
|
+
"pg": "^8.20.0",
|
|
30
37
|
"react": "^19.2.5"
|
|
31
38
|
}
|
|
32
39
|
}
|