clean up the plugin manager

This commit is contained in:
Eugene
2026-07-13 10:41:19 +02:00
parent 142af28596
commit d33ba48302
18 changed files with 525 additions and 810 deletions
+2
View File
@@ -1,9 +1,11 @@
import { app } from 'electron'
import * as nodeModule from 'module'
import * as fs from 'fs'
import * as path from 'path'
// This module is imported before any other main-process module so that errors thrown
// while importing those modules (which run before index.ts's own body) still get logged.
nodeModule.enableCompileCache?.()
export function logMainError (label: string, err: unknown): void {
const detail = err instanceof Error ? err.stack ?? err.message : String(err)
-1
View File
@@ -11,7 +11,6 @@ import 'dotenv/config'
process.env.TABBY_PLUGINS ??= ''
process.env.TABBY_CONFIG_DIRECTORY ??= app.getPath('userData')
import 'v8-compile-cache'
import 'source-map-support/register'
import './sentry'
import './lru'
+9 -32
View File
@@ -1,40 +1,17 @@
import { promisify } from 'util'
import Arborist from '@npmcli/arborist'
// Arborist is npm's own install engine, used in-process so we don't have to bundle the 18 MB npm CLI
// and run it via ELECTRON_RUN_AS_NODE. reify() resolves and installs the full dependency tree.
export class PluginManager {
npm: any
npmReady?: Promise<void>
async ensureLoaded (): Promise<void> {
if (!this.npmReady) {
this.npmReady = new Promise(resolve => {
const npm = require('npm')
npm.load(err => {
if (err) {
console.error(err)
return
}
npm.config.set('global', false)
this.npm = npm
resolve()
})
})
}
return this.npmReady
async install (targetPath: string, name: string, version: string): Promise<void> {
await new Arborist({ path: targetPath, save: false, audit: false, fund: false })
.reify({ add: [`${name}@${version}`] })
}
async install (path: string, name: string, version: string): Promise<void> {
await this.ensureLoaded()
this.npm.prefix = path
return promisify(this.npm.commands.install)([`${name}@${version}`])
}
async uninstall (path: string, name: string): Promise<void> {
await this.ensureLoaded()
this.npm.prefix = path
return promisify(this.npm.commands.remove)([name])
async uninstall (targetPath: string, name: string): Promise<void> {
await new Arborist({ path: targetPath, save: false })
.reify({ rm: [name] })
}
}
export const pluginManager = new PluginManager()
+3 -7
View File
@@ -16,6 +16,7 @@
},
"dependencies": {
"@electron/remote": "^2",
"@npmcli/arborist": "^9",
"any-promise": "^1.3.0",
"atomically": "^2.0.2",
"dunder-proto": "^1",
@@ -30,11 +31,9 @@
"mz": "^2.7.0",
"native-process-working-directory": "^1.0.2",
"node-pty": "^1.2.0-beta.8",
"npm": "12",
"russh": "0.1.37",
"rxjs": "^7.5.7",
"source-map-support": "^0.5.20",
"v8-compile-cache": "^2.3.0",
"yargs": "^17.7.2"
},
"optionalDependencies": {
@@ -49,7 +48,7 @@
"devDependencies": {
"@ngx-translate/core": "^14.0.0",
"@types/mz": "2.7.4",
"@types/node": "20.3.1"
"@types/node": "22"
},
"peerDependencies": {
"tabby-community-color-schemes": "*",
@@ -66,9 +65,6 @@
"node-abi": "4.9.0",
"node-gyp": "^10.0.0",
"nan": "2.22.2",
"node-addon-api": "^8.3.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
"node-addon-api": "^8.3.0"
}
}
+2 -1
View File
@@ -1,4 +1,5 @@
import 'v8-compile-cache'
require('module').enableCompileCache?.()
import '../lib/lru'
import 'source-sans-pro/source-sans-pro.css'
import 'source-code-pro/source-code-pro.css'
+1 -2
View File
@@ -36,7 +36,6 @@ const config = {
],
},
externals: {
'v8-compile-cache': 'commonjs v8-compile-cache',
'any-promise': 'commonjs any-promise',
electron: 'commonjs electron',
'electron-config': 'commonjs electron-config',
@@ -46,7 +45,7 @@ const config = {
fs: 'commonjs fs',
glasstron: 'commonjs glasstron',
mz: 'commonjs mz',
npm: 'commonjs npm',
'@npmcli/arborist': 'commonjs @npmcli/arborist',
'node:os': 'commonjs os',
'node-pty': 'commonjs node-pty',
path: 'commonjs path',
-1
View File
@@ -72,7 +72,6 @@ export default () => ({
},
externals: {
'@electron/remote': 'commonjs @electron/remote',
'v8-compile-cache': 'commonjs v8-compile-cache',
child_process: 'commonjs child_process',
electron: 'commonjs electron',
fs: 'commonjs fs',
+418 -677
View File
File diff suppressed because it is too large Load Diff
@@ -34,9 +34,7 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
strong.d-block {{plugin.name}}
small.d-block.text-muted {{plugin.description}}
ng-template(ngbPanelContent)
.row
.col-4
div.d-flex.flex-column.flex-md-row.gap-2
.d-flex.flex-column.flex-md-row.gap-3.align-items-start
button.btn.btn-primary.btn-block.justify-content-center(
(click)='installPlugin(plugin)',
[disabled]='busy.has(plugin.name)'
@@ -52,11 +50,10 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
i.fas.fa-fw.fa-external-link-alt
span.ms-2(translate) Homepage
.col-8
.ms-auto
div
ng-container(*ngTemplateOutlet='pluginInfo; context: { plugin }')
.mt-2 {{plugin.description}}
li(ngbNavItem)
a(ngbNavLink, translate) Installed
ng-template(ngbNavContent)
@@ -94,8 +91,7 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
)
ng-template(ngbPanelContent)
.row
.col-4
.d-flex.flex-column.flex-md-row.gap-3.align-items-start
button.btn.btn-warning.btn-block.justify-content-center(
(click)='togglePlugin(plugin)',
*ngIf='isPluginEnabled(plugin)',
@@ -117,21 +113,17 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
i.fas.fa-fw.fa-trash(*ngIf='busy.get(plugin.name) != BusyState.Uninstalling')
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Uninstalling')
span(translate) Uninstall
.col-8
.ms-auto
div
ng-container(*ngTemplateOutlet='pluginInfo; context: { plugin }')
.mt-2 {{plugin.description}}
ng-template(#pluginInfo, let-plugin='plugin')
.row.align-items-center
.col-4
.d-flex.align-items-center.gap-3
strong(translate) Version
.col-8
span {{plugin.version}}
.row.align-items-center
.col-4
.d-flex.align-items-center.gap-3
strong(translate) Author
.col-8
.badge.text-bg-success(*ngIf='plugin.isOfficial')
i.fas.fa-check
span.ms-1(translate) Official
@@ -124,7 +124,8 @@ export class PluginsSettingsTabComponent {
}
async upgradePlugin (plugin: PluginInfo): Promise<void> {
return this.installPlugin(this.knownUpgrades[plugin.name]!)
await this.installPlugin(this.knownUpgrades[plugin.name]!)
this.knownUpgrades[plugin.name] = null
}
showPluginInfo (plugin: PluginInfo) {
@@ -60,7 +60,7 @@ export class PluginManagerService {
description: item.package.description,
version: item.package.version,
homepage: item.package.links.homepage,
author: item.package.author?.name,
author: item.package.maintainers?.[0]?.username,
isOfficial: item.package.publisher.username === OFFICIAL_NPM_ACCOUNT,
searchScore: item.searchScore,
})),
+1 -1
View File
@@ -18,7 +18,7 @@
"author": "Tabby Developers",
"license": "MIT",
"devDependencies": {
"@types/node": "14.14.14",
"@types/node": "22",
"ansi-colors": "^4.1.1"
},
"peerDependencies": {
+11 -4
View File
@@ -2,12 +2,19 @@
# yarn lockfile v1
"@types/node@14.14.14":
version "14.14.14"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
"@types/node@22":
version "22.20.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.20.1.tgz#84e7cdf63cdaa20c134aa317ccc901aa21e16f0e"
integrity sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==
dependencies:
undici-types "~6.21.0"
ansi-colors@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
+1 -1
View File
@@ -20,7 +20,7 @@
"author": "Tabby Developers",
"license": "MIT",
"devDependencies": {
"@types/node": "20.3.1",
"@types/node": "22",
"ansi-colors": "^4.1.1",
"strip-ansi": "^7.0.0"
},
+11 -4
View File
@@ -9,10 +9,12 @@
dependencies:
ipv6 "*"
"@types/node@20.3.1":
version "20.3.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe"
integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==
"@types/node@22":
version "22.20.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.20.1.tgz#84e7cdf63cdaa20c134aa317ccc901aa21e16f0e"
integrity sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==
dependencies:
undici-types "~6.21.0"
ansi-colors@^4.1.1:
version "4.1.3"
@@ -185,6 +187,11 @@ tmp@^0.2.0:
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.7.tgz#26f4db11d1601ce8012dcb8a798ece1c06a99059"
integrity sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
winston@0.8.x:
version "0.8.3"
resolved "https://registry.yarnpkg.com/winston/-/winston-0.8.3.tgz#64b6abf4cd01adcaefd5009393b1d8e8bec19db0"
+1 -1
View File
@@ -19,7 +19,7 @@
"license": "MIT",
"devDependencies": {
"ansi-colors": "^4.1.1",
"@types/node": "14.14.31"
"@types/node": "22"
},
"peerDependencies": {
"@angular/animations": "^15",
+11 -4
View File
@@ -2,12 +2,19 @@
# yarn lockfile v1
"@types/node@14.14.31":
version "14.14.31"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==
"@types/node@22":
version "22.20.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.20.1.tgz#84e7cdf63cdaa20c134aa317ccc901aa21e16f0e"
integrity sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==
dependencies:
undici-types "~6.21.0"
ansi-colors@^4.1.1:
version "4.1.3"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
-13
View File
@@ -1,13 +0,0 @@
diff --git a/node_modules/browserify-sign/browser/index.js b/node_modules/browserify-sign/browser/index.js
index e6df44c..641e18e 100644
--- a/node_modules/browserify-sign/browser/index.js
+++ b/node_modules/browserify-sign/browser/index.js
@@ -11,6 +11,8 @@ Object.keys(algorithms).forEach(function (key) {
algorithms[key.toLowerCase()] = algorithms[key]
})
+algorithms['sha1'] = algorithms['RSA-SHA1']
+
function Sign (algorithm) {
stream.Writable.call(this)