The contract every Schuly plugin implements.
dotnet add package Schuly.Plugin.Abstractionsusing Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Schuly.Plugin.Abstractions;
public sealed class MyPlugin : ISchulyPlugin
{
public string Name => "My School";
public string Version => "1.0.0";
public void ConfigureServices(IServiceCollection services, PluginServiceContext context) { }
public void ConfigureEndpoints(IEndpointRouteBuilder endpoints) =>
endpoints.MapGet("/api/plugins/myschool/hello", () => "Hello from my plugin");
public Task MigrateAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken = default) =>
Task.CompletedTask;
}That's a whole plugin. SchulyServer finds the class, and the plugin never touches the server's source or database.
Implement these when your plugin needs them:
IPluginLogin: connect a school account, and put your school system in the app's pickerIPluginBackgroundTask: recurring work on aPluginScheduleIPluginEventHandler<TCommand>: react to application commandsILinkProvider: link an outside account
The server hands you ISchoolData, IPluginVault, IPluginFileStore, IPluginUserContext and ILinkedAccounts.
The contract has every member, versioning says what counts as breaking, and Add a plugin goes from here to a loaded plugin.