@altotyler/alto-rootstock-cli 1.0.1 → 1.0.2
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/package.json +1 -1
- package/src/commands/install.js +1 -87
- package/src/commands/new.js +1 -13
- package/src/lib/config.js +1 -14
- package/src/lib/fetcher.js +4 -7
package/package.json
CHANGED
package/src/commands/install.js
CHANGED
|
@@ -4,11 +4,8 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const chalk = require('chalk');
|
|
7
|
-
const prompts = require('prompts');
|
|
8
7
|
const { fetchRemoteFile } = require('../lib/fetcher');
|
|
9
|
-
const { getToken, saveToken } = require('../lib/config');
|
|
10
8
|
|
|
11
|
-
// VS Code Copilot global agent directory by platform
|
|
12
9
|
function getVsCodeAgentDir() {
|
|
13
10
|
switch (process.platform) {
|
|
14
11
|
case 'win32':
|
|
@@ -20,11 +17,6 @@ function getVsCodeAgentDir() {
|
|
|
20
17
|
}
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
// Global Claude Code commands directory
|
|
24
|
-
function getClaudeCommandsDir() {
|
|
25
|
-
return path.join(os.homedir(), '.claude', 'commands');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
20
|
const GLOBAL_FILES = [
|
|
29
21
|
{
|
|
30
22
|
remote: 'project-template/github/agents/Rootstock Agent.agent.md',
|
|
@@ -33,90 +25,12 @@ const GLOBAL_FILES = [
|
|
|
33
25
|
},
|
|
34
26
|
];
|
|
35
27
|
|
|
36
|
-
async function promptForToken() {
|
|
37
|
-
console.log();
|
|
38
|
-
console.log(chalk.yellow(' No GitHub token found.'));
|
|
39
|
-
console.log(chalk.dim(' A token with read:packages scope is required to access the private distribution repo.'));
|
|
40
|
-
console.log();
|
|
41
|
-
|
|
42
|
-
const { token } = await prompts(
|
|
43
|
-
{
|
|
44
|
-
type: 'password',
|
|
45
|
-
name: 'token',
|
|
46
|
-
message: 'GitHub Personal Access Token (read:packages)',
|
|
47
|
-
},
|
|
48
|
-
{ onCancel: () => process.exit(0) }
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
if (!token) return null;
|
|
52
|
-
|
|
53
|
-
const { save } = await prompts(
|
|
54
|
-
{
|
|
55
|
-
type: 'confirm',
|
|
56
|
-
name: 'save',
|
|
57
|
-
message: 'Save token to ~/.alto-rootstock/config.json for future use?',
|
|
58
|
-
initial: true,
|
|
59
|
-
},
|
|
60
|
-
{ onCancel: () => {} }
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
if (save) {
|
|
64
|
-
saveToken(token);
|
|
65
|
-
console.log(` ${chalk.green('✓')} Token saved to ~/.alto-rootstock/config.json`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Also write to ~/.npmrc so npm update works without re-entering the token
|
|
69
|
-
const npmrcPath = path.join(os.homedir(), '.npmrc');
|
|
70
|
-
const npmrcLine = `//npm.pkg.github.com/:_authToken=${token}`;
|
|
71
|
-
const npmrcScope = '@alto-tyler:registry=https://npm.pkg.github.com';
|
|
72
|
-
|
|
73
|
-
let npmrcContent = '';
|
|
74
|
-
if (fs.existsSync(npmrcPath)) {
|
|
75
|
-
npmrcContent = fs.readFileSync(npmrcPath, 'utf8');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let updated = false;
|
|
79
|
-
if (!npmrcContent.includes('//npm.pkg.github.com/:_authToken=')) {
|
|
80
|
-
npmrcContent += `\n${npmrcLine}\n`;
|
|
81
|
-
updated = true;
|
|
82
|
-
} else {
|
|
83
|
-
// Replace existing token line
|
|
84
|
-
npmrcContent = npmrcContent.replace(/\/\/npm\.pkg\.github\.com\/:_authToken=.*/g, npmrcLine);
|
|
85
|
-
updated = true;
|
|
86
|
-
}
|
|
87
|
-
if (!npmrcContent.includes('@alto-tyler:registry=')) {
|
|
88
|
-
npmrcContent += `${npmrcScope}\n`;
|
|
89
|
-
updated = true;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (updated) {
|
|
93
|
-
fs.writeFileSync(npmrcPath, npmrcContent.trimStart(), 'utf8');
|
|
94
|
-
console.log(` ${chalk.green('✓')} ~/.npmrc updated — ${chalk.cyan('npm update -g @altotyler/alto-rootstock-cli')} will work without re-entering a token`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
process.env.GITHUB_TOKEN = token;
|
|
98
|
-
return token;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
28
|
async function run() {
|
|
102
29
|
console.log();
|
|
103
30
|
console.log(chalk.bold(' Rootstock: Global Install / Update'));
|
|
104
31
|
console.log(chalk.dim(' ─────────────────────────────────────────────────'));
|
|
105
32
|
console.log();
|
|
106
33
|
|
|
107
|
-
let token = getToken();
|
|
108
|
-
if (!token) {
|
|
109
|
-
token = await promptForToken();
|
|
110
|
-
if (!token) {
|
|
111
|
-
console.error(chalk.red(' ✗ No token provided. Cannot access private distribution repo.'));
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
console.log(` ${chalk.green('✓')} GitHub token found`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
console.log();
|
|
119
|
-
|
|
120
34
|
for (const entry of GLOBAL_FILES) {
|
|
121
35
|
const target = entry.getTarget();
|
|
122
36
|
const dir = path.dirname(target);
|
|
@@ -143,7 +57,7 @@ async function run() {
|
|
|
143
57
|
console.log(chalk.dim(' 3. For project-level skills: run altors new or altors update in your project'));
|
|
144
58
|
console.log();
|
|
145
59
|
console.log(chalk.bold(' To update in future:'));
|
|
146
|
-
console.log(chalk.cyan(' npm update -g @altotyler/
|
|
60
|
+
console.log(chalk.cyan(' npm update -g @altotyler/rootstock-cli'));
|
|
147
61
|
console.log(chalk.cyan(' altors install'));
|
|
148
62
|
console.log();
|
|
149
63
|
}
|
package/src/commands/new.js
CHANGED
|
@@ -6,7 +6,7 @@ const fs = require('fs');
|
|
|
6
6
|
const chalk = require('chalk');
|
|
7
7
|
const prompts = require('prompts');
|
|
8
8
|
const { injectScaffolding } = require('../lib/scaffold');
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
|
|
11
11
|
function banner() {
|
|
12
12
|
console.log();
|
|
@@ -28,17 +28,6 @@ function checkSfCli() {
|
|
|
28
28
|
console.log(` ${chalk.green('✓')} Salesforce CLI detected ${chalk.dim(`(${version})`)}`);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function checkGithubToken() {
|
|
32
|
-
const token = getToken();
|
|
33
|
-
if (!token) {
|
|
34
|
-
console.log();
|
|
35
|
-
console.log(chalk.yellow(' ⚠ No GitHub token found.'));
|
|
36
|
-
console.log(chalk.dim(' Skill files are hosted on a private repo.'));
|
|
37
|
-
console.log(chalk.dim(' Set GITHUB_TOKEN or run:') + chalk.cyan(' altors install --save-token'));
|
|
38
|
-
console.log();
|
|
39
|
-
}
|
|
40
|
-
return token;
|
|
41
|
-
}
|
|
42
31
|
|
|
43
32
|
async function promptProjectDetails() {
|
|
44
33
|
console.log();
|
|
@@ -93,7 +82,6 @@ function runSfProjectGenerate(projectName, outputDir) {
|
|
|
93
82
|
async function run() {
|
|
94
83
|
banner();
|
|
95
84
|
checkSfCli();
|
|
96
|
-
checkGithubToken();
|
|
97
85
|
|
|
98
86
|
const { projectName, outputDir } = await promptProjectDetails();
|
|
99
87
|
|
package/src/lib/config.js
CHANGED
|
@@ -20,17 +20,4 @@ function load() {
|
|
|
20
20
|
return { ...DEFAULTS };
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
if (!fs.existsSync(CONFIG_DIR)) fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getToken() {
|
|
29
|
-
return process.env.GITHUB_TOKEN || load().token || null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function saveToken(token) {
|
|
33
|
-
save({ ...load(), token });
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
module.exports = { load, save, getToken, saveToken, CONFIG_FILE };
|
|
23
|
+
module.exports = { load, CONFIG_FILE };
|
package/src/lib/fetcher.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const https = require('https');
|
|
4
|
-
const { load
|
|
4
|
+
const { load } = require('./config');
|
|
5
5
|
|
|
6
|
-
function fetchUrl(url
|
|
6
|
+
function fetchUrl(url) {
|
|
7
7
|
return new Promise((resolve, reject) => {
|
|
8
8
|
const opts = new URL(url);
|
|
9
9
|
const headers = { 'User-Agent': 'alto-rootstock-cli' };
|
|
10
|
-
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
11
10
|
|
|
12
11
|
https.get({ hostname: opts.hostname, path: opts.pathname + opts.search, headers }, (res) => {
|
|
13
12
|
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
14
|
-
return fetchUrl(res.headers.location
|
|
13
|
+
return fetchUrl(res.headers.location).then(resolve).catch(reject);
|
|
15
14
|
}
|
|
16
15
|
if (res.statusCode !== 200) {
|
|
17
16
|
res.resume();
|
|
@@ -27,9 +26,7 @@ function fetchUrl(url, token) {
|
|
|
27
26
|
|
|
28
27
|
async function fetchRemoteFile(remotePath) {
|
|
29
28
|
const { baseUrl } = load();
|
|
30
|
-
|
|
31
|
-
const url = `${baseUrl}/${remotePath}`;
|
|
32
|
-
return fetchUrl(url, token);
|
|
29
|
+
return fetchUrl(`${baseUrl}/${remotePath}`);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
async function fetchRemoteJson(remotePath) {
|