plugin-updater 1.0.8 → 1.0.10
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/.github/workflows/publish.yml +1 -1
- package/index.js +100 -28
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const { execSync } = require('child_process');
|
|
@@ -15,6 +15,31 @@ function getAppConfigDir(appName) {
|
|
|
15
15
|
return fs.existsSync(directPath) ? directPath : configPath;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
function writeLog(message, isError = false) {
|
|
19
|
+
try {
|
|
20
|
+
const date = new Date();
|
|
21
|
+
const dateStr = date.toISOString().split('T')[0];
|
|
22
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
23
|
+
const appName = isClaude ? "claude" : "opencode";
|
|
24
|
+
const configDir = getAppConfigDir(appName);
|
|
25
|
+
|
|
26
|
+
const logsDir = path.join(configDir, "logs", dateStr);
|
|
27
|
+
if (!fs.existsSync(logsDir)) {
|
|
28
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const logFile = path.join(logsDir, `updater-${dateStr}.log`);
|
|
32
|
+
const prefix = isError ? "[ERROR]" : "[INFO]";
|
|
33
|
+
const logMsg = `[${date.toISOString()}] ${prefix} ${message}\n`;
|
|
34
|
+
|
|
35
|
+
fs.appendFileSync(logFile, logMsg);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
// Silent fallback if logging fails
|
|
38
|
+
}
|
|
39
|
+
if (isError) console.error(message);
|
|
40
|
+
else console.log(message);
|
|
41
|
+
}
|
|
42
|
+
|
|
18
43
|
function getReposDir() {
|
|
19
44
|
const isClaude = process.argv.join(' ').includes('claude');
|
|
20
45
|
const appName = isClaude ? "claude" : "opencode";
|
|
@@ -22,11 +47,12 @@ function getReposDir() {
|
|
|
22
47
|
}
|
|
23
48
|
|
|
24
49
|
function executeGit(command, cwd) {
|
|
50
|
+
writeLog(`Executing git: ${command} in ${cwd}`);
|
|
25
51
|
try {
|
|
26
52
|
execSync(command, { cwd, stdio: "ignore" });
|
|
27
53
|
return true;
|
|
28
54
|
} catch (error) {
|
|
29
|
-
|
|
55
|
+
writeLog(`Git error in ${cwd}: ${error.message}`, true);
|
|
30
56
|
return false;
|
|
31
57
|
}
|
|
32
58
|
}
|
|
@@ -67,12 +93,23 @@ const updaterAPI = {
|
|
|
67
93
|
const sourceDir = path.join(getReposDir(), pluginName);
|
|
68
94
|
if (!fs.existsSync(sourceDir)) return false;
|
|
69
95
|
|
|
70
|
-
|
|
96
|
+
const packageJsonPath = path.join(sourceDir, "package.json");
|
|
97
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
71
98
|
try {
|
|
99
|
+
writeLog(`Running npm install for ${pluginName}`);
|
|
72
100
|
execSync("npm install", { cwd: sourceDir, stdio: "ignore" });
|
|
73
|
-
|
|
101
|
+
writeLog(`Finished npm install for ${pluginName}`);
|
|
102
|
+
|
|
103
|
+
// Safely check if a build script exists before executing
|
|
104
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
105
|
+
if (pkg.scripts && pkg.scripts.build) {
|
|
106
|
+
execSync("npm run build", { cwd: sourceDir, stdio: "ignore" });
|
|
107
|
+
writeLog(`Finished npm run build for ${pluginName}`);
|
|
108
|
+
} else {
|
|
109
|
+
writeLog(`Skipped npm run build for ${pluginName} (no build script found)`);
|
|
110
|
+
}
|
|
74
111
|
} catch (error) {
|
|
75
|
-
|
|
112
|
+
writeLog(`Build/Install failed for ${pluginName}: ${error.message}`, true);
|
|
76
113
|
}
|
|
77
114
|
}
|
|
78
115
|
|
|
@@ -85,31 +122,50 @@ const updaterAPI = {
|
|
|
85
122
|
}
|
|
86
123
|
|
|
87
124
|
try {
|
|
125
|
+
writeLog(`Running cpSync for ${pluginName}`);
|
|
88
126
|
fs.cpSync(deploySource, pluginExecutionPath, { recursive: true, force: true });
|
|
89
|
-
|
|
90
|
-
} catch (
|
|
91
|
-
|
|
92
|
-
return false;
|
|
127
|
+
writeLog(`Finished cpSync for ${pluginName}`);
|
|
128
|
+
} catch (e) {
|
|
129
|
+
writeLog(`cpSync failed for ${pluginName}: ${e.message}`, true);
|
|
93
130
|
}
|
|
131
|
+
return true;
|
|
94
132
|
},
|
|
95
133
|
|
|
96
|
-
rebuild: function(
|
|
97
|
-
const
|
|
98
|
-
const
|
|
134
|
+
rebuild: function(pluginName) {
|
|
135
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
136
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
137
|
+
this.deployToExecutionDir(pluginName, path.join(configDir, "plugin"));
|
|
138
|
+
return "Rebuilt " + pluginName;
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
downgrade: function(pluginName, commitHash) {
|
|
142
|
+
const reposDir = getReposDir();
|
|
143
|
+
const targetDir = path.join(reposDir, pluginName);
|
|
99
144
|
if (fs.existsSync(targetDir)) {
|
|
100
|
-
|
|
145
|
+
executeGit(`git fetch origin`, targetDir);
|
|
146
|
+
executeGit(`git checkout ${commitHash}`, targetDir);
|
|
147
|
+
executeGit(`git submodule update --init --recursive`, targetDir);
|
|
148
|
+
return this.rebuild(pluginName);
|
|
101
149
|
}
|
|
102
|
-
return
|
|
150
|
+
return "Repo not found";
|
|
103
151
|
},
|
|
104
152
|
|
|
105
153
|
disable: function(plugin) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
154
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
155
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
156
|
+
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
157
|
+
if (fs.existsSync(pluginsJsonPath)) {
|
|
158
|
+
let plugins = JSON.parse(fs.readFileSync(pluginsJsonPath, "utf-8"));
|
|
159
|
+
const pluginIndex = plugins.findIndex(p => p.name === plugin.name);
|
|
160
|
+
if (pluginIndex >= 0) {
|
|
161
|
+
plugins[pluginIndex].enabled = false;
|
|
162
|
+
fs.writeFileSync(pluginsJsonPath, JSON.stringify(plugins, null, 2), "utf-8");
|
|
111
163
|
}
|
|
112
|
-
}
|
|
164
|
+
}
|
|
165
|
+
const pluginExecutionPath = path.join(configDir, "plugin", plugin.name);
|
|
166
|
+
if (fs.existsSync(pluginExecutionPath)) {
|
|
167
|
+
try { fs.rmSync(pluginExecutionPath, { recursive: true, force: true }); } catch (e) {}
|
|
168
|
+
}
|
|
113
169
|
},
|
|
114
170
|
|
|
115
171
|
uninstall: function(plugin) {
|
|
@@ -122,8 +178,15 @@ const updaterAPI = {
|
|
|
122
178
|
};
|
|
123
179
|
|
|
124
180
|
const pluginUpdaterEntry = async function(input) {
|
|
181
|
+
const configDir = (input && input.configDir) ? input.configDir : path.dirname(getReposDir());
|
|
182
|
+
|
|
183
|
+
// 1. GUARANTEE BASE DIRECTORIES EXIST ON LAUNCH
|
|
184
|
+
const reposDir = path.join(configDir, "repos");
|
|
185
|
+
const pluginsDir = path.join(configDir, "plugin");
|
|
186
|
+
if (!fs.existsSync(reposDir)) fs.mkdirSync(reposDir, { recursive: true });
|
|
187
|
+
if (!fs.existsSync(pluginsDir)) fs.mkdirSync(pluginsDir, { recursive: true });
|
|
188
|
+
|
|
125
189
|
if (!global.__PLUGIN_UPDATER_HANDLED_BY_HUB__) {
|
|
126
|
-
const configDir = (input && input.configDir) ? input.configDir : path.dirname(getReposDir());
|
|
127
190
|
updaterAPI.earlyLaunch(configDir);
|
|
128
191
|
|
|
129
192
|
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
@@ -132,19 +195,28 @@ const pluginUpdaterEntry = async function(input) {
|
|
|
132
195
|
const plugins = JSON.parse(fs.readFileSync(pluginsJsonPath, "utf-8"));
|
|
133
196
|
for (const plugin of plugins) {
|
|
134
197
|
if (plugin.url && plugin.enabled !== false && plugin.type !== "npm") {
|
|
135
|
-
|
|
136
|
-
|
|
198
|
+
const branch = plugin.branch || null;
|
|
199
|
+
const commit = plugin.commit || null;
|
|
200
|
+
updaterAPI.updatePlugin(plugin.name, plugin.url, branch, commit);
|
|
201
|
+
updaterAPI.deployToExecutionDir(plugin.name, pluginsDir);
|
|
137
202
|
}
|
|
138
203
|
}
|
|
139
204
|
} catch (e) {
|
|
140
|
-
|
|
205
|
+
writeLog(`Failed to parse plugins.json: ${e.message}`, true);
|
|
141
206
|
}
|
|
142
207
|
}
|
|
143
208
|
}
|
|
144
209
|
return {};
|
|
145
210
|
};
|
|
146
211
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
212
|
+
module.exports = {
|
|
213
|
+
activate: async function() { return await pluginUpdaterEntry(); },
|
|
214
|
+
earlyLaunch: updaterAPI.earlyLaunch,
|
|
215
|
+
updatePlugin: updaterAPI.updatePlugin,
|
|
216
|
+
deployToExecutionDir: updaterAPI.deployToExecutionDir,
|
|
217
|
+
rebuild: updaterAPI.rebuild,
|
|
218
|
+
downgrade: updaterAPI.downgrade,
|
|
219
|
+
disable: updaterAPI.disable,
|
|
220
|
+
uninstall: updaterAPI.uninstall,
|
|
221
|
+
default: pluginUpdaterEntry
|
|
222
|
+
};
|