-
Notifications
You must be signed in to change notification settings - Fork 154
Expand file tree
/
Copy pathvalidate-legacy-compatibility.js
More file actions
107 lines (87 loc) · 3.75 KB
/
Copy pathvalidate-legacy-compatibility.js
File metadata and controls
107 lines (87 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/env node
/**
* Validates that legacy .claude-plugin manifests mirror the Open Plugins
* metadata. Existing marketplace subscriptions still resolve the legacy paths
* during auto-update, so these files must stay in sync. Mirrors are committed
* files (not links), so this guard must pass whenever marketplace/plugin
* metadata changes.
*/
const fs = require('fs');
const path = require('path');
const assert = require('assert/strict');
const ROOT = path.resolve(__dirname, '..');
const OPEN_MARKETPLACE_PATH = path.join(ROOT, 'marketplace.json');
const LEGACY_MARKETPLACE_PATH = path.join(ROOT, '.claude-plugin', 'marketplace.json');
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
}
function normalizeRelative(relativePath) {
return relativePath.replace(/\\/g, '/').replace(/\/+$/, '');
}
function pluginDirectoryFromOpenEntry(openMarketplace, plugin) {
const pluginRoot = openMarketplace.metadata?.pluginRoot || '.';
return path.resolve(ROOT, pluginRoot, plugin.source);
}
function expectedLegacySource(pluginDirectory) {
return `./${normalizeRelative(path.relative(ROOT, pluginDirectory))}`;
}
function assertJsonMirror(legacyPath, sourcePath) {
assert.deepEqual(readJson(legacyPath), readJson(sourcePath));
}
const errors = [];
function check(label, fn) {
try {
fn();
} catch (error) {
errors.push(`${label}: ${error.message}`);
}
}
check('legacy marketplace manifest', () => {
assert.ok(fs.existsSync(LEGACY_MARKETPLACE_PATH), 'missing .claude-plugin/marketplace.json');
assertJsonMirror(LEGACY_MARKETPLACE_PATH, OPEN_MARKETPLACE_PATH);
});
if (errors.length === 0) {
const openMarketplace = readJson(OPEN_MARKETPLACE_PATH);
const legacyMarketplace = readJson(LEGACY_MARKETPLACE_PATH);
const legacyPlugins = new Map((legacyMarketplace.plugins || []).map((plugin) => [plugin.name, plugin]));
const openPluginNames = new Set();
check('marketplace name', () => {
assert.equal(legacyMarketplace.name, openMarketplace.name);
});
for (const plugin of openMarketplace.plugins || []) {
openPluginNames.add(plugin.name);
const pluginDirectory = pluginDirectoryFromOpenEntry(openMarketplace, plugin);
const openManifestPath = path.join(pluginDirectory, '.plugin', 'plugin.json');
const legacyManifestPath = path.join(pluginDirectory, '.claude-plugin', 'plugin.json');
const relativeLegacyManifestPath = normalizeRelative(path.relative(ROOT, legacyManifestPath));
check(`${plugin.name} legacy marketplace entry`, () => {
const legacyPlugin = legacyPlugins.get(plugin.name);
assert.ok(legacyPlugin, 'missing from .claude-plugin/marketplace.json');
assert.equal(legacyPlugin.source, expectedLegacySource(pluginDirectory));
assert.equal(legacyPlugin.description, plugin.description);
assert.equal(legacyPlugin.category, 'development');
assert.deepEqual(legacyPlugin.tags || [], plugin.keywords || []);
});
check(`${plugin.name} marketplace version`, () => {
const pluginManifest = readJson(openManifestPath);
assert.equal(plugin.version, pluginManifest.version);
});
check(relativeLegacyManifestPath, () => {
assert.ok(fs.existsSync(legacyManifestPath), 'missing legacy plugin manifest');
assertJsonMirror(legacyManifestPath, openManifestPath);
});
}
for (const legacyPluginName of legacyPlugins.keys()) {
check(`${legacyPluginName} legacy marketplace entry`, () => {
assert.ok(openPluginNames.has(legacyPluginName), 'not present in marketplace.json');
});
}
}
if (errors.length > 0) {
console.log('Found legacy compatibility metadata issues:');
for (const error of errors) {
console.log(`- ${error}`);
}
process.exit(1);
}
console.log('Legacy .claude-plugin compatibility metadata is in sync.');