refactor: Removed the use of d.ts files to support SDK generation for public plugins

This commit is contained in:
Simeon Radivoev 2026-05-05 01:21:22 +03:00
parent 06b7e4074d
commit 2683d46b16
Signed by: simeonradivoev
GPG key ID: 7611A451D2A5D37A
114 changed files with 408 additions and 257 deletions

View file

@ -24,6 +24,7 @@ import controls from './controls/controls';
import { RunAPIServer } from "./rpc";
import { RunBunServer } from "../server";
import ReloadPluginsJob from "./jobs/reload-plugins-job";
import { AppEventMap } from "../types/types";
export let config: Conf<SettingsType>;
export let customEmulators: Conf<Record<string, string>>;

View file

@ -1,6 +1,7 @@
import si from 'systeminformation';
import fs from 'node:fs';
import os from "node:os";
import { Drive } from '@/shared/types';
async function getAccess (path: string)
{

View file

@ -5,6 +5,7 @@ import z from "zod";
import path from 'node:path';
import { config, events, plugins } from "../app";
import { getLocalGame, updateLocalLastPlayed } from "../games/services/statusService";
import { SaveFileChange } from "@/shared/types";
// TODO: use the retroarch cores based on ES-DE
export const cores: Record<string, string> = {
@ -83,7 +84,7 @@ export default new Elysia({ prefix: '/emulatorjs' })
await plugins.hooks.games.postPlay.promise({
source,
id,
saveFolderPath: path.join(config.get('downloadPath'), "saves", "EMULATORJS"),
saveFolderSlots: { 'emulatorjs': { cwd: path.join(config.get('downloadPath'), "saves", "EMULATORJS") } },
gameInfo: { platformSlug: localGame?.platform.slug },
changedSaveFiles: [],
validChangedSaveFiles: changedSaveFiles,

View file

@ -1,5 +1,6 @@
import Elysia, { status } from "elysia";
import { plugins } from "../app";
import { FrontEndCollection } from "@/shared/types";
export default new Elysia()
.get('/collections', async () =>

View file

@ -22,6 +22,7 @@ import { LaunchGameJob } from "../jobs/launch-game-job";
import { cores } from "../emulatorjs/emulatorjs";
import { findEmulatorPluginIntegration } from "../store/services/emulatorsService";
import { ImportJob } from "../jobs/import-job";
import { EmulatorSourceEntryType, EmulatorSystem, FrontEndFilterLists, FrontEndFilterSets, FrontEndGameType, FrontEndGameTypeDetailedEmulator, FrontEndGameTypeWithIds, FrontEndId, GameLookup } from "@/shared/types";
// A custom jimp that supports webp
const Jimp = createJimp({

View file

@ -4,6 +4,7 @@ import { and, count, eq, getTableColumns, not, notExists, or } from "drizzle-orm
import { config, db, plugins } from "../app";
import * as schema from "@schema/app";
import { findPlatform } from "./services/utils";
import { FrontEndPlatformType } from "@/shared/types";
export default new Elysia()
.get('/platforms', async () =>

View file

@ -6,6 +6,7 @@ import { config, taskQueue } from '../../app';
import { LaunchGameJob } from '../../jobs/launch-game-job';
import { getStoreEmulatorPackage } from '../../store/services/gamesService';
import { getOrCachedScoopPackage } from '../../store/services/emulatorsService';
import { CommandEntry, EmulatorSourceEntryType, FrontEndId } from '@/shared/types';
export async function launchCommand (validCommand: CommandEntry, id: FrontEndId, source?: string, sourceId?: string)
{

View file

@ -10,6 +10,7 @@ import { LaunchGameJob } from "../../jobs/launch-game-job";
import * as appSchema from "@schema/app";
import { DownloadSourceSchema, RPC_URL } from "@/shared/constants";
import { host } from "@/bun/utils/host";
import { CommandEntry, FrontEndId, GameLookup, GameStatusType, LocalDownloadFileEntry } from "@/shared/types";
export class CommandSearchError extends Error
{

View file

@ -8,6 +8,7 @@ import { RPC_URL } from "@shared/constants";
import { hashFile } from "@/bun/utils";
import { host } from "@/bun/utils/host";
import * as emulatorSchema from "@schema/emulators";
import { DownloadFileEntry, FrontEndGameType, FrontEndGameTypeDetailed, GameLookup, LocalDownloadFileEntry, LocalGameMetadata } from "@/shared/types";
export async function calculateSize (installPath: string | null)
{

View file

@ -1,9 +1,9 @@
import { AuthHooks } from "./auth";
import { EmulatorHooks } from "./emulators";
import { GameHooks } from "./games";
import { StoreHooks } from "./store";
import AuthHooks from "./auth";
import EmulatorHooks from "./emulators";
import GameHooks from "./games";
import StoreHooks from "./store";
export class GameflowHooks
export default class GameflowHooks
{
games = new GameHooks();
emulators = new EmulatorHooks();

View file

@ -1,6 +1,7 @@
import { DownloadFileEntry } from "@/shared/types";
import { AsyncSeriesHook } from "tapable";
export class AuthHooks
export default class AuthHooks
{
loginComplete = new AsyncSeriesHook<[ctx: {
service: string;

View file

@ -1,16 +1,8 @@
import { EmulatorDownloadInfoType, EmulatorPackageType } from "@/shared/constants";
import { EmulatorPostInstallContext } from "@/bun/types/types";
import { DownloadFileEntry, EmulatorSourceEntryType, EmulatorSystem } from "@/shared/types";
import { AsyncSeriesBailHook, AsyncSeriesHook } from "tapable";
interface EmulatorPostInstallContext
{
emulator: string;
emulatorPackage?: EmulatorPackageType;
path: string;
update: boolean;
info: EmulatorDownloadInfoType;
}
export class EmulatorHooks
export default class EmulatorHooks
{
fetchBiosDownload = new AsyncSeriesBailHook<[ctx: {
emulator: string;

View file

@ -1,7 +1,8 @@
import { EmulatorPackageType, GameListFilterType } from '@/shared/constants';
import { SyncBailHook, AsyncSeriesHook, AsyncSeriesBailHook } from 'tapable';
import { CommandEntry, DownloadInfo, EmulatorSourceEntryType, EmulatorSupport, EmulatorSystem, FrontEndCollection, FrontEndFilterSets, FrontEndGameType, FrontEndGameTypeDetailed, FrontEndGameTypeWithIds, FrontEndId, FrontEndPlatformType, GameLookup, SaveFileChange, SaveSlots } from '@/shared/types';
import { SyncBailHook, AsyncSeriesHook, AsyncSeriesBailHook, Hook } from 'tapable';
export class GameHooks
export default class GameHooks
{
buildLaunchCommands = new AsyncSeriesBailHook<[ctx: {
source: string | null;
@ -121,7 +122,7 @@ export class GameHooks
postPlay = new AsyncSeriesHook<[ctx: {
source: string,
id: string;
saveFolderSlots?: Record<string, { cwd: string; }>;
saveFolderSlots?: SaveSlots;
changedSaveFiles: { subPath: string, cwd: string; }[],
validChangedSaveFiles: Record<string, SaveFileChange>,
command: CommandEntry;

View file

@ -1,7 +1,8 @@
import { EmulatorDownloadInfoType } from "@/shared/constants";
import { FrontEndEmulator, FrontEndEmulatorDetailed, FrontEndGameTypeDetailed } from "@/shared/types";
import { AsyncSeriesBailHook, AsyncSeriesHook } from "tapable";
export class StoreHooks
export default class StoreHooks
{
fetchFeaturedGames = new AsyncSeriesHook<[ctx: { games: FrontEndGameTypeDetailed[]; }]>(['ctx']);
fetchEmulators = new AsyncSeriesHook<[ctx: { emulators: FrontEndEmulator[]; search?: string; }]>(['ctx']);

View file

@ -12,6 +12,7 @@ import { simulateProgress } from "@/bun/utils";
import { path7za } from "7zip-bin";
import { getEmulatorDownload, getEmulatorPath } from "../store/services/emulatorsService";
import { $ } from "bun";
import { EmulatorSourceEntryType } from "@/shared/types";
type EmulatorDownloadStates = "download" | "extract";

View file

@ -4,6 +4,7 @@ import { createLocalGame } from "../games/services/utils";
import { IJob, JobContext } from "../task-queue";
import * as schema from "@schema/app";
import z from "zod";
import { GameLookup } from "@/shared/types";
export class ImportJob implements IJob<z.infer<typeof ImportJob.dataSchema>, string>
{

View file

@ -11,6 +11,7 @@ import { ensureDir, move } from "fs-extra";
import { path7za } from "7zip-bin";
import StreamZip from 'node-stream-zip';
import { which } from "bun";
import { DownloadInfo } from "@/shared/types";
interface JobConfig
{

View file

@ -1,13 +1,13 @@
import z from "zod";
import { IJob, JobContext } from "../task-queue";
import { ActiveGameSchema, ActiveGameType } from "@/bun/types/typesc.schema";
import { ActiveGameSchema, ActiveGameType } from "@/bun/types/types.schema";
import { config, db, events, plugins } from "../app";
import * as appSchema from "@schema/app";
import { eq } from "drizzle-orm";
import { spawn } from 'node:child_process';
import fs from "node:fs/promises";
import { updateLocalLastPlayed } from "../games/services/statusService";
import { getErrorMessage } from "@/bun/utils";
import { CommandEntry, FrontEndId, SaveSlots } from "@/shared/types";
export class LaunchGameJob implements IJob<z.infer<typeof LaunchGameJob.dataSchema>, string>
{

View file

@ -1,7 +1,6 @@
import z from "zod";
import { IJob, JobContext } from "../task-queue";
import { cleanPromise, cleanup, events, plugins } from "../app";
import fs from 'fs/promises';
import { events } from "../app";
import { Downloader } from "@/bun/utils/downloader";
import path from 'node:path';
import os from "node:os";

View file

@ -1,4 +1,5 @@
import { FrontendNotification } from '@/shared/types';
import { events } from './app';
export default function buildNotificationsStream ()

View file

@ -1,4 +1,4 @@
import { PluginContextType, PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import path from 'node:path';
import { config } from "@/bun/api/app";

View file

@ -1,6 +1,6 @@
import { config } from "@/bun/api/app";
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import path from 'node:path';
import desc from './package.json';
import { ensureDir } from "fs-extra";

View file

@ -1,11 +1,12 @@
import { config } from "@/bun/api/app";
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import defaultConfig from './PCSX2.ini' with { type: 'file' };
import path from 'node:path';
import { ensureDir } from "fs-extra";
import desc from './package.json';
import ini from 'ini';
import { EmulatorCapabilities } from "@/shared/types";
export default class PCSX2Integration implements PluginType
{

View file

@ -1,4 +1,4 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import { config } from "@/bun/api/app";
import configFilePathWin32 from './win32/ppsspp.ini' with { type: 'file' };
@ -11,6 +11,7 @@ import { ensureDir } from "fs-extra";
import { homedir } from "node:os";
import ini from 'ini';
import fs from 'node:fs/promises';
import { EmulatorCapabilities } from "@/shared/types";
export default class PPSSPPIntegration implements PluginType
{

View file

@ -1,4 +1,4 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import { config } from "@/bun/api/app";
import path from "node:path";

View file

@ -1,5 +1,4 @@
import { join } from "path";
import { platform } from "os";
const SECTOR_SIZE = 0x800;
const MAGIC = "MICROSOFT*XBOX*MEDIA";

View file

@ -1,6 +1,6 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import { GameflowHooks } from "@/bun/api/hooks/app";
import GameflowHooks from "@/bun/api/hooks/app";
import { config } from "@/bun/api/app";
import path from "node:path";
import { ensureDir } from "fs-extra";

View file

@ -1,4 +1,4 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import { config, customEmulators, db, emulatorsDb } from "@/bun/api/app";
import * as emulatorSchema from '@schema/emulators';
@ -13,6 +13,7 @@ import { findStoreEmulatorExec } from "@/bun/api/games/services/launchGameServic
import { which } from "bun";
import os from 'node:os';
import { getLocalGameMatch } from "@/bun/api/games/services/utils";
import { CommandEntry, EmulatorSourceEntryType } from "@/shared/types";
export default class IgdbIntegration implements PluginType
{

View file

@ -1,13 +1,13 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import { config, db, events } from "@/bun/api/app";
import path, { dirname } from 'node:path';
import path from 'node:path';
import unzip from 'unzip-stream';
import { chmodSync, ensureDir } from "fs-extra";
import { ensureDir } from "fs-extra";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";
import fs from 'node:fs/promises';
import { randomUUIDv7, sleep } from "bun";
import { randomUUIDv7 } from "bun";
import z from "zod";
import { createInterface } from "node:readline";
import { getLocalGameMatch } from "@/bun/api/games/services/utils";

View file

@ -1,9 +1,10 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import secrets from "@/bun/api/secrets";
import PQueue from 'p-queue';
import * as igdb from '@phalcode/ts-igdb-client';
import { checkLoginAndRefreshTwitch } from "@/bun/api/auth";
import { GameLookup } from "@/shared/types";
export default class IgdbIntegration implements PluginType
{
@ -80,7 +81,7 @@ export default class IgdbIntegration implements PluginType
first_release_date: g.first_release_date ? g.first_release_date * 1000 : undefined,
average_rating: g.rating ?? undefined,
keywords: g.keywords?.map(k => k.name!) ?? [],
igdb_id: g.id,
igdb_id: g.id ?? undefined,
platforms: g.platforms?.map(p => ({ id: p.id!, name: p.abbreviation, displayName: p.name!, slug: p.slug! })) ?? [],
slug: g.slug
};

View file

@ -1,6 +1,6 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import { DetailedRomSchema, getCollectionApiCollectionsIdGet, getCollectionsApiCollectionsGet, getCurrentUserApiUsersMeGet, getPlatformApiPlatformsIdGet, getPlatformFirmwareApiFirmwareGet, getPlatformsApiPlatformsGet, getRomApiRomsIdGet, getRomByMetadataProviderApiRomsByMetadataProviderGet, getRomContentApiRomsIdContentFileNameGet, getRomFiltersApiRomsFiltersGet, getRomsApiRomsGet, getSavesSummaryApiSavesSummaryGet, PlatformSchema, SimpleRomSchema, updateRomUserApiRomsIdPropsPut } from "@/clients/romm";
import { config, events } from "@/bun/api/app";
@ -14,6 +14,7 @@ import { client } from "@/clients/romm/client.gen";
import { validateGameSource } from "@/bun/api/games/services/statusService";
import z from "zod";
import { checkLoginAndRefreshRomm } from "@/bun/api/auth";
import { DownloadFileEntry, DownloadInfo, FrontEndCollection, FrontEndGameType, FrontEndGameTypeDetailed, FrontEndGameTypeDetailedAchievement, FrontEndGameTypeWithIds, FrontEndPlatformType } from "@/shared/types";
const SettingsSchema = z.object({
savesSync: z.boolean().default(false).describe("Experimental save sync support")

View file

@ -12,6 +12,7 @@ import { shuffleInPlace } from "@/bun/utils";
import mustache from "mustache";
import { getEmulatorDownload, getEmulatorPath } from "@/bun/api/store/services/emulatorsService";
import fs from "node:fs/promises";
import { CommandEntry, EmulatorSourceEntryType, EmulatorSystem, FrontEndEmulator, FrontEndFilterSets, FrontEndGameType, FrontEndGameTypeDetailed, SaveFileChange } from "@/shared/types";
export async function getStoreGames (gamesManifest: any[], filter?: { limit?: number; offset?: number; })
{

View file

@ -1,4 +1,4 @@
import { PluginLoadingContextType, PluginType } from "@/bun/types/typesc.schema";
import { PluginLoadingContextType, PluginType } from "@/bun/types/types.schema";
import desc from './package.json';
import path, { } from 'node:path';
import { buildStoreFrontendEmulatorSystems, getAllStoreEmulatorPackages, getStoreEmulatorPackage, getStoreFolder } from "@/bun/api/store/services/gamesService";
@ -12,6 +12,7 @@ import { getSourceGameDetailed } from "@/bun/api/games/services/utils";
import UpdateStoreJob from "@/bun/api/jobs/update-store";
import { getEmulatorDownload, getEmulatorPath } from "@/bun/api/store/services/emulatorsService";
import { buildFilters, buildLaunchCommand, buildSaves, convertStoreEmulatorToFrontend, convertStoreToFrontend, convertStoreToFrontendDetailed, getExistingStoreEmulatorDownload, getShuffledStoreGames, getStoreGame, getValidDownloads } from "./services";
import { DownloadInfo, FrontEndEmulatorDetailed, FrontEndGameTypeWithIds } from "@/shared/types";
export default class RommIntegration implements PluginType
{

View file

@ -1,10 +1,10 @@
import { GameflowHooks } from "../hooks/app";
import { PluginDescriptionType, PluginLoadingContextType, PluginType } from "../../types/typesc.schema";
import GameflowHooks from "../hooks/app";
import { PluginDescriptionType, PluginLoadingContextType, PluginType } from "../../types/types.schema";
import { config } from "../app";
import Conf from "conf";
import projectPackage from '~/package.json';
import z from "zod";
import { EventEmitter } from "node:stream";
import { PluginSourceType } from "@/shared/types";
export const pluginZodRegistry = z.registry<{
requiresRestart?: boolean;

View file

@ -3,6 +3,7 @@ import { plugins, taskQueue } from "../app";
import z from "zod";
import { toggleElementInConfig } from "@/bun/utils";
import ReloadPluginsJob from "../jobs/reload-plugins-job";
import { FrontendPlugin } from "@/shared/types";
export default new Elysia({ prefix: '/plugins' })
.get('/', async () =>

View file

@ -11,11 +11,15 @@ import igdb from './builtin/sources/com.simeonradivoev.gameflow.igdb/package.jso
import store from './builtin/sources/com.simeonradivoev.gameflow.store/package.json';
import es from './builtin/launchers/com.simeonradivoev.gameflow.es/package.json';
import rclone from './builtin/other/com.simeonradivoev.gameflow.rclone/package.json';
import { PluginDescriptionSchema, PluginDescriptionType, PluginSchema } from "@/bun/types/typesc.schema";
import { PluginDescriptionSchema, PluginDescriptionType, PluginSchema } from "@/bun/types/types.schema";
import path from 'node:path';
import { getStoreRootFolder } from "../store/services/gamesService";
type PluginEntry = PluginDescriptionType & { load: () => Promise<any>; };
export default async function register (pluginManager: PluginManager)
{
const plugins: (PluginDescriptionType & { main: string; load: () => Promise<any>; })[] = [
const plugins: PluginEntry[] = [
{ ...pcsx2, load: () => import('./builtin/emulators/com.simeonradivoev.gameflow.pcsx2/pcsx2') },
{ ...ppsspp, load: () => import('./builtin/emulators/com.simeonradivoev.gameflow.ppsspp/ppsspp') },
{ ...dolphin, load: () => import('./builtin/emulators/com.simeonradivoev.gameflow.dolphin/dolphin') },
@ -29,6 +33,33 @@ export default async function register (pluginManager: PluginManager)
{ ...rclone, load: () => import('./builtin/other/com.simeonradivoev.gameflow.rclone/rclone') },
];
const storePackageFile = path.join(getStoreRootFolder(), 'package.json');
const storePackage = await Bun.file(storePackageFile).json();
if (storePackage.dependencies)
{
const storePlugins = await Promise.all(Object.keys(storePackage.dependencies).map(async p =>
{
const pluginPath = path.join(getStoreRootFolder(), 'node_modules', p);
const pluginPackageFile = Bun.file(path.join(pluginPath, 'package.json'));
if (await pluginPackageFile.exists())
{
const pluginPackage = await PluginDescriptionSchema.safeParseAsync(await pluginPackageFile.json());
if (pluginPackage.success)
{
const mainPath = path.join(pluginPath, pluginPackage.data.main);
if (await Bun.file(mainPath).exists())
{
const entry: PluginEntry = { ...pluginPackage.data, load: () => import(mainPath) };
return entry;
}
}
}
}));
plugins.push(...storePlugins.filter(p => !!p));
}
await Promise.all(plugins.filter(p =>
{
if (process.env.PLUGIN_WHITELIST && !process.env.PLUGIN_WHITELIST.includes(p.name))

View file

@ -1,3 +1,4 @@
import { LocalGameMetadata } from "@/shared/types";
import { sql, relations } from "drizzle-orm";
import { integer, text, sqliteTable, blob } from "drizzle-orm/sqlite-core";

View file

@ -7,6 +7,7 @@ import { cores } from '../emulatorjs/emulatorjs';
import { SERVER_URL } from '@/shared/constants';
import { host } from '@/bun/utils/host';
import { findEmulatorPluginIntegration } from '../store/services/emulatorsService';
import { EmulatorSourceEntryType, FrontEndEmulator } from '@/shared/types';
/**
* Get emulators based on local games. Only the ones we probably need.

View file

@ -2,6 +2,7 @@ import { EmulatorDownloadInfoType, EmulatorPackageType, ScoopPackageSchema } fro
import { config, plugins } from "../../app";
import { getOrCached, getOrCachedGithubRelease } from "../../cache";
import path from "node:path";
import { EmulatorSourceEntryType, EmulatorSupport } from "@/shared/types";
export function findEmulatorPluginIntegration (name: string, validSources: (EmulatorSourceEntryType | undefined)[]): EmulatorSupport[]
{

View file

@ -1,14 +1,10 @@
import { EmulatorPackageSchema, EmulatorPackageType, GithubManifestSchema, StoreGameSchema } from "@/shared/constants";
import { CACHE_KEYS, getOrCached } from "../../cache";
import { EmulatorPackageSchema, EmulatorPackageType } from "@/shared/constants";
import { and, eq, or } from "drizzle-orm";
import { config, emulatorsDb } from '../../app';
import path from "node:path";
import fs from 'node:fs/promises';
import * as emulatorSchema from '@schema/emulators';
import { shuffleInPlace } from "@/bun/utils";
import { Glob } from "bun";
import { EmulatorSystem } from "@/shared/types";
export function getStoreRootFolder ()
{

View file

@ -13,6 +13,7 @@ import { getStoreFolder } from "./services/gamesService";
import { EmulatorDownloadJob } from "../jobs/emulator-download-job";
import { BiosDownloadJob } from "../jobs/bios-download-job";
import { findEmulatorPluginIntegration, getEmulatorPath } from "./services/emulatorsService";
import { EmulatorSourceEntryType, FrontEndEmulator, FrontEndGameTypeDetailed } from "@/shared/types";
export const store = new Elysia({ prefix: '/api/store' })
.get('/emulators', async ({ query }) =>

View file

@ -16,6 +16,7 @@ import ReloadPluginsJob from "./jobs/reload-plugins-job";
import { semver } from "bun";
import { getOrCachedGithubRelease } from "./cache";
import SelfUpdateJob from "./jobs/self-update-job";
import { DownloadsDrive } from "@/shared/types";
async function checkUpdate (force?: boolean)
{

View file

@ -1,3 +1,4 @@
import { JobStatus } from '@/shared/types';
import EventEmitter from 'node:events';
import z from 'zod';

19
src/bun/types/helpers.d.ts vendored Normal file
View file

@ -0,0 +1,19 @@
declare module '*.bat' {
const content: string;
export default content;
}
declare module '*.sh' {
const content: string;
export default content;
}
declare module '*.ini' {
const content: string;
export default content;
}
declare module '*.bin' {
const content: string;
export default content;
}

View file

@ -1,42 +0,0 @@
declare interface ObjectConstructor
{
/**
* Groups members of an iterable according to the return value of the passed callback.
* @param items An iterable.
* @param keySelector A callback which will be invoked for each item in items.
*/
groupBy<K extends PropertyKey, T> (
items: Iterable<T>,
keySelector: (item: T, index: number) => K,
): Partial<Record<K, T[]>>;
}
declare interface MapConstructor
{
/**
* Groups members of an iterable according to the return value of the passed callback.
* @param items An iterable.
* @param keySelector A callback which will be invoked for each item in items.
*/
groupBy<K, T> (
items: Iterable<T>,
keySelector: (item: T, index: number) => K,
): Map<K, T[]>;
}
declare interface AppEventMap
{
exitapp: [];
notification: [FrontendNotification];
focus: [];
}
declare module '*.bat' {
const content: string;
export default content;
}
declare module '*.sh' {
const content: string;
export default content;
}

View file

@ -1,8 +1,7 @@
import z from "zod";
import { GameflowHooks } from "../api/hooks/app";
import GameflowHooks from "../api/hooks/app";
import Conf from "conf";
import { $ZodRegistry } from "zod/v4/core";
import EventEmitter from "node:events";
export const PluginContextSchema = z.object({
hooks: z.instanceof(GameflowHooks)
@ -22,6 +21,7 @@ export const PluginDescriptionSchema = z.object({
icon: z.url().optional(),
keywords: z.array(z.string()).optional(),
category: z.string().default("other"),
main: z.string(),
canDisable: z.boolean().default(true).optional()
});

18
src/bun/types/types.ts Normal file
View file

@ -0,0 +1,18 @@
import { EmulatorDownloadInfoType, EmulatorPackageType } from "@/shared/constants";
import { FrontendNotification } from "@/shared/types";
export interface AppEventMap
{
exitapp: [];
notification: [FrontendNotification];
focus: [];
}
export interface EmulatorPostInstallContext
{
emulator: string;
emulatorPackage?: EmulatorPackageType;
path: string;
update: boolean;
info: EmulatorDownloadInfoType;
}

View file

@ -4,6 +4,7 @@ import { SettingsType } from '@/shared/constants';
import { config } from './api/app';
import fs from 'node:fs/promises';
import packageDef from '~/package.json';
import { KeysWithValueAssignableTo } from '@/shared/types';
export function checkRunning (pid: number)
{

View file

@ -5,6 +5,7 @@ import fs from 'node:fs/promises';
import { createWriteStream } from "node:fs";
import { config, jar } from "../api/app";
import { moveAllFiles } from "../utils";
import { DownloadFileEntry } from "@/shared/types";
export interface ProgressStats
{

View file

@ -35,18 +35,6 @@ interface BrowserResult
source: GetBrowserSource;
}
const PLATFORM_MAP: Record<string, string> = {
linux: "linux",
win32: "windows",
darwin: 'macos'
};
const ARCH_MAP: Record<string, Record<string, string>> = {
linux: { x64: "x86_64", arm64: "arm64" },
darwin: { x64: "x86_64", arm64: "arm64" },
win32: { x64: "x64", arm64: "arm64" },
};
/** The expected binary path per platform after extraction */
async function getBundledBinaryPath (outDir: string, version: string, platform: string, arch: string): Promise<string | undefined>
{