@coffer-org/server 1.4.0 → 1.5.0

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.js CHANGED
@@ -28,7 +28,7 @@ import { initPlugins, teardownPlugins, readDisabled, purgePluginData, getPluginS
28
28
  import { registerPluginsApi } from "./plugins-api.js";
29
29
  import { registerAuthApi, resolveRequestUser, requireAdmin, PUBLIC_API_PATHS } from "./auth-api.js";
30
30
  import { discoverPluginAssets } from "./plugin-discovery.js";
31
- import { checkLatestVersion, resolveUpdateTarget, runNpmInstall } from "./plugin-updates.js";
31
+ import { checkLatestVersion, resolveUpdateTarget, resolveAllUpdateTargets, runNpmInstall } from "./plugin-updates.js";
32
32
  import { buildClientSchema } from "./schema-api.js";
33
33
  import { recordList, recordGet, recordCreate, recordUpdate, recordDelete, rowMatch, UnknownTypeError } from "./records-api.js";
34
34
  import { maskTree, preserveTree } from "./secrets.js";
@@ -234,13 +234,28 @@ app.post('/api/plugins/:id/update', async (req, reply) => {
234
234
  if (!target.ok) {
235
235
  return reply.code(target.error === 'unknown_plugin' ? 404 : 400).send({ error: target.error });
236
236
  }
237
- const result = await runNpmInstall(target.packageName, target.version, process.cwd());
237
+ const result = await runNpmInstall([`${target.packageName}@${target.version}`], process.cwd());
238
238
  if (!result.ok) {
239
239
  return reply.code(500).send({ error: 'install_failed', stderr: result.stderr });
240
240
  }
241
241
  reply.send({ ok: true });
242
242
  setTimeout(() => process.exit(0), 500);
243
243
  });
244
+ app.post('/api/plugins/update-all', async (req, reply) => {
245
+ if (!requireAdmin(req, reply))
246
+ return;
247
+ const assets = await discoverPluginAssets();
248
+ const latestById = new Map(await Promise.all(assets.map(async (a) => [a.id, await checkLatestVersion(a.packageName)])));
249
+ const targets = resolveAllUpdateTargets(assets, latestById);
250
+ if (targets.length === 0)
251
+ return reply.code(400).send({ error: 'no_update_available' });
252
+ const result = await runNpmInstall(targets.map((t) => `${t.packageName}@${t.to}`), process.cwd());
253
+ if (!result.ok) {
254
+ return reply.code(500).send({ error: 'install_failed', stderr: result.stderr });
255
+ }
256
+ reply.send({ ok: true, updated: targets.map(({ id, from, to }) => ({ id, from, to })) });
257
+ setTimeout(() => process.exit(0), 500);
258
+ });
244
259
  app.get('/api/plugins/:id/settings', async (req, reply) => {
245
260
  if (!requireAdmin(req, reply))
246
261
  return;
@@ -9,7 +9,14 @@ export type UpdateTarget = {
9
9
  error: 'unknown_plugin' | 'no_update_available';
10
10
  };
11
11
  export declare function resolveUpdateTarget(assets: PluginAssetRecord[], id: string, latestVersion: string | null): UpdateTarget;
12
- export declare function runNpmInstall(packageName: string, version: string, cwd: string): Promise<{
12
+ export interface AllUpdateTarget {
13
+ id: string;
14
+ packageName: string;
15
+ from: string;
16
+ to: string;
17
+ }
18
+ export declare function resolveAllUpdateTargets(assets: PluginAssetRecord[], latestById: Map<string, string | null>): AllUpdateTarget[];
19
+ export declare function runNpmInstall(specs: string[], cwd: string): Promise<{
13
20
  ok: boolean;
14
21
  stderr: string;
15
22
  }>;
@@ -41,9 +41,17 @@ export function resolveUpdateTarget(assets, id, latestVersion) {
41
41
  return { ok: false, error: 'no_update_available' };
42
42
  return { ok: true, packageName: rec.packageName, version: latestVersion };
43
43
  }
44
- export function runNpmInstall(packageName, version, cwd) {
44
+ export function resolveAllUpdateTargets(assets, latestById) {
45
+ return assets.flatMap((rec) => {
46
+ const latest = latestById.get(rec.id) ?? null;
47
+ if (!latest || latest === rec.version)
48
+ return [];
49
+ return [{ id: rec.id, packageName: rec.packageName, from: rec.version, to: latest }];
50
+ });
51
+ }
52
+ export function runNpmInstall(specs, cwd) {
45
53
  return new Promise((resolve) => {
46
- execFile('npm', ['install', `${packageName}@${version}`], { cwd, timeout: 120_000, encoding: 'utf8' }, (err, _stdout, stderr) => {
54
+ execFile('npm', ['install', ...specs], { cwd, timeout: 120_000 + 30_000 * specs.length, encoding: 'utf8' }, (err, _stdout, stderr) => {
47
55
  if (err)
48
56
  return resolve({ ok: false, stderr: (stderr || err.message || '').trim() });
49
57
  resolve({ ok: true, stderr: '' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffer-org/server",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"