mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 23:46:35 +00:00
feat(plugins): install an older version of a plugin (#2035)
Adds a version picker to the plugin admin panel, on desktop and mobile: every published version with its own server-computed compatibility verdict, so the client never re-derives semver range logic. A deliberate non-latest pick sets an update hold on the row, which keeps the update banner and "Update all" from immediately nagging the rollback away. The hold releases when an install lands back on the newest compatible version by any path, or when the admin resumes updates explicitly. An unresolvable registry never sets one: refusing to pin on missing information beats silently muting future updates.
This commit is contained in:
@@ -43,6 +43,7 @@ interface PluginRawRow {
|
||||
update_block_code: string | null;
|
||||
update_block_detail: string | null;
|
||||
update_block_version: string | null;
|
||||
update_hold: number;
|
||||
}
|
||||
|
||||
export interface PluginListItem {
|
||||
@@ -87,6 +88,9 @@ export interface PluginListItem {
|
||||
/** Why an update was refused, if one was. `version` is the registry version that was
|
||||
* refused, so a caller can treat the block as stale once a newer one is on offer. */
|
||||
updateBlock: { code: string; detail: string | null; version: string | null } | null;
|
||||
/** A deliberate non-latest install paused updates: excluded from the banner/Update all
|
||||
* until the admin resumes, or an install lands back on the newest compatible version. */
|
||||
updateHold: boolean;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@@ -114,7 +118,7 @@ export class PluginsService {
|
||||
.prepare(
|
||||
`SELECT id, name, description, type, icon, version, status, enabled, last_error, reviewed_at, source_repo,
|
||||
permissions, capabilities, dependencies, operator_egress, trek_range,
|
||||
author_pubkey, update_block_code, update_block_detail, update_block_version
|
||||
author_pubkey, update_block_code, update_block_detail, update_block_version, update_hold
|
||||
FROM plugins
|
||||
ORDER BY sort_order, name`,
|
||||
)
|
||||
@@ -143,6 +147,7 @@ export class PluginsService {
|
||||
update_block_code,
|
||||
update_block_detail,
|
||||
update_block_version,
|
||||
update_hold,
|
||||
...rest
|
||||
} = r as PluginRawRow & { operator_egress?: number };
|
||||
return {
|
||||
@@ -159,11 +164,20 @@ export class PluginsService {
|
||||
updateBlock: update_block_code
|
||||
? { code: update_block_code, detail: update_block_detail, version: update_block_version }
|
||||
: null,
|
||||
updateHold: update_hold === 1,
|
||||
};
|
||||
});
|
||||
return { enabled: pluginsEnabled(), devLink: devLinkEnabled(), plugins };
|
||||
}
|
||||
|
||||
/**
|
||||
* Release a per-plugin update hold (set by a deliberate non-latest install).
|
||||
* Returns whether the plugin row existed — the controller answers 404 otherwise.
|
||||
*/
|
||||
resumeUpdates(id: string): boolean {
|
||||
return this.db.prepare('UPDATE plugins SET update_hold = 0 WHERE id = ?').run(id).changes > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge instance-scope settings into the plugin's config, encrypting fields
|
||||
* declared secret (unless the value is the unchanged mask sentinel). Only keys
|
||||
|
||||
Reference in New Issue
Block a user