@crystalplatforms/adm 0.2.3 → 0.3.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 -21
- package/README.md +154 -161
- package/bin/adm +18 -21
- package/package.json +9 -22
- package/scripts/completion/adm.bash +12 -55
- package/scripts/completion/adm.zsh +21 -58
- package/scripts/install.js +8 -8
- package/src/commands/config.js +66 -0
- package/src/commands/dotfiles.js +49 -32
- package/src/commands/feedback.js +12 -0
- package/src/commands/help.js +33 -0
- package/src/commands/uninstall.js +73 -54
- package/src/commands/version.js +7 -0
- package/src/commands.js +26 -0
- package/src/config/index.js +32 -32
- package/src/data/extensions.json +358 -358
- package/src/engines.js +38 -0
- package/src/install/executor.js +263 -0
- package/src/install/hints.js +94 -0
- package/src/install/npm-prefix.js +110 -0
- package/src/install/plan.js +75 -0
- package/src/install/report.js +46 -0
- package/src/install/run.js +88 -0
- package/src/install/shell-paths.js +129 -0
- package/src/legacy-cleanup.js +96 -0
- package/src/pkg/builders.js +220 -0
- package/src/pkg/managers.js +59 -0
- package/src/pkg/package-names.js +229 -0
- package/src/pkg/script-urls.js +100 -0
- package/src/platform/index.js +129 -0
- package/src/platform/os-release.js +27 -0
- package/src/platform/shell.js +111 -0
- package/src/reports.js +37 -0
- package/src/router.js +157 -0
- package/src/setup/catalog.js +13 -13
- package/src/setup/git-step.js +128 -0
- package/src/setup/loader.js +108 -0
- package/src/setup/prompts.js +259 -0
- package/src/setup/registry.js +48 -0
- package/src/setup/spinner.js +67 -0
- package/src/setup/wizard.js +319 -195
- package/src/upgrade/index.js +499 -0
- package/src/utils/closest-match.js +36 -0
- package/src/utils/dotfiles-sync.js +89 -89
- package/src/utils/file-conflict-handler.js +30 -30
- package/bin/adm-tui +0 -13
- package/src/ai/knowledge.js +0 -61
- package/src/commands/connect.js +0 -76
- package/src/commands/issue.js +0 -80
- package/src/commands/pr.js +0 -55
- package/src/commands/theme.js +0 -103
- package/src/commands/upgrade.js +0 -114
- package/src/installer/git-config.js +0 -34
- package/src/installer/node-installer.js +0 -50
- package/src/installer/package-manager-installer.js +0 -31
- package/src/installer/ssh-setup.js +0 -31
- package/src/installer/system-packages.js +0 -49
- package/src/installers/index.js +0 -66
- package/src/integrations/ai-backend.js +0 -60
- package/src/integrations/ai-providers/registry.js +0 -261
- package/src/integrations/github.js +0 -107
- package/src/integrations/gitlab.js +0 -121
- package/src/plugins/context.js +0 -64
- package/src/plugins/loader.js +0 -50
- package/src/plugins/runner.js +0 -25
- package/src/setup/installer.js +0 -192
- package/src/shell/detector.js +0 -10
- package/src/tui/app-state.js +0 -374
- package/src/tui/app.js +0 -442
- package/src/tui/autocomplete.js +0 -57
- package/src/tui/commands/registry.js +0 -823
- package/src/tui/components/SetupScreen.js +0 -292
- package/src/ui/animations.js +0 -24
- package/src/ui/spinner.js +0 -34
- package/src/ui/theme/cyberpunk.js +0 -14
- package/src/ui/theme/dark.js +0 -14
- package/src/ui/theme/forest.js +0 -14
- package/src/ui/theme/light.js +0 -14
- package/src/ui/theme/monokai.js +0 -14
- package/src/ui/theme/nord.js +0 -14
- package/src/ui/theme.js +0 -49
- package/src/utils/command-history.js +0 -43
- package/src/utils/error-handler.js +0 -69
- package/src/utils/fuzzy-search.js +0 -20
- package/src/utils/github-error-handler.js +0 -26
- package/src/utils/keychain.js +0 -97
- package/src/utils/open-url.js +0 -15
- package/src/utils/terminal-detection.js +0 -26
- package/src/utils/token-encryption.js +0 -96
package/src/utils/keychain.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
const child_process = require('child_process');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const tokenEncryption = require('./token-encryption');
|
|
4
|
-
|
|
5
|
-
const SERVICE = 'adm-cli';
|
|
6
|
-
|
|
7
|
-
function isKeychainAvailable() {
|
|
8
|
-
if (os.platform() !== 'darwin') return false;
|
|
9
|
-
try {
|
|
10
|
-
child_process.execSync('security find-generic-password -s adm-cli 2>/dev/null', { stdio: 'pipe' });
|
|
11
|
-
return true;
|
|
12
|
-
} catch {
|
|
13
|
-
// Keychain exists but no entry yet — still usable
|
|
14
|
-
try {
|
|
15
|
-
child_process.execSync('security list-keychains >/dev/null 2>&1', { stdio: 'pipe' });
|
|
16
|
-
return true;
|
|
17
|
-
} catch {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function keychainSet(name, value) {
|
|
24
|
-
child_process.execSync(
|
|
25
|
-
`security add-generic-password -U -s "${SERVICE}" -a "${name}" -w "${value}"`,
|
|
26
|
-
{ stdio: 'pipe' },
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function keychainGet(name) {
|
|
31
|
-
try {
|
|
32
|
-
return child_process.execSync(
|
|
33
|
-
`security find-generic-password -s "${SERVICE}" -a "${name}" -w`,
|
|
34
|
-
{ encoding: 'utf8', stdio: 'pipe' },
|
|
35
|
-
).trim();
|
|
36
|
-
} catch {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function keychainDelete(name) {
|
|
42
|
-
try {
|
|
43
|
-
child_process.execSync(
|
|
44
|
-
`security delete-generic-password -s "${SERVICE}" -a "${name}"`,
|
|
45
|
-
{ stdio: 'pipe' },
|
|
46
|
-
);
|
|
47
|
-
return true;
|
|
48
|
-
} catch {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function storeToken(name, token) {
|
|
54
|
-
if (isKeychainAvailable()) {
|
|
55
|
-
keychainSet(name, token);
|
|
56
|
-
return 'keychain';
|
|
57
|
-
}
|
|
58
|
-
await tokenEncryption.writeEncryptedToken(name, token);
|
|
59
|
-
return 'encrypted-file';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function retrieveToken(name) {
|
|
63
|
-
if (isKeychainAvailable()) {
|
|
64
|
-
const val = keychainGet(name);
|
|
65
|
-
if (val) return val;
|
|
66
|
-
}
|
|
67
|
-
return tokenEncryption.readEncryptedToken(name);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function removeToken(name) {
|
|
71
|
-
if (isKeychainAvailable()) {
|
|
72
|
-
return keychainDelete(name);
|
|
73
|
-
}
|
|
74
|
-
return tokenEncryption.deleteEncryptedToken(name);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function listStoredServices() {
|
|
78
|
-
// Always check both keychain and encrypted file
|
|
79
|
-
const names = new Set();
|
|
80
|
-
if (isKeychainAvailable()) {
|
|
81
|
-
try {
|
|
82
|
-
const out = child_process.execSync(
|
|
83
|
-
`security dump-keychain 2>/dev/null | grep -A1 "svce.*${SERVICE}" | grep acct`,
|
|
84
|
-
{ encoding: 'utf8', stdio: 'pipe' },
|
|
85
|
-
);
|
|
86
|
-
const matches = out.matchAll(/"acct"<blob>="([^"]+)"/g);
|
|
87
|
-
for (const m of matches) names.add(m[1]);
|
|
88
|
-
} catch { /* empty */ }
|
|
89
|
-
}
|
|
90
|
-
const fileNames = await tokenEncryption.listTokenNames();
|
|
91
|
-
fileNames.forEach(n => names.add(n));
|
|
92
|
-
return [...names];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
module.exports = {
|
|
96
|
-
isKeychainAvailable, storeToken, retrieveToken, removeToken, listStoredServices,
|
|
97
|
-
};
|
package/src/utils/open-url.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const { exec } = require('child_process');
|
|
2
|
-
|
|
3
|
-
function openUrl(url, deps = {}) {
|
|
4
|
-
const execFn = deps.exec || ((cmd) => {
|
|
5
|
-
return new Promise((resolve, reject) => {
|
|
6
|
-
exec(cmd, (err) => err ? reject(err) : resolve());
|
|
7
|
-
});
|
|
8
|
-
});
|
|
9
|
-
const cmd = process.platform === 'darwin'
|
|
10
|
-
? `open "${url}"`
|
|
11
|
-
: `xdg-open "${url}"`;
|
|
12
|
-
return execFn(cmd);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = { openUrl };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const CI_ENV_VARS = ['CI', 'TF_BUILD', 'GITHUB_ACTIONS', 'JENKINS_URL', 'BUILDKITE', 'TRAVIS', 'CIRCLECI', 'GITLAB_CI'];
|
|
2
|
-
|
|
3
|
-
function isCI() {
|
|
4
|
-
return CI_ENV_VARS.some(key => process.env[key]);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function isTTY() {
|
|
8
|
-
return Boolean(process.stdout.isTTY);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function detectColorSupport() {
|
|
12
|
-
if (process.env.NO_COLOR) return false;
|
|
13
|
-
if (process.env.TERM === 'dumb') return false;
|
|
14
|
-
return Boolean(process.env.COLORTERM || process.env.TERM?.includes('color') || process.env.TERM?.includes('xterm'));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function isDarkMode() {
|
|
18
|
-
const colorfgbg = process.env.COLORFGBG;
|
|
19
|
-
if (!colorfgbg) return true;
|
|
20
|
-
const parts = colorfgbg.split(';');
|
|
21
|
-
if (parts.length < 2) return true;
|
|
22
|
-
const bg = parseInt(parts[1], 10);
|
|
23
|
-
return bg < 8;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = { detectColorSupport, isDarkMode, isCI, isTTY };
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
const crypto = require('crypto');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const os = require('os');
|
|
5
|
-
|
|
6
|
-
const ALGO = 'aes-256-gcm';
|
|
7
|
-
const KEY_LEN = 32;
|
|
8
|
-
const IV_LEN = 16;
|
|
9
|
-
const TAG_LEN = 16;
|
|
10
|
-
|
|
11
|
-
function configDir() {
|
|
12
|
-
return process.env.ADM_CONFIG_DIR || path.join(os.homedir(), '.adm');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function tokensFile() {
|
|
16
|
-
return path.join(configDir(), 'tokens.enc');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function getMachineKey() {
|
|
20
|
-
// Derive a stable key from machine-specific data
|
|
21
|
-
const homedir = os.homedir();
|
|
22
|
-
const hostname = os.hostname();
|
|
23
|
-
const username = os.userInfo().username;
|
|
24
|
-
const secret = `adm-cli-${username}@${hostname}:${homedir}`;
|
|
25
|
-
return crypto.scryptSync(secret, 'adm-cli-salt-v1', KEY_LEN);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function encrypt(text, key) {
|
|
29
|
-
const iv = crypto.randomBytes(IV_LEN);
|
|
30
|
-
const cipher = crypto.createCipheriv(ALGO, key, iv);
|
|
31
|
-
const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
|
|
32
|
-
const tag = cipher.getAuthTag();
|
|
33
|
-
return Buffer.concat([iv, tag, encrypted]).toString('base64');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function decrypt(data, key) {
|
|
37
|
-
const buf = Buffer.from(data, 'base64');
|
|
38
|
-
const iv = buf.subarray(0, IV_LEN);
|
|
39
|
-
const tag = buf.subarray(IV_LEN, IV_LEN + TAG_LEN);
|
|
40
|
-
const encrypted = buf.subarray(IV_LEN + TAG_LEN);
|
|
41
|
-
const decipher = crypto.createDecipheriv(ALGO, key, iv);
|
|
42
|
-
decipher.setAuthTag(tag);
|
|
43
|
-
return decipher.update(encrypted) + decipher.final('utf8');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function writeEncryptedToken(name, token) {
|
|
47
|
-
const dir = configDir();
|
|
48
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
49
|
-
|
|
50
|
-
const key = getMachineKey();
|
|
51
|
-
const store = readAllTokens(key);
|
|
52
|
-
store[name] = token;
|
|
53
|
-
|
|
54
|
-
const json = JSON.stringify(store, null, 2);
|
|
55
|
-
const encrypted = encrypt(json, key);
|
|
56
|
-
fs.writeFileSync(tokensFile(), encrypted, 'utf8');
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function readEncryptedToken(name) {
|
|
61
|
-
const key = getMachineKey();
|
|
62
|
-
const store = readAllTokens(key);
|
|
63
|
-
return store[name] || undefined;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async function deleteEncryptedToken(name) {
|
|
67
|
-
const key = getMachineKey();
|
|
68
|
-
const store = readAllTokens(key);
|
|
69
|
-
if (!(name in store)) return false;
|
|
70
|
-
delete store[name];
|
|
71
|
-
const json = JSON.stringify(store, null, 2);
|
|
72
|
-
const encrypted = encrypt(json, key);
|
|
73
|
-
fs.writeFileSync(tokensFile(), encrypted, 'utf8');
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function listTokenNames() {
|
|
78
|
-
const key = getMachineKey();
|
|
79
|
-
const store = readAllTokens(key);
|
|
80
|
-
return Object.keys(store);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function readAllTokens(key) {
|
|
84
|
-
if (!fs.existsSync(tokensFile())) return {};
|
|
85
|
-
try {
|
|
86
|
-
const data = fs.readFileSync(tokensFile(), 'utf8').trim();
|
|
87
|
-
const json = decrypt(data, key);
|
|
88
|
-
return JSON.parse(json);
|
|
89
|
-
} catch {
|
|
90
|
-
return {};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
module.exports = {
|
|
95
|
-
writeEncryptedToken, readEncryptedToken, deleteEncryptedToken, listTokenNames,
|
|
96
|
-
};
|