@onuraslan/sdd 1.0.5 → 1.0.7
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/cli/install.js +54 -20
- package/cli/targets.js +4 -1
- package/package.json +1 -1
package/cli/install.js
CHANGED
|
@@ -17,11 +17,40 @@ function writeMetadata(metadataPath, targetId, plugins, version) {
|
|
|
17
17
|
fs.writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`, 'utf8');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
function writeMcpConfig(target, selectedPlugins) {
|
|
20
|
+
async function writeMcpConfig(target, selectedPlugins, scope = 'project', cwd = process.cwd()) {
|
|
21
21
|
if (!selectedPlugins.includes('frontend')) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
if (target.id === 'claude') {
|
|
26
|
+
const { spawnSync } = await import('node:child_process');
|
|
27
|
+
const commandArgs = ['mcp', 'add', '--scope', scope, '--transport', 'stdio', 'playwright', '--', 'npx', '-y', '@playwright/mcp'];
|
|
28
|
+
|
|
29
|
+
const result = process.platform === 'win32'
|
|
30
|
+
? spawnSync('cmd.exe', ['/d', '/s', '/c', 'claude', ...commandArgs], { cwd, stdio: ['inherit', 'pipe', 'pipe'], env: process.env })
|
|
31
|
+
: spawnSync('claude', commandArgs, { cwd, stdio: ['inherit', 'pipe', 'pipe'], env: process.env });
|
|
32
|
+
|
|
33
|
+
const combinedOutput = [result.stdout?.toString() || '', result.stderr?.toString() || ''].join('\n');
|
|
34
|
+
|
|
35
|
+
if (result.error && (result.error.code === 'ENOENT' || result.error.code === 'EINVAL')) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (result.error) {
|
|
40
|
+
throw new Error(`Claude MCP setup failed: ${result.error.message}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (result.status !== 0) {
|
|
44
|
+
const duplicateMatch = /already exists/i.test(combinedOutput);
|
|
45
|
+
if (duplicateMatch) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`Claude MCP setup exited with code ${result.status}.`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
25
54
|
const { mcpConfigPath, mcpFormat } = target;
|
|
26
55
|
const playwrightConfig = {
|
|
27
56
|
command: 'npx',
|
|
@@ -69,19 +98,25 @@ function writeMcpConfig(target, selectedPlugins) {
|
|
|
69
98
|
return;
|
|
70
99
|
}
|
|
71
100
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
101
|
+
let existing = {};
|
|
102
|
+
if (fs.existsSync(mcpConfigPath)) {
|
|
103
|
+
try {
|
|
104
|
+
existing = JSON.parse(fs.readFileSync(mcpConfigPath, 'utf8'));
|
|
105
|
+
} catch {
|
|
106
|
+
existing = {};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
75
109
|
|
|
76
110
|
const nextConfig = {
|
|
77
111
|
...existing,
|
|
78
112
|
mcpServers: {
|
|
79
113
|
...(existing.mcpServers || {}),
|
|
80
114
|
playwright: playwrightConfig
|
|
81
|
-
}
|
|
82
|
-
playwright: playwrightConfig
|
|
115
|
+
}
|
|
83
116
|
};
|
|
84
117
|
|
|
118
|
+
delete nextConfig.playwright;
|
|
119
|
+
|
|
85
120
|
const dir = path.dirname(mcpConfigPath);
|
|
86
121
|
fs.mkdirSync(dir, { recursive: true });
|
|
87
122
|
fs.writeFileSync(mcpConfigPath, `${JSON.stringify(nextConfig, null, 2)}\n`, 'utf8');
|
|
@@ -120,19 +155,18 @@ export async function installSelectedSkills({
|
|
|
120
155
|
const destination = path.join(target.installRoot, skillName);
|
|
121
156
|
|
|
122
157
|
if (fs.existsSync(destination)) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
throw new Error(`Skill already exists: ${skillName}`);
|
|
158
|
+
const action = conflictHandler
|
|
159
|
+
? await conflictHandler({ skillName, destination, source, pluginId })
|
|
160
|
+
: 'overwrite';
|
|
161
|
+
|
|
162
|
+
if (action === 'skip') {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (action === 'abort') {
|
|
166
|
+
throw new Error(`Installation aborted while processing Skill: ${skillName}`);
|
|
167
|
+
}
|
|
168
|
+
if (action === 'overwrite' || action === undefined) {
|
|
169
|
+
fs.rmSync(destination, { recursive: true, force: true });
|
|
136
170
|
}
|
|
137
171
|
}
|
|
138
172
|
|
|
@@ -142,7 +176,7 @@ export async function installSelectedSkills({
|
|
|
142
176
|
}
|
|
143
177
|
|
|
144
178
|
writeMetadata(target.metadataPath, targetId, consistentPlugins, version);
|
|
145
|
-
writeMcpConfig(target, consistentPlugins);
|
|
179
|
+
await writeMcpConfig(target, consistentPlugins, scope, cwd);
|
|
146
180
|
|
|
147
181
|
return {
|
|
148
182
|
installedCount,
|
package/cli/targets.js
CHANGED
|
@@ -57,7 +57,10 @@ export function resolveTargetPath(targetId, scope = 'project', cwd = process.cwd
|
|
|
57
57
|
const baseDir = resolveInstallBase(scope, cwd);
|
|
58
58
|
const installRoot = path.resolve(baseDir, target.skillDirectory);
|
|
59
59
|
const metadataPath = path.resolve(baseDir, path.dirname(target.skillDirectory), 'sdd.json');
|
|
60
|
-
const
|
|
60
|
+
const effectiveMcpConfigPath = target.id === 'claude' && scope === 'user'
|
|
61
|
+
? '.claude.json'
|
|
62
|
+
: target.mcpConfigPath;
|
|
63
|
+
const mcpConfigPath = path.resolve(baseDir, effectiveMcpConfigPath);
|
|
61
64
|
|
|
62
65
|
return {
|
|
63
66
|
...target,
|