Skip to content

Plugin API v1

Su-Yong edited this page Sep 14, 2023 · 2 revisions

manifest.json

{
  "id": "plugin-id",
  "name": "plugin name",
  "description": "optional plugin description",
  "author": "author",
  "version": "1.0.0",
  "versionCode": 1,
  "manifestVersion": 1,

  "css": ["./style1.css", "./style2.css"],
  "main": "index.js",
}

id, name, description, author, version, versionCode: Show this page

  • manifestVersion: It must be 1

Optional Fields

  • css: css path array. it indicates paths where css file is.
  • main: js path string. it indicates path where alspotron load plugin js file from.

CSS

  • TODO

JavaScript

alspotron plugin uses a CommonJS System. plugin's default export must be function.

module.export = (context) => {
  // plugin code
};

the function will being called when the plugin is loaded. and its return function also called when the plugin is unload.
that means plugins working like this.

module.export = (context) => {
  context.logger.info('My Test Plugin is Loaded!!!');

  // some plugin code...

  return () => {
    context.logger.info('My Test Plugin is unloaded. bye 👋🏻 ');
  };
};

Context

Here is PluginContext's type definition.

interface PluginContext {
  on<K extends keyof PluginEventMap>(event: K, listener: PluginEventMap[K]): void;
  
  useConfig(): [Accessor<Config>, (config: DeepPartial<Config>) => void];
  useSetting(options: SettingOption, onValueChange?: () => void): unknown;
  useOverride<Target extends keyof OverrideMap>(target: Target, fn: OverrideMap[Target]): void;

  logger: PluginLogger;
}

Context.on

Context.on is subscribe alspotron's events.

All available events and parameter types are listed below.

interface PluginEventMap {
  'update': (updateContext: { data: UpdateData }) => void;
  'config': (config: DeepPartial<Config>) => void;
  'game-list': (gameList: Partial<GameList>) => void;
  'lyric-mapper': (lyricMapper: Partial<LyricMapper>) => void;
  'registered-process-list': (pidList: number[]) => void;
  'window-minimize': () => void;
  'window-maximize': (maximize: boolean) => void;
  'window-close': () => void;
  'before-add-plugin': (pluginPath: string) => void;
  'add-plugin': (plugin: Plugin, extractPath: string) => void;
  'before-remove-plugin': (plugin: Plugin) => void;
  'after-remove-plugin': (plugin: Plugin) => void;
  'change-plugin-state': (plugin: Plugin, state: 'enable' | 'disable') => void;
  'start-overlay': () => void;
  'stop-overlay': () => void;
  'inject-overlay-to-process': (processId: number, name?: string, filePath?: string) => void;
  'remove-overlay-from-process': (processId: number) => void;
}
  • example
context.on('update', (body) => {
  context.logger.info('Progress change:', body.data.progress);
});

Context.useConfig

This works like createSignal where included in solid-js. It returns tuple that first item is config accessor(Accessor<Config>) and second is config partial setter(PartialSetter<Config>).

Its type definition.

type Accessor<T> = () => T;
type PartialSetter<T> = (value: DeepPartial<T>) => void;
const useConfig = () => [Accessor<Config>, PartialSetter<Config>];

PartialSetter does NOT set the first parameter value as it is.
Because the current data value is set above the default value and then the first parameter value is set, if you want to CLEAR the value, you must set undefined.

  • example
const [config, setConfig] = useConfig();

const nowFont = config().style.font; // read font from config
setConfig({
  style: {
    font: 'Pretendard Variable',
  },
}); // set font

Context.useSetting

  • TODO

Context.useOverride

  • TODO

Context.logger

A logger for plugin. It has info, debug, warn, error, log methods.

Like console.log, it provides any value can serialize.

  • example
const someOptions = { /* ... */ };
try {
  const result = await fetch(someOptions);
  // ...
} catch (err) {
  context.logger.error(`Failed to fetch data`, err, '/', someOptions);
}
Clone this wiki locally