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