claudeup 3.4.0 → 3.5.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/package.json
CHANGED
package/src/data/marketplaces.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { formatMarketplaceName } from "../utils/string-utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* Known repo aliases — GitHub redirects the old repo to the new one,
|
|
4
|
+
* so these should be treated as identical for deduplication.
|
|
5
|
+
*/
|
|
6
|
+
const REPO_ALIASES = {
|
|
7
|
+
"madappgang/claude-code": "madappgang/magus",
|
|
8
|
+
};
|
|
9
|
+
/** Normalize a repo string through known aliases. */
|
|
10
|
+
function normalizeRepo(repo) {
|
|
11
|
+
const lower = repo.toLowerCase();
|
|
12
|
+
return REPO_ALIASES[lower] || lower;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Deprecated marketplace names that should be hidden if the canonical
|
|
16
|
+
* marketplace is already present. Maps deprecated name → canonical name.
|
|
17
|
+
*/
|
|
18
|
+
export const deprecatedMarketplaces = {
|
|
19
|
+
"mag-claude-plugins": "magus",
|
|
20
|
+
};
|
|
2
21
|
export const defaultMarketplaces = [
|
|
3
22
|
{
|
|
4
23
|
name: "magus",
|
|
@@ -37,23 +56,36 @@ export function getMarketplaceByName(name) {
|
|
|
37
56
|
}
|
|
38
57
|
// Get all available marketplaces from local cache + hardcoded defaults
|
|
39
58
|
// Local cache is primary source of truth, defaults are fallback
|
|
40
|
-
// Deduplicates by repo URL to avoid showing same marketplace twice
|
|
59
|
+
// Deduplicates by normalized repo URL to avoid showing same marketplace twice
|
|
41
60
|
export function getAllMarketplaces(localMarketplaces) {
|
|
42
61
|
const all = new Map();
|
|
43
62
|
const seenRepos = new Set();
|
|
44
63
|
// Primary source: local cache (what's actually cloned)
|
|
45
64
|
if (localMarketplaces) {
|
|
46
65
|
for (const [name, local] of localMarketplaces) {
|
|
47
|
-
const repo = local.gitRepo || "";
|
|
66
|
+
const repo = normalizeRepo(local.gitRepo || "");
|
|
67
|
+
// Skip deprecated marketplaces if their canonical replacement exists
|
|
68
|
+
// (or will be added from defaults)
|
|
69
|
+
const canonical = deprecatedMarketplaces[name];
|
|
70
|
+
if (canonical) {
|
|
71
|
+
// If canonical already in the map or in defaults, skip this entry
|
|
72
|
+
if (all.has(canonical) || defaultMarketplaces.some((m) => m.name === canonical)) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Skip if another marketplace already claimed this repo URL
|
|
77
|
+
if (repo && seenRepos.has(repo))
|
|
78
|
+
continue;
|
|
48
79
|
if (repo)
|
|
49
|
-
seenRepos.add(repo
|
|
80
|
+
seenRepos.add(repo);
|
|
50
81
|
// Check if this marketplace has defaults (for official/featured flags)
|
|
51
82
|
const defaultMp = defaultMarketplaces.find((m) => m.name === name);
|
|
52
83
|
all.set(name, {
|
|
53
84
|
name,
|
|
54
|
-
displayName
|
|
55
|
-
|
|
56
|
-
|
|
85
|
+
// Prefer default displayName over stale local clone data
|
|
86
|
+
displayName: defaultMp?.displayName || local.name || formatMarketplaceName(name),
|
|
87
|
+
source: { source: "github", repo: defaultMp?.source.repo || local.gitRepo || "" },
|
|
88
|
+
description: defaultMp?.description || local.description || "",
|
|
57
89
|
official: defaultMp?.official ?? repo.toLowerCase().includes("anthropics/"),
|
|
58
90
|
featured: defaultMp?.featured,
|
|
59
91
|
});
|
|
@@ -61,7 +93,7 @@ export function getAllMarketplaces(localMarketplaces) {
|
|
|
61
93
|
}
|
|
62
94
|
// Fallback: hardcoded defaults (only if their repo isn't already represented)
|
|
63
95
|
for (const mp of defaultMarketplaces) {
|
|
64
|
-
const repo = mp.source.repo
|
|
96
|
+
const repo = normalizeRepo(mp.source.repo || "");
|
|
65
97
|
if (!all.has(mp.name) && !seenRepos.has(repo)) {
|
|
66
98
|
all.set(mp.name, mp);
|
|
67
99
|
if (repo)
|
package/src/data/marketplaces.ts
CHANGED
|
@@ -2,6 +2,28 @@ import type { Marketplace } from "../types/index.js";
|
|
|
2
2
|
import type { LocalMarketplace } from "../services/local-marketplace.js";
|
|
3
3
|
import { formatMarketplaceName } from "../utils/string-utils.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Known repo aliases — GitHub redirects the old repo to the new one,
|
|
7
|
+
* so these should be treated as identical for deduplication.
|
|
8
|
+
*/
|
|
9
|
+
const REPO_ALIASES: Record<string, string> = {
|
|
10
|
+
"madappgang/claude-code": "madappgang/magus",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** Normalize a repo string through known aliases. */
|
|
14
|
+
function normalizeRepo(repo: string): string {
|
|
15
|
+
const lower = repo.toLowerCase();
|
|
16
|
+
return REPO_ALIASES[lower] || lower;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Deprecated marketplace names that should be hidden if the canonical
|
|
21
|
+
* marketplace is already present. Maps deprecated name → canonical name.
|
|
22
|
+
*/
|
|
23
|
+
export const deprecatedMarketplaces: Record<string, string> = {
|
|
24
|
+
"mag-claude-plugins": "magus",
|
|
25
|
+
};
|
|
26
|
+
|
|
5
27
|
export const defaultMarketplaces: Marketplace[] = [
|
|
6
28
|
{
|
|
7
29
|
name: "magus",
|
|
@@ -45,7 +67,7 @@ export function getMarketplaceByName(name: string): Marketplace | undefined {
|
|
|
45
67
|
|
|
46
68
|
// Get all available marketplaces from local cache + hardcoded defaults
|
|
47
69
|
// Local cache is primary source of truth, defaults are fallback
|
|
48
|
-
// Deduplicates by repo URL to avoid showing same marketplace twice
|
|
70
|
+
// Deduplicates by normalized repo URL to avoid showing same marketplace twice
|
|
49
71
|
export function getAllMarketplaces(
|
|
50
72
|
localMarketplaces?: Map<string, LocalMarketplace>,
|
|
51
73
|
): Marketplace[] {
|
|
@@ -55,17 +77,31 @@ export function getAllMarketplaces(
|
|
|
55
77
|
// Primary source: local cache (what's actually cloned)
|
|
56
78
|
if (localMarketplaces) {
|
|
57
79
|
for (const [name, local] of localMarketplaces) {
|
|
58
|
-
const repo = local.gitRepo || "";
|
|
59
|
-
|
|
80
|
+
const repo = normalizeRepo(local.gitRepo || "");
|
|
81
|
+
|
|
82
|
+
// Skip deprecated marketplaces if their canonical replacement exists
|
|
83
|
+
// (or will be added from defaults)
|
|
84
|
+
const canonical = deprecatedMarketplaces[name];
|
|
85
|
+
if (canonical) {
|
|
86
|
+
// If canonical already in the map or in defaults, skip this entry
|
|
87
|
+
if (all.has(canonical) || defaultMarketplaces.some((m) => m.name === canonical)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Skip if another marketplace already claimed this repo URL
|
|
93
|
+
if (repo && seenRepos.has(repo)) continue;
|
|
94
|
+
if (repo) seenRepos.add(repo);
|
|
60
95
|
|
|
61
96
|
// Check if this marketplace has defaults (for official/featured flags)
|
|
62
97
|
const defaultMp = defaultMarketplaces.find((m) => m.name === name);
|
|
63
98
|
|
|
64
99
|
all.set(name, {
|
|
65
100
|
name,
|
|
66
|
-
displayName
|
|
67
|
-
|
|
68
|
-
|
|
101
|
+
// Prefer default displayName over stale local clone data
|
|
102
|
+
displayName: defaultMp?.displayName || local.name || formatMarketplaceName(name),
|
|
103
|
+
source: { source: "github" as const, repo: defaultMp?.source.repo || local.gitRepo || "" },
|
|
104
|
+
description: defaultMp?.description || local.description || "",
|
|
69
105
|
official:
|
|
70
106
|
defaultMp?.official ?? repo.toLowerCase().includes("anthropics/"),
|
|
71
107
|
featured: defaultMp?.featured,
|
|
@@ -75,7 +111,7 @@ export function getAllMarketplaces(
|
|
|
75
111
|
|
|
76
112
|
// Fallback: hardcoded defaults (only if their repo isn't already represented)
|
|
77
113
|
for (const mp of defaultMarketplaces) {
|
|
78
|
-
const repo = mp.source.repo
|
|
114
|
+
const repo = normalizeRepo(mp.source.repo || "");
|
|
79
115
|
if (!all.has(mp.name) && !seenRepos.has(repo)) {
|
|
80
116
|
all.set(mp.name, mp);
|
|
81
117
|
if (repo) seenRepos.add(repo);
|
|
@@ -519,23 +519,70 @@ export async function migrateMarketplaceRename(projectPath) {
|
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
catch { /* skip if unreadable */ }
|
|
522
|
-
// 4. known_marketplaces.json — rename the key
|
|
522
|
+
// 4. known_marketplaces.json — rename the key + physical directory cleanup
|
|
523
|
+
const pluginsDir = path.join(os.homedir(), ".claude", "plugins", "marketplaces");
|
|
524
|
+
const oldDir = path.join(pluginsDir, OLD_MARKETPLACE_NAME);
|
|
525
|
+
const newDir = path.join(pluginsDir, NEW_MARKETPLACE_NAME);
|
|
523
526
|
try {
|
|
524
527
|
const known = await readKnownMarketplaces();
|
|
528
|
+
let knownModified = false;
|
|
525
529
|
if (known[OLD_MARKETPLACE_NAME]) {
|
|
526
|
-
known[
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
530
|
+
const oldEntry = known[OLD_MARKETPLACE_NAME];
|
|
531
|
+
// If canonical entry already exists, just delete the old one
|
|
532
|
+
if (!known[NEW_MARKETPLACE_NAME]) {
|
|
533
|
+
known[NEW_MARKETPLACE_NAME] = {
|
|
534
|
+
...oldEntry,
|
|
535
|
+
source: {
|
|
536
|
+
...oldEntry.source,
|
|
537
|
+
repo: "MadAppGang/magus",
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
}
|
|
533
541
|
delete known[OLD_MARKETPLACE_NAME];
|
|
542
|
+
knownModified = true;
|
|
543
|
+
}
|
|
544
|
+
// Ensure installLocation points to new directory name
|
|
545
|
+
if (known[NEW_MARKETPLACE_NAME]?.installLocation?.includes(OLD_MARKETPLACE_NAME)) {
|
|
546
|
+
known[NEW_MARKETPLACE_NAME].installLocation =
|
|
547
|
+
known[NEW_MARKETPLACE_NAME].installLocation.replace(OLD_MARKETPLACE_NAME, NEW_MARKETPLACE_NAME);
|
|
548
|
+
knownModified = true;
|
|
549
|
+
}
|
|
550
|
+
if (knownModified) {
|
|
534
551
|
await writeKnownMarketplaces(known);
|
|
535
552
|
result.knownMarketplacesMigrated = true;
|
|
536
553
|
}
|
|
537
554
|
}
|
|
538
555
|
catch { /* skip if unreadable */ }
|
|
556
|
+
// 4b. Rename/remove the old physical directory (runs even if key was already migrated)
|
|
557
|
+
try {
|
|
558
|
+
if (await fs.pathExists(oldDir)) {
|
|
559
|
+
if (!(await fs.pathExists(newDir))) {
|
|
560
|
+
await fs.rename(oldDir, newDir);
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
// Both exist — remove the old one (magus dir is canonical)
|
|
564
|
+
await fs.remove(oldDir);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
catch { /* non-fatal: directory cleanup is best-effort */ }
|
|
569
|
+
// 4c. Update git remote URL in the marketplace clone (old → new repo)
|
|
570
|
+
try {
|
|
571
|
+
const marketplaceDir = await fs.pathExists(newDir) ? newDir : oldDir;
|
|
572
|
+
if (await fs.pathExists(path.join(marketplaceDir, ".git"))) {
|
|
573
|
+
const { execSync } = await import("node:child_process");
|
|
574
|
+
const remote = execSync("git remote get-url origin", {
|
|
575
|
+
cwd: marketplaceDir, encoding: "utf-8", timeout: 5000,
|
|
576
|
+
}).trim();
|
|
577
|
+
if (remote.includes("claude-code") && remote.includes("MadAppGang")) {
|
|
578
|
+
const newRemote = remote.replace("claude-code", NEW_MARKETPLACE_NAME);
|
|
579
|
+
execSync(`git remote set-url origin "${newRemote}"`, {
|
|
580
|
+
cwd: marketplaceDir, encoding: "utf-8", timeout: 5000,
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
catch { /* non-fatal: git remote update is best-effort */ }
|
|
539
586
|
// 5. installed_plugins.json — rename plugin ID keys
|
|
540
587
|
try {
|
|
541
588
|
const registry = await readInstalledPluginsRegistry();
|
|
@@ -748,23 +748,77 @@ export async function migrateMarketplaceRename(
|
|
|
748
748
|
}
|
|
749
749
|
} catch { /* skip if unreadable */ }
|
|
750
750
|
|
|
751
|
-
// 4. known_marketplaces.json — rename the key
|
|
751
|
+
// 4. known_marketplaces.json — rename the key + physical directory cleanup
|
|
752
|
+
const pluginsDir = path.join(os.homedir(), ".claude", "plugins", "marketplaces");
|
|
753
|
+
const oldDir = path.join(pluginsDir, OLD_MARKETPLACE_NAME);
|
|
754
|
+
const newDir = path.join(pluginsDir, NEW_MARKETPLACE_NAME);
|
|
755
|
+
|
|
752
756
|
try {
|
|
753
757
|
const known = await readKnownMarketplaces();
|
|
758
|
+
let knownModified = false;
|
|
759
|
+
|
|
754
760
|
if (known[OLD_MARKETPLACE_NAME]) {
|
|
755
|
-
known[
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
761
|
+
const oldEntry = known[OLD_MARKETPLACE_NAME];
|
|
762
|
+
|
|
763
|
+
// If canonical entry already exists, just delete the old one
|
|
764
|
+
if (!known[NEW_MARKETPLACE_NAME]) {
|
|
765
|
+
known[NEW_MARKETPLACE_NAME] = {
|
|
766
|
+
...oldEntry,
|
|
767
|
+
source: {
|
|
768
|
+
...oldEntry.source,
|
|
769
|
+
repo: "MadAppGang/magus",
|
|
770
|
+
},
|
|
771
|
+
};
|
|
772
|
+
}
|
|
762
773
|
delete known[OLD_MARKETPLACE_NAME];
|
|
774
|
+
knownModified = true;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Ensure installLocation points to new directory name
|
|
778
|
+
if (known[NEW_MARKETPLACE_NAME]?.installLocation?.includes(OLD_MARKETPLACE_NAME)) {
|
|
779
|
+
known[NEW_MARKETPLACE_NAME].installLocation =
|
|
780
|
+
known[NEW_MARKETPLACE_NAME].installLocation.replace(
|
|
781
|
+
OLD_MARKETPLACE_NAME,
|
|
782
|
+
NEW_MARKETPLACE_NAME,
|
|
783
|
+
);
|
|
784
|
+
knownModified = true;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (knownModified) {
|
|
763
788
|
await writeKnownMarketplaces(known);
|
|
764
789
|
result.knownMarketplacesMigrated = true;
|
|
765
790
|
}
|
|
766
791
|
} catch { /* skip if unreadable */ }
|
|
767
792
|
|
|
793
|
+
// 4b. Rename/remove the old physical directory (runs even if key was already migrated)
|
|
794
|
+
try {
|
|
795
|
+
if (await fs.pathExists(oldDir)) {
|
|
796
|
+
if (!(await fs.pathExists(newDir))) {
|
|
797
|
+
await fs.rename(oldDir, newDir);
|
|
798
|
+
} else {
|
|
799
|
+
// Both exist — remove the old one (magus dir is canonical)
|
|
800
|
+
await fs.remove(oldDir);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
} catch { /* non-fatal: directory cleanup is best-effort */ }
|
|
804
|
+
|
|
805
|
+
// 4c. Update git remote URL in the marketplace clone (old → new repo)
|
|
806
|
+
try {
|
|
807
|
+
const marketplaceDir = await fs.pathExists(newDir) ? newDir : oldDir;
|
|
808
|
+
if (await fs.pathExists(path.join(marketplaceDir, ".git"))) {
|
|
809
|
+
const { execSync } = await import("node:child_process");
|
|
810
|
+
const remote = execSync("git remote get-url origin", {
|
|
811
|
+
cwd: marketplaceDir, encoding: "utf-8", timeout: 5000,
|
|
812
|
+
}).trim();
|
|
813
|
+
if (remote.includes("claude-code") && remote.includes("MadAppGang")) {
|
|
814
|
+
const newRemote = remote.replace("claude-code", NEW_MARKETPLACE_NAME);
|
|
815
|
+
execSync(`git remote set-url origin "${newRemote}"`, {
|
|
816
|
+
cwd: marketplaceDir, encoding: "utf-8", timeout: 5000,
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
} catch { /* non-fatal: git remote update is best-effort */ }
|
|
821
|
+
|
|
768
822
|
// 5. installed_plugins.json — rename plugin ID keys
|
|
769
823
|
try {
|
|
770
824
|
const registry = await readInstalledPluginsRegistry();
|