@reservine/dx 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/bin/cli.ts +145 -3
- package/package.json +1 -1
package/bin/cli.ts
CHANGED
|
@@ -152,8 +152,113 @@ function install() {
|
|
|
152
152
|
writeSettings(settings);
|
|
153
153
|
ok(`Settings written to ${DIM}${SETTINGS_PATH}${RESET}`);
|
|
154
154
|
|
|
155
|
-
// Step 3:
|
|
156
|
-
step(3, "
|
|
155
|
+
// Step 3: Clone marketplace + register in plugin system
|
|
156
|
+
step(3, "Installing marketplace plugin");
|
|
157
|
+
|
|
158
|
+
const PLUGINS_DIR = join(homedir(), ".claude", "plugins");
|
|
159
|
+
const KNOWN_MARKETPLACES_PATH = join(PLUGINS_DIR, "known_marketplaces.json");
|
|
160
|
+
const INSTALLED_PLUGINS_PATH = join(PLUGINS_DIR, "installed_plugins.json");
|
|
161
|
+
const CACHE_DIR = join(PLUGINS_DIR, "cache", "reservine-dx", "reservine-dx", "1.0.0");
|
|
162
|
+
const PLUGIN_SOURCE = join(MARKETPLACE_DIR, "plugins", "reservine-dx");
|
|
163
|
+
|
|
164
|
+
// 3a: Clone marketplace repo if not present
|
|
165
|
+
if (!existsSync(MARKETPLACE_DIR)) {
|
|
166
|
+
info("Cloning marketplace from GitHub...");
|
|
167
|
+
try {
|
|
168
|
+
execSync(
|
|
169
|
+
`git clone git@github.com:Reservine/Reservine-DX.git ${JSON.stringify(MARKETPLACE_DIR)} 2>&1`,
|
|
170
|
+
{ encoding: "utf-8", stdio: "pipe" }
|
|
171
|
+
);
|
|
172
|
+
ok("Marketplace cloned");
|
|
173
|
+
} catch {
|
|
174
|
+
// Try HTTPS if SSH fails
|
|
175
|
+
try {
|
|
176
|
+
execSync(
|
|
177
|
+
`git clone ${REPO_URL} ${JSON.stringify(MARKETPLACE_DIR)} 2>&1`,
|
|
178
|
+
{ encoding: "utf-8", stdio: "pipe" }
|
|
179
|
+
);
|
|
180
|
+
ok("Marketplace cloned (via HTTPS)");
|
|
181
|
+
} catch (e) {
|
|
182
|
+
warn("Failed to clone marketplace — Claude Code will clone on next startup");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
info("Marketplace already cloned");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 3b: Create cache symlink (Claude Code reads plugins from cache/)
|
|
190
|
+
if (existsSync(PLUGIN_SOURCE)) {
|
|
191
|
+
mkdirSync(join(PLUGINS_DIR, "cache", "reservine-dx", "reservine-dx"), { recursive: true });
|
|
192
|
+
if (existsSync(CACHE_DIR)) {
|
|
193
|
+
// Remove old cache entry (might be stale symlink)
|
|
194
|
+
try { execSync(`rm -rf ${JSON.stringify(CACHE_DIR)}`); } catch {}
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
require("fs").symlinkSync(PLUGIN_SOURCE, CACHE_DIR);
|
|
198
|
+
ok("Cache symlink created");
|
|
199
|
+
} catch {
|
|
200
|
+
warn("Could not create cache symlink — Claude Code may not load skills until restart");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 3c: Register in known_marketplaces.json
|
|
205
|
+
try {
|
|
206
|
+
const knownPath = KNOWN_MARKETPLACES_PATH;
|
|
207
|
+
const known = existsSync(knownPath)
|
|
208
|
+
? JSON.parse(readFileSync(knownPath, "utf-8"))
|
|
209
|
+
: {};
|
|
210
|
+
|
|
211
|
+
if (!known["reservine-dx"]) {
|
|
212
|
+
known["reservine-dx"] = {
|
|
213
|
+
source: { source: "git", url: REPO_URL },
|
|
214
|
+
installLocation: MARKETPLACE_DIR,
|
|
215
|
+
lastUpdated: new Date().toISOString(),
|
|
216
|
+
};
|
|
217
|
+
writeFileSync(knownPath, JSON.stringify(known, null, 4) + "\n");
|
|
218
|
+
ok("Registered in known_marketplaces.json");
|
|
219
|
+
} else {
|
|
220
|
+
info("Already in known_marketplaces.json");
|
|
221
|
+
}
|
|
222
|
+
} catch {
|
|
223
|
+
warn("Could not update known_marketplaces.json");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 3d: Register in installed_plugins.json
|
|
227
|
+
try {
|
|
228
|
+
const instPath = INSTALLED_PLUGINS_PATH;
|
|
229
|
+
const inst = existsSync(instPath)
|
|
230
|
+
? JSON.parse(readFileSync(instPath, "utf-8"))
|
|
231
|
+
: { version: 2, plugins: {} };
|
|
232
|
+
|
|
233
|
+
if (!inst.plugins) inst.plugins = {};
|
|
234
|
+
|
|
235
|
+
// Get git commit sha if available
|
|
236
|
+
let sha = "";
|
|
237
|
+
try {
|
|
238
|
+
sha = execSync(`git -C ${JSON.stringify(MARKETPLACE_DIR)} rev-parse --short HEAD 2>/dev/null`, {
|
|
239
|
+
encoding: "utf-8",
|
|
240
|
+
}).trim();
|
|
241
|
+
} catch {}
|
|
242
|
+
|
|
243
|
+
inst.plugins["reservine-dx@reservine-dx"] = [
|
|
244
|
+
{
|
|
245
|
+
scope: "user",
|
|
246
|
+
installPath: CACHE_DIR,
|
|
247
|
+
version: "1.0.0",
|
|
248
|
+
installedAt: new Date().toISOString(),
|
|
249
|
+
lastUpdated: new Date().toISOString(),
|
|
250
|
+
gitCommitSha: sha,
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
writeFileSync(instPath, JSON.stringify(inst, null, 4) + "\n");
|
|
255
|
+
ok("Registered in installed_plugins.json");
|
|
256
|
+
} catch {
|
|
257
|
+
warn("Could not update installed_plugins.json");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Step 4: Summary
|
|
261
|
+
step(4, "Done!");
|
|
157
262
|
|
|
158
263
|
console.log(`
|
|
159
264
|
${GREEN}${BOLD}Reservine-DX installed successfully!${RESET}
|
|
@@ -164,12 +269,13 @@ function install() {
|
|
|
164
269
|
reservine-dx:cross-plan
|
|
165
270
|
${DIM}Commands${RESET} reservine-dx:cherry-pick-pr
|
|
166
271
|
reservine-dx:commit
|
|
272
|
+
reservine-dx:cleanup
|
|
167
273
|
${DIM}Scripts${RESET} setup-worktree.sh (auto-detects Angular/Laravel)
|
|
168
274
|
|
|
169
275
|
${BOLD}Next steps:${RESET}
|
|
170
276
|
${DIM}1.${RESET} Restart Claude Code to load the marketplace
|
|
171
277
|
${DIM}2.${RESET} Run ${CYAN}/reservine-dx:new-feature-planning${RESET} in any Reservine repo
|
|
172
|
-
${DIM}3.${RESET} Run ${CYAN}bunx reservine
|
|
278
|
+
${DIM}3.${RESET} Run ${CYAN}bunx @reservine/dx doctor${RESET} to verify everything
|
|
173
279
|
|
|
174
280
|
${DIM}Each repo needs a local plugin at:${RESET}
|
|
175
281
|
${DIM}.claude/skills/implement-plan/plugin.md${RESET}
|
|
@@ -485,6 +591,42 @@ function uninstall() {
|
|
|
485
591
|
writeSettings(settings);
|
|
486
592
|
ok(`Settings updated at ${DIM}${SETTINGS_PATH}${RESET}`);
|
|
487
593
|
|
|
594
|
+
// Remove from internal plugin registry
|
|
595
|
+
const PLUGINS_DIR = join(homedir(), ".claude", "plugins");
|
|
596
|
+
|
|
597
|
+
try {
|
|
598
|
+
const knownPath = join(PLUGINS_DIR, "known_marketplaces.json");
|
|
599
|
+
if (existsSync(knownPath)) {
|
|
600
|
+
const known = JSON.parse(readFileSync(knownPath, "utf-8"));
|
|
601
|
+
if (known["reservine-dx"]) {
|
|
602
|
+
delete known["reservine-dx"];
|
|
603
|
+
writeFileSync(knownPath, JSON.stringify(known, null, 4) + "\n");
|
|
604
|
+
ok("Removed from known_marketplaces.json");
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
} catch {}
|
|
608
|
+
|
|
609
|
+
try {
|
|
610
|
+
const instPath = join(PLUGINS_DIR, "installed_plugins.json");
|
|
611
|
+
if (existsSync(instPath)) {
|
|
612
|
+
const inst = JSON.parse(readFileSync(instPath, "utf-8"));
|
|
613
|
+
if (inst.plugins?.["reservine-dx@reservine-dx"]) {
|
|
614
|
+
delete inst.plugins["reservine-dx@reservine-dx"];
|
|
615
|
+
writeFileSync(instPath, JSON.stringify(inst, null, 4) + "\n");
|
|
616
|
+
ok("Removed from installed_plugins.json");
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
} catch {}
|
|
620
|
+
|
|
621
|
+
// Remove cache symlink
|
|
622
|
+
const cacheDir = join(PLUGINS_DIR, "cache", "reservine-dx");
|
|
623
|
+
if (existsSync(cacheDir)) {
|
|
624
|
+
try {
|
|
625
|
+
execSync(`rm -rf ${JSON.stringify(cacheDir)}`);
|
|
626
|
+
ok("Removed cache entry");
|
|
627
|
+
} catch {}
|
|
628
|
+
}
|
|
629
|
+
|
|
488
630
|
console.log(`
|
|
489
631
|
${BOLD}Uninstalled.${RESET}
|
|
490
632
|
|