Refactor into plugin loader and do not enforce (#20112)

This commit is contained in:
Sebastian
2026-03-30 20:36:21 +02:00
committed by GitHub
parent 9f3c2bd861
commit fa95a61c4e
17 changed files with 1056 additions and 351 deletions

View File

@@ -0,0 +1,135 @@
import { Config } from "@/config/config"
import { Installation } from "@/installation"
import {
checkPluginCompatibility,
createPluginEntry,
isDeprecatedPlugin,
resolvePluginTarget,
type PluginKind,
type PluginPackage,
type PluginSource,
} from "./shared"
export namespace PluginLoader {
export type Plan = {
item: Config.PluginSpec
spec: string
options: Config.PluginOptions | undefined
deprecated: boolean
}
export type Resolved = Plan & {
source: PluginSource
target: string
entry: string
pkg?: PluginPackage
}
export type Loaded = Resolved & {
mod: Record<string, unknown>
}
export function plan(item: Config.PluginSpec): Plan {
const spec = Config.pluginSpecifier(item)
return {
item,
spec,
options: Config.pluginOptions(item),
deprecated: isDeprecatedPlugin(spec),
}
}
export async function resolve(
plan: Plan,
kind: PluginKind,
): Promise<
{ ok: true; value: Resolved } | { ok: false; stage: "install" | "entry" | "compatibility"; error: unknown }
> {
let target = ""
try {
target = await resolvePluginTarget(plan.spec)
} catch (error) {
return {
ok: false,
stage: "install",
error,
}
}
if (!target) {
return {
ok: false,
stage: "install",
error: new Error(`Plugin ${plan.spec} target is empty`),
}
}
let base
try {
base = await createPluginEntry(plan.spec, target, kind)
} catch (error) {
return {
ok: false,
stage: "entry",
error,
}
}
if (!base.entry) {
return {
ok: false,
stage: "entry",
error: new Error(`Plugin ${plan.spec} entry is empty`),
}
}
if (base.source === "npm") {
try {
await checkPluginCompatibility(base.target, Installation.VERSION, base.pkg)
} catch (error) {
return {
ok: false,
stage: "compatibility",
error,
}
}
}
return {
ok: true,
value: {
...plan,
source: base.source,
target: base.target,
entry: base.entry,
pkg: base.pkg,
},
}
}
export async function load(row: Resolved): Promise<{ ok: true; value: Loaded } | { ok: false; error: unknown }> {
let mod
try {
mod = await import(row.entry)
} catch (error) {
return {
ok: false,
error,
}
}
if (!mod) {
return {
ok: false,
error: new Error(`Plugin ${row.spec} module is empty`),
}
}
return {
ok: true,
value: {
...row,
mod,
},
}
}
}