error-ux-cli 1.0.0 → 1.1.1

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/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 || 'Aniruth').trim() || 'Aniruth';
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 openBrowser(url) {
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 "" "${url}"`;
155
+ command = `start "" "${target}"`;
150
156
  break;
151
157
  case 'darwin':
152
- command = `open "${url}"`;
158
+ command = `open "${target}"`;
153
159
  break;
154
160
  case 'linux':
155
- command = `xdg-open "${url}"`;
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 URL: ${error.message}`);
170
+ console.error(`Failed to open: ${error.message}`);
165
171
  }
166
172
  });
167
173
  }
168
174
 
169
- function isValidUrl(urlString) {
175
+ function isValidResource(target) {
176
+ // 1. Check if it's a valid URL
170
177
  try {
171
- new URL(urlString);
178
+ new URL(target);
172
179
  return true;
173
180
  } catch (e) {
174
- return false;
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
- openBrowser,
377
- isValidUrl,
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.0.0",
4
- "description": "All-in-one developer productivity CLI",
3
+ "version": "1.1.1",
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
- "developer",
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
  }