import type { RouteLocationRaw, RouteRecordRaw, RouteRecordName } from 'vue-router'; import type { Component } from '@vue/runtime-core'; /* This is some sort of PEP440 subset */ type Join = T extends [] ? '' : T extends [string | number | boolean | bigint] ? `${T[0]}` : T extends [string | number | boolean | bigint, ...infer U] ? `${T[0]}${D}${Join}` : string; type BaseVersion = Join<[number, number], '.'> | Join<[number, number, number], '.'>; type PreRelease = Join<[['a' | 'b' | 'rc'], number], '.'>; type PRVersion = BaseVersion | `${BaseVersion}${PreRelease}`; /** A PEP440 subset used to describe backend module versions */ export type PEP440Version = PRVersion | `${PRVersion}.dev${number}`; export namespace FG_Plugin { /** * Interface defining a Flaschengeist plugin */ export interface Plugin { /** Unique identifier for this plugin, we recommend using a FQN like com.example.my_plugin */ id: string; /** Arbitrary name of the plugin used inside admin view etc */ name: string; /** Version of this plugin, used for dependencies. MUST be semver parsable */ version: string; /** Widgets provided by this plugin */ widgets: Widget[]; /** Backend modules needed for this plugin to work correctly */ requiredModules: [string, PEP440Version?][]; /** Menu entries for authenticated users */ innerRoutes?: MenuRoute[]; /** Public menu entries (without authentification) */ outerRoutes?: MenuRoute[]; /** Routes without menu links, for internal usage */ internalRoutes?: NamedRouteRecordRaw[]; /** Handle notifications, defaults to boot/plugins.ts:translateNotification() */ notification?(msg: FG.Notification): FG_Plugin.Notification; } /** * Defines the loaded state of the Flaschengeist */ export interface Flaschengeist { /** All loaded plugins */ plugins: LoadedPlugin[]; /** All routes, combined from all plugins */ routes: RouteRecordRaw[]; /** All menu entries */ menuLinks: MenuLink[]; /** All inner shortcuts */ shortcuts: Shortcut[]; /** All outer shortcuts */ outerShortcuts: Shortcut[]; /** All widgets */ widgets: Widget[]; } /** * Interface for a frontend notification */ export interface Notification extends FG.Notification { /** If set a button for accepting will be shown, this function will get called before deleting the notification */ accept?(): Promise; /** If set this function is called before the notification gets deleted */ reject?(): Promise; /** If set the notification text is interpreted as a link to this location */ link?: RouteLocationRaw; /** If set this icon is used */ icon?: string; } /** * Loaded Flaschengeist plugin */ interface LoadedPlugin { name: string; version: string; notification(msg: FG.Notification): FG_Plugin.Notification; } /** * Defines a shortcut link */ export interface Shortcut { link: RouteRecordName; icon: string; permissions?: string[]; } type NamedRouteRecordRaw = RouteRecordRaw & { name: RouteRecordName; }; /** * Defines a main menu entry along with the route * Used when defining a plugin */ export interface MenuRoute extends MenuEntry { route: NamedRouteRecordRaw; shortcut?: boolean; children?: this[]; } /** * Defines a menu entry in the main menu */ export interface MenuLink extends MenuEntry { /** Name of the target route */ link: RouteRecordName; /** * Order inside the menu, higher numbers come ahead of lower numbers * @todo: Promote to required with first beta */ order?: number; } /** * Base interface for internal use */ interface MenuEntry { title: string | (() => string); icon: string; permissions?: string[]; children?: this[]; } /** * Widget object for the dashboard */ export interface Widget { name: string; /** * @deprecated Deprecated in favor of order * @todo Remove with beta 1 */ priority?: number; /** * Default order on the dashboard, higher numbers come ahead of lower numbers * @todo Promote to required if priority is removed */ order?: number; permissions: FG.Permission[]; widget: Component; } }