@str-public/installer 0.3.0 → 0.4.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/dist/cli.js +81 -32
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -47,8 +47,9 @@ async function main() {
|
|
|
47
47
|
const tools = await multiselect({
|
|
48
48
|
message: 'What would you like to install?',
|
|
49
49
|
options: [
|
|
50
|
-
{ value: 'theme-switcher', label: 'Theme Switcher', hint: '
|
|
51
|
-
{ value: 'basic-cursor-settings', label: 'Basic Cursor Settings', hint: 'Workspace folders and AI agent rules' }
|
|
50
|
+
{ value: 'theme-switcher', label: 'Theme Switcher', hint: 'Stronghold / Stronghold Dusk' },
|
|
51
|
+
{ value: 'basic-cursor-settings', label: 'Basic Cursor Settings', hint: 'Workspace folders and AI agent rules' },
|
|
52
|
+
{ value: 'development-standards', label: 'Development Standards', hint: 'TypeScript & Next.js strict rules (.mdc)' }
|
|
52
53
|
],
|
|
53
54
|
required: true
|
|
54
55
|
});
|
|
@@ -62,51 +63,59 @@ async function main() {
|
|
|
62
63
|
s.start('Downloading and installing selected tools...');
|
|
63
64
|
try {
|
|
64
65
|
if (selectedTools.includes('theme-switcher')) {
|
|
65
|
-
s.message('Installing Theme Switcher...');
|
|
66
|
+
s.message('Installing Theme Switcher and Themes...');
|
|
66
67
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'str-installer-'));
|
|
67
68
|
try {
|
|
68
|
-
// Pack the package to get the vsix
|
|
69
|
+
// Pack the package to get the vsix files
|
|
69
70
|
execSync(`npm pack @str-public/theme-switcher@${tag} --pack-destination "${tmpDir}"`, { stdio: 'ignore' });
|
|
70
71
|
const tgzFile = fs.readdirSync(tmpDir).find(f => f.endsWith('.tgz'));
|
|
71
72
|
if (!tgzFile)
|
|
72
73
|
throw new Error('Failed to download theme-switcher package.');
|
|
73
74
|
execSync(`tar -xzf ${tgzFile}`, { cwd: tmpDir, stdio: 'ignore' });
|
|
74
75
|
const packageDir = path.join(tmpDir, 'package');
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
throw new Error('VSIX
|
|
78
|
-
const vsixPath = path.join(packageDir, vsixFile);
|
|
76
|
+
const vsixFiles = fs.readdirSync(packageDir).filter(f => f.endsWith('.vsix'));
|
|
77
|
+
if (vsixFiles.length === 0)
|
|
78
|
+
throw new Error('No VSIX files found in the downloaded package.');
|
|
79
79
|
// Define target directories based on IDE selection
|
|
80
80
|
const homeDir = os.homedir();
|
|
81
81
|
const idePaths = {
|
|
82
82
|
cursor: path.join(homeDir, '.cursor', 'extensions'),
|
|
83
83
|
code: path.join(homeDir, '.vscode', 'extensions')
|
|
84
84
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
// Ensure the base extensions directory exists
|
|
90
|
-
if (!fs.existsSync(targetExtDir)) {
|
|
91
|
-
fs.mkdirSync(targetExtDir, { recursive: true });
|
|
92
|
-
}
|
|
93
|
-
const finalPath = path.join(targetExtDir, extFolderName);
|
|
94
|
-
// Clean up existing installation if it exists
|
|
95
|
-
if (fs.existsSync(finalPath)) {
|
|
96
|
-
fs.rmSync(finalPath, { recursive: true, force: true });
|
|
97
|
-
}
|
|
98
|
-
fs.mkdirSync(finalPath, { recursive: true });
|
|
99
|
-
// Unzip the vsix 'extension' folder into a temp dir
|
|
100
|
-
const unzipTemp = path.join(tmpDir, `unzip-${ide}`);
|
|
85
|
+
for (const vsixFile of vsixFiles) {
|
|
86
|
+
const vsixPath = path.join(packageDir, vsixFile);
|
|
87
|
+
// Unzip the vsix 'extension' folder into a temp dir to read its package.json
|
|
88
|
+
const unzipTemp = path.join(tmpDir, `unzip-meta-${vsixFile}`);
|
|
101
89
|
fs.mkdirSync(unzipTemp, { recursive: true });
|
|
102
|
-
// Use native unzip to extract just the extension
|
|
103
|
-
execSync(`unzip -q "${vsixPath}" "extension
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
for (const
|
|
109
|
-
|
|
90
|
+
// Use native unzip to extract just the extension/package.json
|
|
91
|
+
execSync(`unzip -q "${vsixPath}" "extension/package.json" -d "${unzipTemp}"`, { stdio: 'ignore' });
|
|
92
|
+
const extPkgJsonPath = path.join(unzipTemp, 'extension', 'package.json');
|
|
93
|
+
const extPkg = JSON.parse(fs.readFileSync(extPkgJsonPath, 'utf-8'));
|
|
94
|
+
// The exact folder name VS Code/Cursor expects: <publisher>.<name>-<version>
|
|
95
|
+
const extFolderName = `${extPkg.publisher}.${extPkg.name}-${extPkg.version}`;
|
|
96
|
+
for (const ide of selectedIdes) {
|
|
97
|
+
const targetExtDir = idePaths[ide];
|
|
98
|
+
// Ensure the base extensions directory exists
|
|
99
|
+
if (!fs.existsSync(targetExtDir)) {
|
|
100
|
+
fs.mkdirSync(targetExtDir, { recursive: true });
|
|
101
|
+
}
|
|
102
|
+
const finalPath = path.join(targetExtDir, extFolderName);
|
|
103
|
+
// Clean up existing installation if it exists
|
|
104
|
+
if (fs.existsSync(finalPath)) {
|
|
105
|
+
fs.rmSync(finalPath, { recursive: true, force: true });
|
|
106
|
+
}
|
|
107
|
+
fs.mkdirSync(finalPath, { recursive: true });
|
|
108
|
+
// Unzip the vsix 'extension' folder into a temp dir
|
|
109
|
+
const extractTemp = path.join(tmpDir, `extract-${ide}-${vsixFile}`);
|
|
110
|
+
fs.mkdirSync(extractTemp, { recursive: true });
|
|
111
|
+
// Use native unzip to extract just the extension folder
|
|
112
|
+
execSync(`unzip -q "${vsixPath}" "extension/*" -d "${extractTemp}"`, { stdio: 'ignore' });
|
|
113
|
+
// Move contents from extractTemp/extension/* to finalPath
|
|
114
|
+
const sourceExtDir = path.join(extractTemp, 'extension');
|
|
115
|
+
const files = fs.readdirSync(sourceExtDir);
|
|
116
|
+
for (const file of files) {
|
|
117
|
+
fs.renameSync(path.join(sourceExtDir, file), path.join(finalPath, file));
|
|
118
|
+
}
|
|
110
119
|
}
|
|
111
120
|
}
|
|
112
121
|
}
|
|
@@ -171,6 +180,46 @@ async function main() {
|
|
|
171
180
|
}
|
|
172
181
|
}
|
|
173
182
|
}
|
|
183
|
+
if (selectedTools.includes('development-standards')) {
|
|
184
|
+
s.message('Installing Development Standards...');
|
|
185
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'str-installer-dev-standards-'));
|
|
186
|
+
try {
|
|
187
|
+
execSync(`npm pack @str-public/development-standards@${tag} --pack-destination "${tmpDir}"`, { stdio: 'ignore' });
|
|
188
|
+
const tgzFile = fs.readdirSync(tmpDir).find(f => f.endsWith('.tgz'));
|
|
189
|
+
if (!tgzFile)
|
|
190
|
+
throw new Error('Failed to download development-standards package.');
|
|
191
|
+
execSync(`tar -xzf ${tgzFile}`, { cwd: tmpDir, stdio: 'ignore' });
|
|
192
|
+
const targetDir = process.cwd();
|
|
193
|
+
const rulesDir = path.join(targetDir, '.cursor', 'rules');
|
|
194
|
+
if (!fs.existsSync(rulesDir)) {
|
|
195
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
196
|
+
}
|
|
197
|
+
const sourceRulePath = path.join(tmpDir, 'package', 'templates', 'development-standards.mdc');
|
|
198
|
+
const targetRulePath = path.join(rulesDir, 'development-standards.mdc');
|
|
199
|
+
if (fs.existsSync(sourceRulePath)) {
|
|
200
|
+
if (fs.existsSync(targetRulePath)) {
|
|
201
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
202
|
+
const backupPath = path.join(rulesDir, `development-standards.${timestamp}.backup.mdc`);
|
|
203
|
+
fs.renameSync(targetRulePath, backupPath);
|
|
204
|
+
}
|
|
205
|
+
fs.copyFileSync(sourceRulePath, targetRulePath);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
throw new Error('development-standards.mdc template not found in the downloaded package.');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
throw new Error(`Development Standards installation failed: ${e.message || String(e)}`);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
try {
|
|
216
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
// Ignore cleanup errors
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
174
223
|
s.stop('Installation complete!');
|
|
175
224
|
outro(pc.green('✔ All selected tools have been installed successfully. Please restart your IDE(s).'));
|
|
176
225
|
}
|
package/package.json
CHANGED