plugin-updater 1.0.14 → 1.0.16
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 +116 -126
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -57,128 +57,77 @@ 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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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) {
|
|
129
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
130
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
182
131
|
|
|
183
132
|
// 1. GUARANTEE BASE DIRECTORIES EXIST ON LAUNCH
|
|
184
133
|
const reposDir = path.join(configDir, "repos");
|
|
@@ -189,7 +138,8 @@ const serverPlugin = async function(input) {
|
|
|
189
138
|
writeLog(`plugin-updater activated. configDir=${configDir}`);
|
|
190
139
|
|
|
191
140
|
if (!global.__PLUGIN_UPDATER_HANDLED_BY_HUB__) {
|
|
192
|
-
|
|
141
|
+
EARLY_LAUNCH_CONFIG_DIR = configDir;
|
|
142
|
+
global.__PLUGIN_UPDATER_HANDLED_BY_HUB__ = true;
|
|
193
143
|
|
|
194
144
|
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
195
145
|
if (fs.existsSync(pluginsJsonPath)) {
|
|
@@ -199,8 +149,8 @@ const serverPlugin = async function(input) {
|
|
|
199
149
|
if (plugin.url && plugin.enabled !== false && plugin.type !== "npm") {
|
|
200
150
|
const branch = plugin.branch || null;
|
|
201
151
|
const commit = plugin.commit || null;
|
|
202
|
-
|
|
203
|
-
|
|
152
|
+
updatePlugin(plugin.name, plugin.url, branch, commit);
|
|
153
|
+
deployToExecutionDir(plugin.name, pluginsDir);
|
|
204
154
|
}
|
|
205
155
|
}
|
|
206
156
|
} catch (e) {
|
|
@@ -209,18 +159,58 @@ const serverPlugin = async function(input) {
|
|
|
209
159
|
}
|
|
210
160
|
}
|
|
211
161
|
|
|
212
|
-
// Return hooks object
|
|
162
|
+
// Return empty hooks object — required by opencode plugin contract
|
|
213
163
|
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
|
-
});
|
|
164
|
+
}
|
|
220
165
|
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
166
|
+
// Attach API methods for hub access via: import('plugin-updater').then(m => m.default.earlyLaunch(...))
|
|
167
|
+
// These are function properties, NOT module-level named exports — they won't appear in Object.entries(mod)
|
|
168
|
+
pluginUpdaterEntry.earlyLaunch = function(configDir) {
|
|
169
|
+
EARLY_LAUNCH_CONFIG_DIR = configDir;
|
|
170
|
+
global.__PLUGIN_UPDATER_HANDLED_BY_HUB__ = true;
|
|
171
|
+
};
|
|
172
|
+
pluginUpdaterEntry.updatePlugin = updatePlugin;
|
|
173
|
+
pluginUpdaterEntry.deployToExecutionDir = deployToExecutionDir;
|
|
174
|
+
pluginUpdaterEntry.rebuild = function(pluginName) {
|
|
175
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
176
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
177
|
+
deployToExecutionDir(pluginName, path.join(configDir, "plugin"));
|
|
178
|
+
return "Rebuilt " + pluginName;
|
|
226
179
|
};
|
|
180
|
+
pluginUpdaterEntry.downgrade = function(pluginName, commitHash) {
|
|
181
|
+
const reposDir = getReposDir();
|
|
182
|
+
const targetDir = path.join(reposDir, pluginName);
|
|
183
|
+
if (fs.existsSync(targetDir)) {
|
|
184
|
+
executeGit(`git fetch origin`, targetDir);
|
|
185
|
+
executeGit(`git checkout ${commitHash}`, targetDir);
|
|
186
|
+
executeGit(`git submodule update --init --recursive`, targetDir);
|
|
187
|
+
return pluginUpdaterEntry.rebuild(pluginName);
|
|
188
|
+
}
|
|
189
|
+
return "Repo not found";
|
|
190
|
+
};
|
|
191
|
+
pluginUpdaterEntry.disable = function(plugin) {
|
|
192
|
+
const isClaude = process.argv.join(' ').includes('claude');
|
|
193
|
+
const configDir = getAppConfigDir(isClaude ? "claude" : "opencode");
|
|
194
|
+
const pluginsJsonPath = path.join(configDir, "config", "plugins.json");
|
|
195
|
+
if (fs.existsSync(pluginsJsonPath)) {
|
|
196
|
+
let plugins = JSON.parse(fs.readFileSync(pluginsJsonPath, "utf-8"));
|
|
197
|
+
const pluginIndex = plugins.findIndex(p => p.name === plugin.name);
|
|
198
|
+
if (pluginIndex >= 0) {
|
|
199
|
+
plugins[pluginIndex].enabled = false;
|
|
200
|
+
fs.writeFileSync(pluginsJsonPath, JSON.stringify(plugins, null, 2), "utf-8");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const pluginExecutionPath = path.join(configDir, "plugin", plugin.name);
|
|
204
|
+
if (fs.existsSync(pluginExecutionPath)) {
|
|
205
|
+
try { fs.rmSync(pluginExecutionPath, { recursive: true, force: true }); } catch (e) {}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
pluginUpdaterEntry.uninstall = function(plugin) {
|
|
209
|
+
pluginUpdaterEntry.disable(plugin);
|
|
210
|
+
const targetDir = path.join(getReposDir(), plugin.name);
|
|
211
|
+
if (fs.existsSync(targetDir)) {
|
|
212
|
+
try { fs.rmSync(targetDir, { recursive: true, force: true }); } catch (e) {}
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export default pluginUpdaterEntry;
|