plugin-updater 1.0.25 → 1.0.27
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/dist/index.d.ts +3 -3
- package/dist/index.js +75 -19
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare function getNpmPlugins(configDir: string): NpmPlugin[];
|
|
|
16
16
|
export declare function installNpmPlugin(name: string, configDir: string): string;
|
|
17
17
|
export declare function uninstallNpmPlugin(name: string, configDir: string): string;
|
|
18
18
|
export declare function updateNpmPlugin(name: string, configDir: string, updateInterval?: number): string;
|
|
19
|
-
export declare function updatePluginPublic(pluginName: string, gitUrl: string, branch?: string, commitHash?: string): Promise<void>;
|
|
20
|
-
export declare function earlyLaunch(configDir: string, plugins: Plugin[]): Promise<void>;
|
|
21
|
-
export declare function activate(): Promise<void>;
|
|
19
|
+
export declare function updatePluginPublic(pluginName: string, gitUrl: string, branch?: string, commitHash?: string): Promise<void | object>;
|
|
20
|
+
export declare function earlyLaunch(configDir: string, plugins: Plugin[]): Promise<void | object>;
|
|
21
|
+
export declare function activate(opencodeHookInput?: unknown): Promise<void | object>;
|
|
22
22
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,7 @@ function writeLog(message, isError = false) {
|
|
|
53
53
|
else if (loggingEnabled)
|
|
54
54
|
console.log(message);
|
|
55
55
|
}
|
|
56
|
+
let NPM_GLOBAL_ROOT = null;
|
|
56
57
|
function getReposDir() {
|
|
57
58
|
const isClaude = process.argv.join(" ").includes("claude");
|
|
58
59
|
const appName = isClaude ? "claude" : "opencode";
|
|
@@ -75,17 +76,26 @@ function executeGit(command, cwd) {
|
|
|
75
76
|
return false;
|
|
76
77
|
}
|
|
77
78
|
}
|
|
79
|
+
function getNpmGlobalRoot() {
|
|
80
|
+
if (NPM_GLOBAL_ROOT !== null)
|
|
81
|
+
return NPM_GLOBAL_ROOT;
|
|
82
|
+
try {
|
|
83
|
+
NPM_GLOBAL_ROOT = execSync("npm root -g", { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
NPM_GLOBAL_ROOT = "";
|
|
87
|
+
}
|
|
88
|
+
return NPM_GLOBAL_ROOT;
|
|
89
|
+
}
|
|
78
90
|
function resolveNpmPluginVersion(name, configDir) {
|
|
79
91
|
try {
|
|
80
92
|
const cacheDir = path.join(configDir, "cache", "node_modules");
|
|
81
|
-
const globalNpm =
|
|
82
|
-
? path.join(os.homedir(), "AppData", "Roaming", "npm", "node_modules")
|
|
83
|
-
: path.join("/usr", "lib", "node_modules");
|
|
93
|
+
const globalNpm = getNpmGlobalRoot();
|
|
84
94
|
const candidates = [
|
|
85
95
|
path.join(cacheDir, name, "package.json"),
|
|
86
96
|
path.join(configDir, "node_modules", name, "package.json"),
|
|
87
|
-
path.join(globalNpm, name, "package.json"),
|
|
88
|
-
];
|
|
97
|
+
globalNpm ? path.join(globalNpm, name, "package.json") : "",
|
|
98
|
+
].filter((p) => p !== "");
|
|
89
99
|
for (const p of candidates) {
|
|
90
100
|
if (fs.existsSync(p)) {
|
|
91
101
|
return JSON.parse(fs.readFileSync(p, "utf8")).version || "";
|
|
@@ -120,7 +130,15 @@ function writeOpencodeJson(configDir, data) {
|
|
|
120
130
|
fs.writeFileSync(ocPath, JSON.stringify(data, null, 2), "utf8");
|
|
121
131
|
}
|
|
122
132
|
// ── Public API ────────────────────────────────────────────────────────────────
|
|
133
|
+
// opencode invokes every exported function as a plugin hook, passing a context
|
|
134
|
+
// object instead of our protocol arguments; exports detect that and return an
|
|
135
|
+
// inert value so opencode gets a valid (empty) plugin instance
|
|
136
|
+
function isOpencodeHookInvocation(firstArgument) {
|
|
137
|
+
return typeof firstArgument !== "string";
|
|
138
|
+
}
|
|
123
139
|
export function getNpmPlugins(configDir) {
|
|
140
|
+
if (isOpencodeHookInvocation(configDir))
|
|
141
|
+
return [];
|
|
124
142
|
const { plugins } = readOpencodeJson(configDir);
|
|
125
143
|
return plugins.map((raw) => {
|
|
126
144
|
const name = raw.replace(/@[^@/]+$/, "") || raw;
|
|
@@ -129,6 +147,8 @@ export function getNpmPlugins(configDir) {
|
|
|
129
147
|
});
|
|
130
148
|
}
|
|
131
149
|
export function installNpmPlugin(name, configDir) {
|
|
150
|
+
if (isOpencodeHookInvocation(name))
|
|
151
|
+
return "";
|
|
132
152
|
writeLog(`Installing npm plugin: ${name}`);
|
|
133
153
|
try {
|
|
134
154
|
const { plugins, raw } = readOpencodeJson(configDir);
|
|
@@ -147,6 +167,8 @@ export function installNpmPlugin(name, configDir) {
|
|
|
147
167
|
}
|
|
148
168
|
}
|
|
149
169
|
export function uninstallNpmPlugin(name, configDir) {
|
|
170
|
+
if (isOpencodeHookInvocation(name))
|
|
171
|
+
return "";
|
|
150
172
|
writeLog(`Uninstalling npm plugin: ${name}`);
|
|
151
173
|
try {
|
|
152
174
|
const { plugins, raw } = readOpencodeJson(configDir);
|
|
@@ -166,6 +188,8 @@ export function uninstallNpmPlugin(name, configDir) {
|
|
|
166
188
|
}
|
|
167
189
|
}
|
|
168
190
|
export function updateNpmPlugin(name, configDir, updateInterval = 1) {
|
|
191
|
+
if (isOpencodeHookInvocation(name))
|
|
192
|
+
return "";
|
|
169
193
|
writeLog(`Updating npm plugin: ${name}`);
|
|
170
194
|
const checkFile = path.join(configDir, "cache", `.npm-lastcheck-${name.replace(/[^a-z0-9]/gi, "_")}`);
|
|
171
195
|
try {
|
|
@@ -262,6 +286,42 @@ async function callPluginCleanup(pluginExecutionFile, configDir) {
|
|
|
262
286
|
writeLog(`cleanup() call failed for ${pluginExecutionFile}: ${e.message}`, true);
|
|
263
287
|
}
|
|
264
288
|
}
|
|
289
|
+
const BUILD_OUTPUT_DIRS = ["dist", path.join("core", "dist")];
|
|
290
|
+
// npm install creates node_modules/.bin symlinks, which fail on filesystems
|
|
291
|
+
// without symlink support (e.g. Windows-backed Docker bind mounts) — build in
|
|
292
|
+
// the OS temp dir and copy the outputs back instead
|
|
293
|
+
function buildInTempDir(pluginName, sourceDir) {
|
|
294
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), `plugin-updater-${pluginName}-`));
|
|
295
|
+
try {
|
|
296
|
+
fs.cpSync(sourceDir, tempDir, {
|
|
297
|
+
recursive: true,
|
|
298
|
+
filter: (src) => {
|
|
299
|
+
const name = path.basename(src);
|
|
300
|
+
return name !== ".git" && name !== "node_modules";
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
writeLog(`Running npm install for ${pluginName}`);
|
|
304
|
+
execSync("npm install", { cwd: tempDir, stdio: "pipe" });
|
|
305
|
+
writeLog(`Finished npm install for ${pluginName}`);
|
|
306
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(tempDir, "package.json"), "utf8"));
|
|
307
|
+
if (pkg.scripts?.build) {
|
|
308
|
+
execSync("npm run build", { cwd: tempDir, stdio: "pipe" });
|
|
309
|
+
writeLog(`Finished npm run build for ${pluginName}`);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
writeLog(`Skipped npm run build for ${pluginName} (no build script found)`);
|
|
313
|
+
}
|
|
314
|
+
for (const outputDir of BUILD_OUTPUT_DIRS) {
|
|
315
|
+
const builtDir = path.join(tempDir, outputDir);
|
|
316
|
+
if (fs.existsSync(builtDir)) {
|
|
317
|
+
fs.cpSync(builtDir, path.join(sourceDir, outputDir), { recursive: true });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
265
325
|
async function deployToExecutionDir(pluginName, executionPath, changed, configDir) {
|
|
266
326
|
const sourceDir = path.join(getReposDir(), pluginName);
|
|
267
327
|
if (!fs.existsSync(sourceDir))
|
|
@@ -275,19 +335,7 @@ async function deployToExecutionDir(pluginName, executionPath, changed, configDi
|
|
|
275
335
|
else {
|
|
276
336
|
if (fs.existsSync(packageJsonPath)) {
|
|
277
337
|
try {
|
|
278
|
-
|
|
279
|
-
execSync("npm install", { cwd: sourceDir, stdio: "pipe" });
|
|
280
|
-
writeLog(`Finished npm install for ${pluginName}`);
|
|
281
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
282
|
-
if (pkg.main)
|
|
283
|
-
entryFile = pkg.main;
|
|
284
|
-
if (pkg.scripts?.build) {
|
|
285
|
-
execSync("npm run build", { cwd: sourceDir, stdio: "pipe" });
|
|
286
|
-
writeLog(`Finished npm run build for ${pluginName}`);
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
writeLog(`Skipped npm run build for ${pluginName} (no build script found)`);
|
|
290
|
-
}
|
|
338
|
+
buildInTempDir(pluginName, sourceDir);
|
|
291
339
|
}
|
|
292
340
|
catch (error) {
|
|
293
341
|
const err = error;
|
|
@@ -345,6 +393,8 @@ async function pluginUpdaterEntry(input) {
|
|
|
345
393
|
}
|
|
346
394
|
}
|
|
347
395
|
export async function updatePluginPublic(pluginName, gitUrl, branch, commitHash) {
|
|
396
|
+
if (isOpencodeHookInvocation(pluginName))
|
|
397
|
+
return {};
|
|
348
398
|
writeLog(`Public API update call for ${pluginName}`);
|
|
349
399
|
const appName = process.argv.join(" ").includes("claude") ? "claude" : "opencode";
|
|
350
400
|
const configDir = getAppConfigDir(appName);
|
|
@@ -352,6 +402,8 @@ export async function updatePluginPublic(pluginName, gitUrl, branch, commitHash)
|
|
|
352
402
|
await deployToExecutionDir(pluginName, path.join(configDir, "plugin"), result.changed, configDir);
|
|
353
403
|
}
|
|
354
404
|
export async function earlyLaunch(configDir, plugins) {
|
|
405
|
+
if (isOpencodeHookInvocation(configDir))
|
|
406
|
+
return {};
|
|
355
407
|
EARLY_LAUNCH_CONFIG_DIR = configDir;
|
|
356
408
|
writeLog("Starting earlyLaunch updater sequence");
|
|
357
409
|
// Self-update first
|
|
@@ -393,7 +445,11 @@ export async function earlyLaunch(configDir, plugins) {
|
|
|
393
445
|
}
|
|
394
446
|
}
|
|
395
447
|
}
|
|
396
|
-
export async function activate() {
|
|
448
|
+
export async function activate(opencodeHookInput) {
|
|
449
|
+
// module load below calls activate() with no argument; opencode passes a
|
|
450
|
+
// context object when re-invoking the export — return an inert plugin instance
|
|
451
|
+
if (opencodeHookInput !== undefined)
|
|
452
|
+
return {};
|
|
397
453
|
const isClaude = process.argv.join(" ").includes("claude");
|
|
398
454
|
const appName = isClaude ? "claude" : "opencode";
|
|
399
455
|
const configDir = getAppConfigDir(appName);
|