plugin-updater 1.0.14 → 1.0.15
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/index.js +114 -123
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -57,125 +57,75 @@ function executeGit(command, cwd) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
executeGit(`git
|
|
60
|
+
function updatePlugin(pluginName, gitUrl, branch, commitHash) {
|
|
61
|
+
const reposDir = getReposDir();
|
|
62
|
+
const targetDir = path.join(reposDir, pluginName);
|
|
63
|
+
|
|
64
|
+
if (!fs.existsSync(targetDir)) {
|
|
65
|
+
if (!fs.existsSync(reposDir)) fs.mkdirSync(reposDir, { recursive: true });
|
|
66
|
+
const branchFlag = branch ? `--branch ${branch}` : "";
|
|
67
|
+
executeGit(`git clone --recurse-submodules ${branchFlag} ${gitUrl} ${pluginName}`, reposDir);
|
|
68
|
+
} else {
|
|
69
|
+
executeGit("git fetch origin", targetDir);
|
|
70
|
+
if (commitHash) {
|
|
71
|
+
executeGit(`git checkout ${commitHash}`, targetDir);
|
|
72
|
+
} else if (branch) {
|
|
73
|
+
executeGit(`git checkout ${branch}`, targetDir);
|
|
74
|
+
executeGit(`git pull --ff-only origin ${branch}`, targetDir);
|
|
74
75
|
} else {
|
|
75
|
-
executeGit("git
|
|
76
|
-
|
|
77
|
-
executeGit(`git checkout ${commitHash}`, targetDir);
|
|
78
|
-
} else if (branch) {
|
|
79
|
-
executeGit(`git checkout ${branch}`, targetDir);
|
|
80
|
-
executeGit(`git pull --ff-only origin ${branch}`, targetDir);
|
|
81
|
-
} else {
|
|
82
|
-
executeGit("git checkout main || git checkout master", targetDir);
|
|
83
|
-
executeGit("git pull --ff-only", targetDir);
|
|
84
|
-
}
|
|
85
|
-
executeGit("git submodule update --init --recursive", targetDir);
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
deployToExecutionDir: function(pluginName, executionPath) {
|
|
91
|
-
const sourceDir = path.join(getReposDir(), pluginName);
|
|
92
|
-
if (!fs.existsSync(sourceDir)) return false;
|
|
93
|
-
|
|
94
|
-
const packageJsonPath = path.join(sourceDir, "package.json");
|
|
95
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
96
|
-
try {
|
|
97
|
-
writeLog(`Running npm install for ${pluginName}`);
|
|
98
|
-
execSync("npm install", { cwd: sourceDir, stdio: "ignore" });
|
|
99
|
-
writeLog(`Finished npm install for ${pluginName}`);
|
|
100
|
-
|
|
101
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
102
|
-
if (pkg.scripts && pkg.scripts.build) {
|
|
103
|
-
execSync("npm run build", { cwd: sourceDir, stdio: "ignore" });
|
|
104
|
-
writeLog(`Finished npm run build for ${pluginName}`);
|
|
105
|
-
} else {
|
|
106
|
-
writeLog(`Skipped npm run build for ${pluginName} (no build script found)`);
|
|
107
|
-
}
|
|
108
|
-
} catch (error) {
|
|
109
|
-
writeLog(`Build/Install failed for ${pluginName}: ${error.message}`, true);
|
|
110
|
-
}
|
|
76
|
+
executeGit("git checkout main || git checkout master", targetDir);
|
|
77
|
+
executeGit("git pull --ff-only", targetDir);
|
|
111
78
|
}
|
|
79
|
+
executeGit("git submodule update --init --recursive", targetDir);
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
112
83
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!fs.existsSync(pluginExecutionPath)) {
|
|
118
|
-
fs.mkdirSync(pluginExecutionPath, { recursive: true });
|
|
119
|
-
}
|
|
84
|
+
function deployToExecutionDir(pluginName, executionPath) {
|
|
85
|
+
const sourceDir = path.join(getReposDir(), pluginName);
|
|
86
|
+
if (!fs.existsSync(sourceDir)) return false;
|
|
120
87
|
|
|
88
|
+
const packageJsonPath = path.join(sourceDir, "package.json");
|
|
89
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
121
90
|
try {
|
|
122
|
-
writeLog(`Running
|
|
123
|
-
|
|
124
|
-
writeLog(`Finished
|
|
125
|
-
|
|
126
|
-
|
|
91
|
+
writeLog(`Running npm install for ${pluginName}`);
|
|
92
|
+
execSync("npm install", { cwd: sourceDir, stdio: "ignore" });
|
|
93
|
+
writeLog(`Finished npm install for ${pluginName}`);
|
|
94
|
+
|
|
95
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
96
|
+
if (pkg.scripts && pkg.scripts.build) {
|
|
97
|
+
execSync("npm run build", { cwd: sourceDir, stdio: "ignore" });
|
|
98
|
+
writeLog(`Finished npm run build for ${pluginName}`);
|
|
99
|
+
} else {
|
|
100
|
+
writeLog(`Skipped npm run build for ${pluginName} (no build script found)`);
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
writeLog(`Build/Install failed for ${pluginName}: ${error.message}`, true);
|
|
127
104
|
}
|
|
128
|
-
|
|
129
|
-
},
|
|
105
|
+
}
|
|
130
106
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
this.deployToExecutionDir(pluginName, path.join(configDir, "plugin"));
|
|
135
|
-
return "Rebuilt " + pluginName;
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
downgrade: function(pluginName, commitHash) {
|
|
139
|
-
const reposDir = getReposDir();
|
|
140
|
-
const targetDir = path.join(reposDir, pluginName);
|
|
141
|
-
if (fs.existsSync(targetDir)) {
|
|
142
|
-
executeGit(`git fetch origin`, targetDir);
|
|
143
|
-
executeGit(`git checkout ${commitHash}`, targetDir);
|
|
144
|
-
executeGit(`git submodule update --init --recursive`, targetDir);
|
|
145
|
-
return this.rebuild(pluginName);
|
|
146
|
-
}
|
|
147
|
-
return "Repo not found";
|
|
148
|
-
},
|
|
107
|
+
const distPath = path.join(sourceDir, "dist");
|
|
108
|
+
const deploySource = fs.existsSync(distPath) ? distPath : sourceDir;
|
|
109
|
+
const pluginExecutionPath = path.join(executionPath, pluginName);
|
|
149
110
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
154
|
-
if (fs.existsSync(pluginsJsonPath)) {
|
|
155
|
-
let plugins = JSON.parse(fs.readFileSync(pluginsJsonPath, "utf-8"));
|
|
156
|
-
const pluginIndex = plugins.findIndex(p => p.name === plugin.name);
|
|
157
|
-
if (pluginIndex >= 0) {
|
|
158
|
-
plugins[pluginIndex].enabled = false;
|
|
159
|
-
fs.writeFileSync(pluginsJsonPath, JSON.stringify(plugins, null, 2), "utf-8");
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
const pluginExecutionPath = path.join(configDir, "plugin", plugin.name);
|
|
163
|
-
if (fs.existsSync(pluginExecutionPath)) {
|
|
164
|
-
try { fs.rmSync(pluginExecutionPath, { recursive: true, force: true }); } catch (e) {}
|
|
165
|
-
}
|
|
166
|
-
},
|
|
111
|
+
if (!fs.existsSync(pluginExecutionPath)) {
|
|
112
|
+
fs.mkdirSync(pluginExecutionPath, { recursive: true });
|
|
113
|
+
}
|
|
167
114
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
115
|
+
try {
|
|
116
|
+
writeLog(`Running cpSync for ${pluginName}`);
|
|
117
|
+
fs.cpSync(deploySource, pluginExecutionPath, { recursive: true, force: true });
|
|
118
|
+
writeLog(`Finished cpSync for ${pluginName}`);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
writeLog(`cpSync failed for ${pluginName}: ${e.message}`, true);
|
|
174
121
|
}
|
|
175
|
-
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
176
124
|
|
|
177
|
-
// OpenCode plugin
|
|
178
|
-
|
|
125
|
+
// OpenCode NPM plugin contract: export default must be a function.
|
|
126
|
+
// opencode iterates Object.entries(mod) and calls each export as fn(input).
|
|
127
|
+
// ONLY export a single default function — no named exports.
|
|
128
|
+
async function pluginUpdaterEntry(input) {
|
|
179
129
|
const configDir = (input && input.directory)
|
|
180
130
|
? path.dirname(input.directory)
|
|
181
131
|
: path.dirname(getReposDir());
|
|
@@ -189,7 +139,8 @@ const serverPlugin = async function(input) {
|
|
|
189
139
|
writeLog(`plugin-updater activated. configDir=${configDir}`);
|
|
190
140
|
|
|
191
141
|
if (!global.__PLUGIN_UPDATER_HANDLED_BY_HUB__) {
|
|
192
|
-
|
|
142
|
+
EARLY_LAUNCH_CONFIG_DIR = configDir;
|
|
143
|
+
global.__PLUGIN_UPDATER_HANDLED_BY_HUB__ = true;
|
|
193
144
|
|
|
194
145
|
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
195
146
|
if (fs.existsSync(pluginsJsonPath)) {
|
|
@@ -199,8 +150,8 @@ const serverPlugin = async function(input) {
|
|
|
199
150
|
if (plugin.url && plugin.enabled !== false && plugin.type !== "npm") {
|
|
200
151
|
const branch = plugin.branch || null;
|
|
201
152
|
const commit = plugin.commit || null;
|
|
202
|
-
|
|
203
|
-
|
|
153
|
+
updatePlugin(plugin.name, plugin.url, branch, commit);
|
|
154
|
+
deployToExecutionDir(plugin.name, pluginsDir);
|
|
204
155
|
}
|
|
205
156
|
}
|
|
206
157
|
} catch (e) {
|
|
@@ -209,18 +160,58 @@ const serverPlugin = async function(input) {
|
|
|
209
160
|
}
|
|
210
161
|
}
|
|
211
162
|
|
|
212
|
-
// Return hooks object
|
|
163
|
+
// Return empty hooks object — required by opencode plugin contract
|
|
213
164
|
return {};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Expose updaterAPI on serverPlugin for hub access: import('plugin-updater').then(m => m.default.server.earlyLaunch(...))
|
|
217
|
-
Object.keys(updaterAPI).forEach(key => {
|
|
218
|
-
serverPlugin[key] = updaterAPI[key];
|
|
219
|
-
});
|
|
165
|
+
}
|
|
220
166
|
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
167
|
+
// Attach API methods for hub access via: import('plugin-updater').then(m => m.default.earlyLaunch(...))
|
|
168
|
+
// These are function properties, NOT module-level named exports — they won't appear in Object.entries(mod)
|
|
169
|
+
pluginUpdaterEntry.earlyLaunch = function(configDir) {
|
|
170
|
+
EARLY_LAUNCH_CONFIG_DIR = configDir;
|
|
171
|
+
global.__PLUGIN_UPDATER_HANDLED_BY_HUB__ = true;
|
|
172
|
+
};
|
|
173
|
+
pluginUpdaterEntry.updatePlugin = updatePlugin;
|
|
174
|
+
pluginUpdaterEntry.deployToExecutionDir = deployToExecutionDir;
|
|
175
|
+
pluginUpdaterEntry.rebuild = function(pluginName) {
|
|
176
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
177
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
178
|
+
deployToExecutionDir(pluginName, path.join(configDir, "plugin"));
|
|
179
|
+
return "Rebuilt " + pluginName;
|
|
226
180
|
};
|
|
181
|
+
pluginUpdaterEntry.downgrade = function(pluginName, commitHash) {
|
|
182
|
+
const reposDir = getReposDir();
|
|
183
|
+
const targetDir = path.join(reposDir, pluginName);
|
|
184
|
+
if (fs.existsSync(targetDir)) {
|
|
185
|
+
executeGit(`git fetch origin`, targetDir);
|
|
186
|
+
executeGit(`git checkout ${commitHash}`, targetDir);
|
|
187
|
+
executeGit(`git submodule update --init --recursive`, targetDir);
|
|
188
|
+
return pluginUpdaterEntry.rebuild(pluginName);
|
|
189
|
+
}
|
|
190
|
+
return "Repo not found";
|
|
191
|
+
};
|
|
192
|
+
pluginUpdaterEntry.disable = function(plugin) {
|
|
193
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
194
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
195
|
+
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
196
|
+
if (fs.existsSync(pluginsJsonPath)) {
|
|
197
|
+
let plugins = JSON.parse(fs.readFileSync(pluginsJsonPath, "utf-8"));
|
|
198
|
+
const pluginIndex = plugins.findIndex(p => p.name === plugin.name);
|
|
199
|
+
if (pluginIndex >= 0) {
|
|
200
|
+
plugins[pluginIndex].enabled = false;
|
|
201
|
+
fs.writeFileSync(pluginsJsonPath, JSON.stringify(plugins, null, 2), "utf-8");
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const pluginExecutionPath = path.join(configDir, "plugin", plugin.name);
|
|
205
|
+
if (fs.existsSync(pluginExecutionPath)) {
|
|
206
|
+
try { fs.rmSync(pluginExecutionPath, { recursive: true, force: true }); } catch (e) {}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
pluginUpdaterEntry.uninstall = function(plugin) {
|
|
210
|
+
pluginUpdaterEntry.disable(plugin);
|
|
211
|
+
const targetDir = path.join(getReposDir(), plugin.name);
|
|
212
|
+
if (fs.existsSync(targetDir)) {
|
|
213
|
+
try { fs.rmSync(targetDir, { recursive: true, force: true }); } catch (e) {}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export default pluginUpdaterEntry;
|