mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
refactor(plugins): route injectable-class SQL through the injected DatabaseService
PluginRuntimeService's operatorEgressHosts/pruneErrorLog and PluginsService's egressHostCount were module-level helpers on the raw db proxy; they fold into their classes as methods over the injected service. (PluginHostDepsFactory's equivalent conversion rode the settings commit — same files.) No injectable class under src/nest imports the db global anymore; the remaining importers are the documented module-level seams (bridges, platform shell, plugin-host-state, signature-status, the bare plugin user-setting readers).
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { Injectable, type OnModuleInit, type OnModuleDestroy } from '@nestjs/common';
|
||||
import semver from 'semver';
|
||||
import { db } from '../../db/database';
|
||||
import { DatabaseService } from '../database/database.service';
|
||||
import { pluginsEnabled } from './kill-switch';
|
||||
import { setPluginEventSink } from '../../plugin-event-sink';
|
||||
@@ -40,15 +39,6 @@ const HTTP_OUTBOUND = 'http:outbound:';
|
||||
// any embedded space — the string is interpolated into the egress guard and the CSP.
|
||||
const EGRESS_HOST_RE = /^(\*\.[a-z0-9-]+(\.[a-z0-9-]+)+|[a-z0-9-]+(\.[a-z0-9-]+)*)$/i;
|
||||
|
||||
/** Hosts an admin added post-install for a plugin that declared `operatorEgress`. */
|
||||
function operatorEgressHosts(id: string): string[] {
|
||||
try {
|
||||
return (db.prepare('SELECT host FROM plugin_egress_hosts WHERE plugin_id = ? ORDER BY host').all(id) as Array<{ host: string }>)
|
||||
.map((r) => r.host);
|
||||
} catch {
|
||||
return []; // table absent (a slimmed test app) — never block activation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove `<plugins>/<id>` whether it is a real directory, a POSIX symlink or a
|
||||
@@ -155,7 +145,7 @@ export class PluginRuntimeService implements OnModuleInit, OnModuleDestroy {
|
||||
// Retention: a crash-looping plugin emits a stderr line per restart, so an
|
||||
// uncapped table grows without bound in the shared trek.db. Keep only the
|
||||
// most recent LOG_RETENTION rows per plugin (the admin view shows 200).
|
||||
pruneErrorLog(id);
|
||||
this.pruneErrorLog(id);
|
||||
} catch { /* DB unavailable — a log line must never crash the host */ }
|
||||
},
|
||||
});
|
||||
@@ -555,13 +545,18 @@ export class PluginRuntimeService implements OnModuleInit, OnModuleDestroy {
|
||||
// still bounds what is possible — and it is always the admin, never an end user,
|
||||
// who widens it. The egress list is spawn-time only, which is why changing it
|
||||
// re-spawns the plugin (see setOperatorEgressHosts).
|
||||
const egress = [...new Set([...manifestHosts, ...operatorEgressHosts(id)])];
|
||||
const egress = [...new Set([...manifestHosts, ...this.operatorEgressHosts(id)])];
|
||||
await this.supervisor.activate(id, new Set(declared), config, egress);
|
||||
}
|
||||
|
||||
/** Hosts an admin added for this plugin (empty unless it declared `operatorEgress`). */
|
||||
operatorEgressHosts(id: string): string[] {
|
||||
return operatorEgressHosts(id);
|
||||
try {
|
||||
return (this.db.prepare('SELECT host FROM plugin_egress_hosts WHERE plugin_id = ? ORDER BY host').all(id) as Array<{ host: string }>)
|
||||
.map((r) => r.host);
|
||||
} catch {
|
||||
return []; // table absent (a slimmed test app) — never block activation
|
||||
}
|
||||
}
|
||||
|
||||
/** Does this plugin's manifest declare that it needs operator-supplied hosts? */
|
||||
@@ -1123,6 +1118,16 @@ export class PluginRuntimeService implements OnModuleInit, OnModuleDestroy {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** Trim a plugin's error log to the most recent LOG_RETENTION rows. Cheap: onLog
|
||||
* only fires on warn/error, so this never runs on the hot path. */
|
||||
private pruneErrorLog(pluginId: string): void {
|
||||
this.db.prepare(
|
||||
`DELETE FROM plugin_error_log WHERE plugin_id = ? AND id NOT IN (
|
||||
SELECT id FROM plugin_error_log WHERE plugin_id = ? ORDER BY id DESC LIMIT ${LOG_RETENTION}
|
||||
)`,
|
||||
).run(pluginId, pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
function parseArray(json: string): string[] {
|
||||
@@ -1151,12 +1156,3 @@ function decryptConfig(config: Record<string, unknown>): Record<string, unknown>
|
||||
}
|
||||
|
||||
const LOG_RETENTION = 500; // rows kept per plugin (the admin view shows the newest 200)
|
||||
/** Trim a plugin's error log to the most recent LOG_RETENTION rows. Cheap: onLog
|
||||
* only fires on warn/error, so this never runs on the hot path. */
|
||||
function pruneErrorLog(pluginId: string): void {
|
||||
db.prepare(
|
||||
`DELETE FROM plugin_error_log WHERE plugin_id = ? AND id NOT IN (
|
||||
SELECT id FROM plugin_error_log WHERE plugin_id = ? ORDER BY id DESC LIMIT ${LOG_RETENTION}
|
||||
)`,
|
||||
).run(pluginId, pluginId);
|
||||
}
|
||||
|
||||
@@ -45,15 +45,6 @@ interface PluginRawRow {
|
||||
update_block_version: string | null;
|
||||
}
|
||||
|
||||
/** Hosts an admin has added for a plugin (0 unless it declared operatorEgress). */
|
||||
function egressHostCount(id: string): number {
|
||||
try {
|
||||
return (db.prepare('SELECT COUNT(*) AS n FROM plugin_egress_hosts WHERE plugin_id = ?').get(id) as { n: number }).n;
|
||||
} catch {
|
||||
return 0; // table absent (a slimmed test app)
|
||||
}
|
||||
}
|
||||
|
||||
export interface PluginListItem {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -106,6 +97,15 @@ export class PluginsService {
|
||||
return this.dbs.connection;
|
||||
}
|
||||
|
||||
/** Hosts an admin has added for a plugin (0 unless it declared operatorEgress). */
|
||||
private egressHostCount(id: string): number {
|
||||
try {
|
||||
return (this.db.prepare('SELECT COUNT(*) AS n FROM plugin_egress_hosts WHERE plugin_id = ?').get(id) as { n: number }).n;
|
||||
} catch {
|
||||
return 0; // table absent (a slimmed test app)
|
||||
}
|
||||
}
|
||||
|
||||
list(): { enabled: boolean; devLink: boolean; plugins: PluginListItem[] } {
|
||||
const rows = this.db
|
||||
.prepare(
|
||||
@@ -145,7 +145,7 @@ export class PluginsService {
|
||||
return {
|
||||
...rest,
|
||||
operatorEgress: _oe === 1,
|
||||
egressHostCount: egressHostCount(r.id),
|
||||
egressHostCount: this.egressHostCount(r.id),
|
||||
dependencies: deps,
|
||||
dependencyStatus,
|
||||
trekRange: trek_range,
|
||||
|
||||
Reference in New Issue
Block a user