mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
feat(plugin): ✨ Add override settings to plugin loading
This commit is contained in:
parent
c0805ff125
commit
f26ab0f0e6
2
.github/config.workflow.toml
vendored
2
.github/config.workflow.toml
vendored
|
|
@ -287,6 +287,6 @@ max_coeff = 1.0
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|
||||||
[plugins."@versia/openid".keys]
|
[plugins.config."@versia/openid".keys]
|
||||||
private = "MC4CAQAwBQYDK2VwBCIEID+H5n9PY3zVKZQcq4jrnE1IiRd2EWWr8ApuHUXmuOzl"
|
private = "MC4CAQAwBQYDK2VwBCIEID+H5n9PY3zVKZQcq4jrnE1IiRd2EWWr8ApuHUXmuOzl"
|
||||||
public = "MCowBQYDK2VwAyEAzenliNkgpXYsh3gXTnAoUWzlCPjIOppmAVx2DBlLsC8="
|
public = "MCowBQYDK2VwAyEAzenliNkgpXYsh3gXTnAoUWzlCPjIOppmAVx2DBlLsC8="
|
||||||
|
|
|
||||||
11
app.ts
11
app.ts
|
|
@ -119,19 +119,24 @@ export const appFactory = async () => {
|
||||||
|
|
||||||
const loader = new PluginLoader();
|
const loader = new PluginLoader();
|
||||||
|
|
||||||
const plugins = await loader.loadPlugins(join(process.cwd(), "plugins"));
|
const plugins = await loader.loadPlugins(
|
||||||
|
join(process.cwd(), "plugins"),
|
||||||
|
config.plugins?.autoload,
|
||||||
|
config.plugins?.overrides.enabled,
|
||||||
|
config.plugins?.overrides.disabled,
|
||||||
|
);
|
||||||
|
|
||||||
for (const data of plugins) {
|
for (const data of plugins) {
|
||||||
serverLogger.info`Loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} ${chalk.gray(`[${plugins.indexOf(data) + 1}/${plugins.length}]`)}`;
|
serverLogger.info`Loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} ${chalk.gray(`[${plugins.indexOf(data) + 1}/${plugins.length}]`)}`;
|
||||||
try {
|
try {
|
||||||
// biome-ignore lint/complexity/useLiteralKeys: loadConfig is a private method
|
// biome-ignore lint/complexity/useLiteralKeys: loadConfig is a private method
|
||||||
await data.plugin["_loadConfig"](
|
await data.plugin["_loadConfig"](
|
||||||
config.plugins?.[data.manifest.name],
|
config.plugins?.config?.[data.manifest.name],
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
serverLogger.fatal`Plugin configuration is invalid: ${chalk.redBright(e as ValidationError)}`;
|
serverLogger.fatal`Plugin configuration is invalid: ${chalk.redBright(e as ValidationError)}`;
|
||||||
serverLogger.fatal`Put your configuration at ${chalk.blueBright(
|
serverLogger.fatal`Put your configuration at ${chalk.blueBright(
|
||||||
"plugins.<plugin-name>",
|
"plugins.config.<plugin-name>",
|
||||||
)}`;
|
)}`;
|
||||||
throw new Error("Plugin configuration is invalid");
|
throw new Error("Plugin configuration is invalid");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ describe("PluginLoader", () => {
|
||||||
default: mockPlugin,
|
default: mockPlugin,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const plugins = await pluginLoader.loadPlugins("/some/path");
|
const plugins = await pluginLoader.loadPlugins("/some/path", true);
|
||||||
expect(plugins).toEqual([
|
expect(plugins).toEqual([
|
||||||
{
|
{
|
||||||
manifest: manifestContent,
|
manifest: manifestContent,
|
||||||
|
|
|
||||||
|
|
@ -162,12 +162,42 @@ export class PluginLoader {
|
||||||
*/
|
*/
|
||||||
public async loadPlugins(
|
public async loadPlugins(
|
||||||
dir: string,
|
dir: string,
|
||||||
|
autoload: boolean,
|
||||||
|
enabled?: string[],
|
||||||
|
disabled?: string[],
|
||||||
): Promise<{ manifest: Manifest; plugin: Plugin<ZodTypeAny> }[]> {
|
): Promise<{ manifest: Manifest; plugin: Plugin<ZodTypeAny> }[]> {
|
||||||
const plugins = await PluginLoader.findPlugins(dir);
|
const plugins = await PluginLoader.findPlugins(dir);
|
||||||
|
|
||||||
|
const enabledOn = (enabled?.length ?? 0) > 0;
|
||||||
|
const disabledOn = (disabled?.length ?? 0) > 0;
|
||||||
|
|
||||||
|
if (enabledOn && disabledOn) {
|
||||||
|
this.logger
|
||||||
|
.fatal`Both enabled and disabled lists are specified. Only one of them can be used.`;
|
||||||
|
throw new Error("Invalid configuration");
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
plugins.map(async (plugin) => {
|
plugins.map(async (plugin) => {
|
||||||
const manifest = await this.parseManifest(dir, plugin);
|
const manifest = await this.parseManifest(dir, plugin);
|
||||||
|
|
||||||
|
// If autoload is disabled, only load plugins explicitly enabled
|
||||||
|
if (
|
||||||
|
!(autoload || enabledOn || enabled?.includes(manifest.name))
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If enabled is specified, only load plugins in the enabled list
|
||||||
|
// If disabled is specified, only load plugins not in the disabled list
|
||||||
|
if (enabledOn && !enabled?.includes(manifest.name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disabled?.includes(manifest.name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const pluginInstance = await this.loadPlugin(
|
const pluginInstance = await this.loadPlugin(
|
||||||
dir,
|
dir,
|
||||||
`${plugin}/index`,
|
`${plugin}/index`,
|
||||||
|
|
@ -175,6 +205,6 @@ export class PluginLoader {
|
||||||
|
|
||||||
return { manifest, plugin: pluginInstance };
|
return { manifest, plugin: pluginInstance };
|
||||||
}),
|
}),
|
||||||
);
|
).then((data) => data.filter((d) => d !== null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4007,7 +4007,41 @@
|
||||||
},
|
},
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {}
|
"properties": {
|
||||||
|
"autoload": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"disabled": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"default": {
|
||||||
|
"enabled": [],
|
||||||
|
"disabled": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -4019,7 +4053,8 @@
|
||||||
"http",
|
"http",
|
||||||
"smtp",
|
"smtp",
|
||||||
"filters",
|
"filters",
|
||||||
"ratelimits"
|
"ratelimits",
|
||||||
|
"plugins"
|
||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -14,7 +14,10 @@ const scope = "openid profile email";
|
||||||
const secret = "test-secret";
|
const secret = "test-secret";
|
||||||
const privateKey = await crypto.subtle.importKey(
|
const privateKey = await crypto.subtle.importKey(
|
||||||
"pkcs8",
|
"pkcs8",
|
||||||
Buffer.from(config.plugins?.["@versia/openid"].keys.private, "base64"),
|
Buffer.from(
|
||||||
|
config.plugins?.config?.["@versia/openid"].keys.private,
|
||||||
|
"base64",
|
||||||
|
),
|
||||||
"Ed25519",
|
"Ed25519",
|
||||||
false,
|
false,
|
||||||
["sign"],
|
["sign"],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue