chore: Fixed tests
This commit is contained in:
parent
9141fb35d4
commit
5593985884
13 changed files with 139 additions and 66 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -28,6 +28,7 @@ downloads
|
||||||
gameflow-deck.code-workspace
|
gameflow-deck.code-workspace
|
||||||
.env.local
|
.env.local
|
||||||
src/tests/mock-roms/db.sqlite
|
src/tests/mock-roms/db.sqlite
|
||||||
|
src/tests/mock-roms/store
|
||||||
src/tests/mock-config
|
src/tests/mock-config
|
||||||
bin
|
bin
|
||||||
.config/flatpak/repo
|
.config/flatpak/repo
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,13 @@ export async function cleanup ()
|
||||||
cleannedUp = true;
|
cleannedUp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Reset the cleanup flags. This is mainly used by tests since they run the same app. */
|
||||||
|
export async function resetCleanup ()
|
||||||
|
{
|
||||||
|
cleaningUp = false;
|
||||||
|
cleannedUp = false;
|
||||||
|
}
|
||||||
|
|
||||||
export async function reloadDatabase ()
|
export async function reloadDatabase ()
|
||||||
{
|
{
|
||||||
await ensureDir(config.get('downloadPath'));
|
await ensureDir(config.get('downloadPath'));
|
||||||
|
|
|
||||||
|
|
@ -454,18 +454,18 @@ export default new Elysia()
|
||||||
}, {
|
}, {
|
||||||
params: z.object({ id: z.string(), source: z.string() }),
|
params: z.object({ id: z.string(), source: z.string() }),
|
||||||
})
|
})
|
||||||
.post('/game/:source/:id/install', async ({ params: { id, source }, body: { downloadId } }) =>
|
.post('/game/:source/:id/install', async ({ params: { id, source }, body }) =>
|
||||||
{
|
{
|
||||||
if (!taskQueue.findJob(InstallJob.query({ source, id }), InstallJob))
|
if (!taskQueue.findJob(InstallJob.query({ source, id }), InstallJob))
|
||||||
{
|
{
|
||||||
return taskQueue.enqueue(InstallJob.query({ source, id }), new InstallJob(id, source, { downloadId }));
|
return taskQueue.enqueue(InstallJob.query({ source, id }), new InstallJob(id, source, body));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return status('Not Implemented');
|
return status('Not Implemented');
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
params: z.object({ id: z.string(), source: z.string() }),
|
params: z.object({ id: z.string(), source: z.string() }),
|
||||||
body: z.object({ downloadId: z.string().optional() }),
|
body: z.object({ downloadId: z.string().optional() }).optional(),
|
||||||
response: z.any()
|
response: z.any()
|
||||||
})
|
})
|
||||||
.delete('/game/:source/:id/install', async ({ params: { id, source } }) =>
|
.delete('/game/:source/:id/install', async ({ params: { id, source } }) =>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ import { runBunPackageCommand } from "../plugins/services";
|
||||||
import { PluginRegistry } from "@/shared/constants";
|
import { PluginRegistry } from "@/shared/constants";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import sdkPkg from '@simeonradivoev/gameflow-sdk/package.json';
|
import sdkPkg from '@simeonradivoev/gameflow-sdk/package.json';
|
||||||
|
import { IsPluginAllowed } from "@/bun/utils";
|
||||||
|
|
||||||
export default class UpdateStoreJob implements IJob<never, string>
|
export default class EnsureStore implements IJob<never, string>
|
||||||
{
|
{
|
||||||
static id = "update-store" as const;
|
static id = "update-store" as const;
|
||||||
static dataSchema = z.never();
|
static dataSchema = z.never();
|
||||||
|
|
@ -20,7 +21,7 @@ export default class UpdateStoreJob implements IJob<never, string>
|
||||||
this.storeVersion = process.env.STORE_VERSION ?? "^0.1.0";
|
this.storeVersion = process.env.STORE_VERSION ?? "^0.1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
async start (context: JobContext<UpdateStoreJob, never, string>)
|
async start (context: JobContext<EnsureStore, never, string>)
|
||||||
{
|
{
|
||||||
const storeFolder = getStoreRootFolder();
|
const storeFolder = getStoreRootFolder();
|
||||||
await ensureDir(storeFolder);
|
await ensureDir(storeFolder);
|
||||||
|
|
@ -32,6 +33,8 @@ export default class UpdateStoreJob implements IJob<never, string>
|
||||||
|
|
||||||
const storePackage = await Bun.file(path.join(storeFolder, "package.json")).json();
|
const storePackage = await Bun.file(path.join(storeFolder, "package.json")).json();
|
||||||
|
|
||||||
|
if (IsPluginAllowed(sdkPkg.name))
|
||||||
|
{
|
||||||
if (!storePackage.dependencies?.[sdkPkg.name] || storePackage.dependencies?.[sdkPkg.name] !== sdkPkg.version)
|
if (!storePackage.dependencies?.[sdkPkg.name] || storePackage.dependencies?.[sdkPkg.name] !== sdkPkg.version)
|
||||||
{
|
{
|
||||||
let response = await runBunPackageCommand(["add", `${sdkPkg.name}@${sdkPkg.version}`, "--registry", PluginRegistry, '--omit', 'peer']);
|
let response = await runBunPackageCommand(["add", `${sdkPkg.name}@${sdkPkg.version}`, "--registry", PluginRegistry, '--omit', 'peer']);
|
||||||
|
|
@ -44,6 +47,10 @@ export default class UpdateStoreJob implements IJob<never, string>
|
||||||
let response = await runBunPackageCommand(["add", '--exact', `${sdkPkg.name}@latest`, "--registry", PluginRegistry, '--omit', 'peer']);
|
let response = await runBunPackageCommand(["add", '--exact', `${sdkPkg.name}@latest`, "--registry", PluginRegistry, '--omit', 'peer']);
|
||||||
console.log(response);
|
console.log(response);
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
console.log("Ignoring SDK package");
|
||||||
|
}
|
||||||
|
|
||||||
if (process.env.CUSTOM_STORE_PATH) return;
|
if (process.env.CUSTOM_STORE_PATH) return;
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@ import z, { _ZodType } from "zod";
|
||||||
import { taskQueue } from "../app";
|
import { taskQueue } from "../app";
|
||||||
import { LoginJob } from "./login-job";
|
import { LoginJob } from "./login-job";
|
||||||
import TwitchLoginJob from "./twitch-login-job";
|
import TwitchLoginJob from "./twitch-login-job";
|
||||||
import UpdateStoreJob from "./update-store";
|
import EnsureStore from "./ensure-store";
|
||||||
import { EmulatorDownloadJob } from "./emulator-download-job";
|
import { EmulatorDownloadJob } from "./emulator-download-job";
|
||||||
import { getErrorMessage } from "@/bun/utils";
|
import { getErrorMessage } from "@/bun/utils";
|
||||||
import { BaseEvent, IJob } from "@simeonradivoev/gameflow-sdk/task-queue";
|
import { BaseEvent, IJob } from "@simeonradivoev/gameflow-sdk/task-queue";
|
||||||
|
|
@ -184,7 +184,7 @@ export const jobs = new Elysia({ prefix: '/api/jobs' })
|
||||||
.use(registerJob(LaunchGameJob))
|
.use(registerJob(LaunchGameJob))
|
||||||
.use(registerJob(LoginJob))
|
.use(registerJob(LoginJob))
|
||||||
.use(registerJob(TwitchLoginJob))
|
.use(registerJob(TwitchLoginJob))
|
||||||
.use(registerJob(UpdateStoreJob))
|
.use(registerJob(EnsureStore))
|
||||||
.use(registerJob(BiosDownloadJob))
|
.use(registerJob(BiosDownloadJob))
|
||||||
.use(registerJob(InstallJob))
|
.use(registerJob(InstallJob))
|
||||||
.use(registerJob(ReloadPluginsJob))
|
.use(registerJob(ReloadPluginsJob))
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ import { PluginLoadingContextType, PluginType } from "@simeonradivoev/gameflow-s
|
||||||
import desc from './package.json';
|
import desc from './package.json';
|
||||||
import path, { } from 'node:path';
|
import path, { } from 'node:path';
|
||||||
import { buildStoreFrontendEmulatorSystems, getAllStoreEmulatorPackages, getStoreEmulatorPackage, getStoreFolder } from "@/bun/api/store/services/gamesService";
|
import { buildStoreFrontendEmulatorSystems, getAllStoreEmulatorPackages, getStoreEmulatorPackage, getStoreFolder } from "@/bun/api/store/services/gamesService";
|
||||||
import { Glob, pathToFileURL, which } from "bun";
|
import { Glob, pathToFileURL, sleep, which } from "bun";
|
||||||
import { and, eq } from "drizzle-orm";
|
import { and, eq } from "drizzle-orm";
|
||||||
import * as emulatorSchema from '@schema/emulators';
|
import * as emulatorSchema from '@schema/emulators';
|
||||||
|
|
||||||
import { config, emulatorsDb, taskQueue } from "@/bun/api/app";
|
import { config, emulatorsDb, taskQueue } from "@/bun/api/app";
|
||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import { getSourceGameDetailed } from "@/bun/api/games/services/utils";
|
import { getSourceGameDetailed } from "@/bun/api/games/services/utils";
|
||||||
import UpdateStoreJob from "@/bun/api/jobs/update-store";
|
import EnsureStore from "@/bun/api/jobs/ensure-store";
|
||||||
import { getEmulatorDownload, getEmulatorPath } from "@/bun/api/store/services/emulatorsService";
|
import { getEmulatorDownload, getEmulatorPath } from "@/bun/api/store/services/emulatorsService";
|
||||||
import { buildFilters, buildLaunchCommand, buildSaves, convertStoreEmulatorToFrontend, convertStoreToFrontend, convertStoreToFrontendDetailed, getExistingStoreEmulatorDownload, getShuffledStoreGames, getStoreGame, getValidDownloads } from "./services";
|
import { buildFilters, buildLaunchCommand, buildSaves, convertStoreEmulatorToFrontend, convertStoreToFrontend, convertStoreToFrontendDetailed, getExistingStoreEmulatorDownload, getShuffledStoreGames, getStoreGame, getValidDownloads } from "./services";
|
||||||
import { DownloadInfo, FrontEndEmulatorDetailed, FrontEndGameTypeWithIds } from "@simeonradivoev/gameflow-sdk/shared";
|
import { DownloadInfo, FrontEndEmulatorDetailed, FrontEndGameTypeWithIds } from "@simeonradivoev/gameflow-sdk/shared";
|
||||||
|
|
@ -20,7 +20,7 @@ import StreamZip from "node-stream-zip";
|
||||||
import { path7za } from "7zip-bin";
|
import { path7za } from "7zip-bin";
|
||||||
import Seven from 'node-7z';
|
import Seven from 'node-7z';
|
||||||
|
|
||||||
export default class RommIntegration implements PluginType
|
export default class StoreIntegration implements PluginType
|
||||||
{
|
{
|
||||||
eventsNames = [{ id: 'updateStore', title: "Update Store", description: "Update the Store Manifest", action: "Update" }];
|
eventsNames = [{ id: 'updateStore', title: "Update Store", description: "Update the Store Manifest", action: "Update" }];
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ export default class RommIntegration implements PluginType
|
||||||
switch (e)
|
switch (e)
|
||||||
{
|
{
|
||||||
case 'updateStore':
|
case 'updateStore':
|
||||||
await taskQueue.enqueue(UpdateStoreJob.id, new UpdateStoreJob());
|
await taskQueue.enqueue(EnsureStore.id, new EnsureStore());
|
||||||
return { reload: true };
|
return { reload: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ export default class RommIntegration implements PluginType
|
||||||
{
|
{
|
||||||
console.log("Store Directory is ", getStoreFolder());
|
console.log("Store Directory is ", getStoreFolder());
|
||||||
ctx.setProgress(0, "Updating Store");
|
ctx.setProgress(0, "Updating Store");
|
||||||
await taskQueue.enqueue(UpdateStoreJob.id, new UpdateStoreJob());
|
await taskQueue.enqueue(EnsureStore.id, new EnsureStore());
|
||||||
}
|
}
|
||||||
|
|
||||||
async load (ctx: PluginLoadingContextType)
|
async load (ctx: PluginLoadingContextType)
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,12 @@ import rclone from './builtin/other/com.simeonradivoev.gameflow.rclone/package.j
|
||||||
import { PluginDescriptionSchema, PluginDescriptionType, PluginSchema } from "@simeonradivoev/gameflow-sdk";
|
import { PluginDescriptionSchema, PluginDescriptionType, PluginSchema } from "@simeonradivoev/gameflow-sdk";
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { getStoreRootFolder } from "../store/services/gamesService";
|
import { getStoreRootFolder } from "../store/services/gamesService";
|
||||||
import { getUpdates } from "./services";
|
import { getUpdates, runBunPackageCommand } from "./services";
|
||||||
import { PluginSourceType } from "@simeonradivoev/gameflow-sdk/shared";
|
import { PluginSourceType } from "@simeonradivoev/gameflow-sdk/shared";
|
||||||
import { taskQueue } from "../app";
|
import { taskQueue } from "../app";
|
||||||
import UpdateStoreJob from "../jobs/update-store";
|
import EnsureStore from "../jobs/ensure-store";
|
||||||
|
import { PluginRegistry } from "@/shared/constants";
|
||||||
|
import { IsPluginAllowed } from "@/bun/utils";
|
||||||
|
|
||||||
type PluginEntry = PluginDescriptionType & { load: () => Promise<any>; };
|
type PluginEntry = PluginDescriptionType & { load: () => Promise<any>; };
|
||||||
|
|
||||||
|
|
@ -58,15 +60,9 @@ export async function unregisterPlugin (id: string, pluginManager: PluginManager
|
||||||
|
|
||||||
export async function registerPlugin (plugin: PluginEntry, source: PluginSourceType, pluginManager: PluginManager)
|
export async function registerPlugin (plugin: PluginEntry, source: PluginSourceType, pluginManager: PluginManager)
|
||||||
{
|
{
|
||||||
if (process.env.PLUGIN_WHITELIST && !process.env.PLUGIN_WHITELIST.includes(plugin.name))
|
if (!IsPluginAllowed(plugin.name))
|
||||||
{
|
{
|
||||||
console.log("Skipping", plugin.name, "missing in whitelist");
|
console.log("Skipping", plugin.name, "plugin not allowed");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.PLUGIN_BLACKLIST && process.env.PLUGIN_BLACKLIST.includes(plugin.name))
|
|
||||||
{
|
|
||||||
console.log("Skipping", plugin.name, "found in whitelist");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,11 +97,13 @@ export default async function register (pluginManager: PluginManager)
|
||||||
|
|
||||||
await Promise.all(plugins.map(p => registerPlugin(p, 'builtin', pluginManager)));
|
await Promise.all(plugins.map(p => registerPlugin(p, 'builtin', pluginManager)));
|
||||||
|
|
||||||
|
if (IsPluginAllowed('@simeonradivoev/gameflow-store'))
|
||||||
|
{
|
||||||
const storePackageFilePath = path.join(getStoreRootFolder(), 'package.json');
|
const storePackageFilePath = path.join(getStoreRootFolder(), 'package.json');
|
||||||
if (!await Bun.file(storePackageFilePath).exists())
|
if (!await Bun.file(storePackageFilePath).exists())
|
||||||
{
|
{
|
||||||
console.log("Store is missing. Updating it.");
|
console.log("Store is missing. Updating it.");
|
||||||
await taskQueue.enqueue(UpdateStoreJob.id, new UpdateStoreJob());
|
await taskQueue.enqueue(EnsureStore.id, new EnsureStore());
|
||||||
console.log("Store Updated");
|
console.log("Store Updated");
|
||||||
}
|
}
|
||||||
const storePackage = await Bun.file(storePackageFilePath).json();
|
const storePackage = await Bun.file(storePackageFilePath).json();
|
||||||
|
|
@ -124,16 +122,27 @@ export default async function register (pluginManager: PluginManager)
|
||||||
|
|
||||||
if (outdated)
|
if (outdated)
|
||||||
{
|
{
|
||||||
validPlugins.forEach(p =>
|
for await (const plugin of validPlugins)
|
||||||
{
|
{
|
||||||
const newVersion = outdated[p.name];
|
const newVersion = outdated[plugin.name];
|
||||||
if (newVersion)
|
if (newVersion)
|
||||||
{
|
{
|
||||||
console.log("Plugin", p.name, "has update", p.version, "=>", newVersion);
|
console.log("Plugin", plugin.name, "has update", plugin.version, "=>", newVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin.autoUpdate)
|
||||||
|
{
|
||||||
|
console.log("Auto Updating Plugin", plugin.name);
|
||||||
|
let response = await runBunPackageCommand(["add", `${plugin.name}@${newVersion}`, "--registry", PluginRegistry, '--omit', 'peer']);
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(validPlugins.map(p => registerPlugin(p, 'store', pluginManager)));
|
await Promise.all(validPlugins.map(p => registerPlugin(p, 'store', pluginManager)));
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
console.log('Skipping Store Packages');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ import os from 'node:os';
|
||||||
import { getStoreRootFolder } from '../store/services/gamesService';
|
import { getStoreRootFolder } from '../store/services/gamesService';
|
||||||
import { PluginDescriptionType } from '@simeonradivoev/gameflow-sdk';
|
import { PluginDescriptionType } from '@simeonradivoev/gameflow-sdk';
|
||||||
import { run } from 'npm-check-updates';
|
import { run } from 'npm-check-updates';
|
||||||
|
import { existsSync } from 'node:fs';
|
||||||
|
|
||||||
export function canDisable (description: PluginDescriptionType)
|
export function canDisable (description: PluginDescriptionType)
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +16,7 @@ export function canDisable (description: PluginDescriptionType)
|
||||||
|
|
||||||
export async function getUpdates ()
|
export async function getUpdates ()
|
||||||
{
|
{
|
||||||
|
if (!existsSync(getStoreRootFolder())) return {};
|
||||||
const updated = await run({ packageManager: 'bun', peer: true, cwd: getStoreRootFolder(), jsonUpgraded: true, reject: ['@simeonradivoev/gameflow-sdk'] });
|
const updated = await run({ packageManager: 'bun', peer: true, cwd: getStoreRootFolder(), jsonUpgraded: true, reject: ['@simeonradivoev/gameflow-sdk'] });
|
||||||
return updated as Record<string, string>;
|
return updated as Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,16 +188,16 @@ export const store = new Elysia({ prefix: '/api/store' })
|
||||||
emulator.integrations = integrations;
|
emulator.integrations = integrations;
|
||||||
return emulator;
|
return emulator;
|
||||||
}, { params: z.object({ id: z.string() }) })
|
}, { params: z.object({ id: z.string() }) })
|
||||||
.post('/install/emulator/:id/:source', async ({ params: { source, id }, body: { isUpdate } }) =>
|
.post('/install/emulator/:id/:source', async ({ params: { source, id }, body }) =>
|
||||||
{
|
{
|
||||||
if (taskQueue.hasActiveOfType(EmulatorDownloadJob))
|
if (taskQueue.hasActiveOfType(EmulatorDownloadJob))
|
||||||
{
|
{
|
||||||
return status("Conflict", "Installation already running");
|
return status("Conflict", "Installation already running");
|
||||||
}
|
}
|
||||||
const job = new EmulatorDownloadJob(id, source, { isUpdate });
|
const job = new EmulatorDownloadJob(id, source, body);
|
||||||
return taskQueue.enqueue(EmulatorDownloadJob.id, job);
|
return taskQueue.enqueue(EmulatorDownloadJob.id, job);
|
||||||
}, {
|
}, {
|
||||||
body: z.object({ isUpdate: z.boolean().optional() })
|
body: z.object({ isUpdate: z.boolean().optional() }).optional()
|
||||||
})
|
})
|
||||||
.delete('/emulator/:id', async ({ params: { id } }) =>
|
.delete('/emulator/:id', async ({ params: { id } }) =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -186,3 +186,18 @@ export function isArchive (path: string)
|
||||||
{
|
{
|
||||||
return archiveRegex.test(path);
|
return archiveRegex.test(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IsPluginAllowed (id: string)
|
||||||
|
{
|
||||||
|
if (process.env.PLUGIN_WHITELIST && !process.env.PLUGIN_WHITELIST.includes(id))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.PLUGIN_BLACKLIST && process.env.PLUGIN_BLACKLIST.includes(id))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -41,7 +41,8 @@ export const PluginDescriptionSchema = z.object({
|
||||||
peerDependencies: z.record(z.string(), z.string()).optional(),
|
peerDependencies: z.record(z.string(), z.string()).optional(),
|
||||||
category: z.string().default("other"),
|
category: z.string().default("other"),
|
||||||
main: z.string().describe("The main entry. It must export a default class implementing PluginType"),
|
main: z.string().describe("The main entry. It must export a default class implementing PluginType"),
|
||||||
canDisable: z.boolean().default(true).optional().describe("Can the plugin be disabled or enabled by the user")
|
canDisable: z.boolean().default(true).optional().describe("Can the plugin be disabled or enabled by the user"),
|
||||||
|
autoUpdate: z.boolean().optional().describe("Should the plugin auto update to latest version")
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PluginSchema = z.object({
|
export const PluginSchema = z.object({
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,11 @@ export class TaskQueue
|
||||||
return this.activeQueue.length > 0;
|
return this.activeQueue.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public hasQueued ()
|
||||||
|
{
|
||||||
|
return this.queue && this.queue.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public hasActiveOfType (type: any)
|
public hasActiveOfType (type: any)
|
||||||
{
|
{
|
||||||
for (const entry of this.activeQueue)
|
for (const entry of this.activeQueue)
|
||||||
|
|
@ -109,6 +114,30 @@ export class TaskQueue
|
||||||
return job?.promise.promise ?? Promise.resolve();
|
return job?.promise.promise ?? Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public waitForAll ()
|
||||||
|
{
|
||||||
|
return new Promise((resolve) =>
|
||||||
|
{
|
||||||
|
if (!this.hasActive())
|
||||||
|
{
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEnded = () =>
|
||||||
|
{
|
||||||
|
if (!this.hasActive() && !this.hasQueued())
|
||||||
|
{
|
||||||
|
resolve(true);
|
||||||
|
this.events?.removeListener('ended', handleEnded);
|
||||||
|
this.events?.removeListener('abort', handleEnded);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.events?.on('ended', handleEnded);
|
||||||
|
this.events?.on('abort', handleEnded);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public cancelJob (id: string)
|
public cancelJob (id: string)
|
||||||
{
|
{
|
||||||
const job = this.queue?.find(j => j.id === id)
|
const job = this.queue?.find(j => j.id === id)
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
import { beforeAll, beforeEach, afterEach } from 'bun:test';
|
import { beforeAll, beforeEach, afterEach } from 'bun:test';
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
import * as app from '@/bun/api/app';
|
import * as app from '@/bun/api/app';
|
||||||
import { remove } from 'fs-extra';
|
import { ensureDir, remove } from 'fs-extra';
|
||||||
|
|
||||||
export async function LoadApp ()
|
export async function LoadApp ()
|
||||||
{
|
{
|
||||||
console.log("Loading App");
|
console.log("Loading App");
|
||||||
await app.load();
|
await app.load();
|
||||||
|
await app.taskQueue.waitForAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function CleanupApp ()
|
export async function CleanupApp ()
|
||||||
{
|
{
|
||||||
console.log("Cleaning Up App");
|
console.log("Cleaning Up App");
|
||||||
await app.cleanup();
|
await app.cleanup();
|
||||||
|
await app.resetCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(async () =>
|
beforeAll(async () =>
|
||||||
|
|
@ -20,7 +22,7 @@ beforeAll(async () =>
|
||||||
process.env.CUSTOM_STORE_PATH = resolve('./src/tests/mock-store');
|
process.env.CUSTOM_STORE_PATH = resolve('./src/tests/mock-store');
|
||||||
process.env.CONFIG_CWD = resolve('./src/tests/mock-config');
|
process.env.CONFIG_CWD = resolve('./src/tests/mock-config');
|
||||||
process.env.DEFAULT_DOWNLOAD_PATH = resolve('./src/tests/mock-roms');
|
process.env.DEFAULT_DOWNLOAD_PATH = resolve('./src/tests/mock-roms');
|
||||||
process.env.PLUGIN_BLACKLIST = 'com.simeonradivoev.gameflow.rclone';
|
process.env.PLUGIN_BLACKLIST = 'com.simeonradivoev.gameflow.rclone,@simeonradivoev/gameflow-store,com.simeonradivoev.gameflow.romm,com.simeonradivoev.gameflow.igdb,@simeonradivoev/gameflow-sdk';
|
||||||
});
|
});
|
||||||
|
|
||||||
async function FileCleanup ()
|
async function FileCleanup ()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue