diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a116a79..66b81a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,25 +12,7 @@ on: - '!v*alpha*' jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 16.14.0 - - - name: Install dependencies - run: npm install - - - name: Run test - run: npm run test - publish-npm: - needs: test runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.husky/pre-commit b/.husky/pre-commit index 18de984..594cdf9 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -npm test \ No newline at end of file +npm lint \ No newline at end of file diff --git a/.xo-config.json b/.xo-config.json index 8324c3e..059074b 100644 --- a/.xo-config.json +++ b/.xo-config.json @@ -11,8 +11,11 @@ ], "rules": { "import/extensions": "off", - "unicorn/prefer-module": "off", - "@typescript-eslint/await-thenable": "off", + "no-await-in-loop": "off", + "import/no-anonymous-default-export": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/consistent-type-definitions": [ "error", "interface" diff --git a/src/helper/expection.ts b/src/helper/expection.ts index 8874aee..b00def6 100644 --- a/src/helper/expection.ts +++ b/src/helper/expection.ts @@ -26,6 +26,5 @@ export default function expection( } const providedMessage: string | undefined = typeof message === 'function' ? message() : message; - throw new NodeError(providedMessage || 'Unknown error', code); + throw new NodeError(providedMessage ?? 'Unknown error', code); } - diff --git a/src/helper/partial-right.ts b/src/helper/partial-right.ts index 0972f03..40bcc4c 100644 --- a/src/helper/partial-right.ts +++ b/src/helper/partial-right.ts @@ -1,17 +1,17 @@ /** * Creates a function that invokes `fn` with partially applied arguments from the right. * - * @param {Function} fn - The function to partially apply arguments to. - * @param {...any[]} args - The arguments to be partially applied from the right. + * @param {Function} function_ - The function to partially apply arguments to. + * @param {...any[]} arguments_ - The arguments to be partially applied from the right. * @returns {Function} - A new function with the partial arguments applied from the right. * @example * const greet = (greeting: string, name: string) => `${greeting}, ${name}`; * const greetJohn = partialRight(greet, 'John'); * console.log(greetJohn('Hello')); // Output: "Hello, John" */ -export default function partialRight any>( - fn: T, - ...args: Parameters +export default function partialRight any>( + function_: T, + ...arguments_: Parameters ): (...rest: any[]) => ReturnType { - return (...rest: any[]) => fn(...rest, ...args); + return (...rest: any[]) => function_(...rest, ...arguments_); } diff --git a/src/helper/pipe.ts b/src/helper/pipe.ts index 57d22a2..db95106 100644 --- a/src/helper/pipe.ts +++ b/src/helper/pipe.ts @@ -18,14 +18,13 @@ * * pipeline(5).then(result => console.log(result)); // Output: 10.5 */ -export default function pipe( - ...fns: Array<(input: any) => any | Promise> -): (input: T) => Promise { +export default function pipe(...fns: Array<(input: any) => any | Promise>): (input: T) => Promise { return async (input: T): Promise => { let result: any = input; - for (const fn of fns) { - result = await fn(result); // Awaiting each function in case it returns a promise + for (const function_ of fns) { + result = await function_(result); // Awaiting each function in case it returns a promise } + return result as R; }; } diff --git a/src/index.ts b/src/index.ts index e24a1b9..7388aec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,6 @@ import steamLibrary, { type SteamLibraryOption } from './steam-library'; import steamRoot from './steam-root'; import { pipe } from './helper/index.js'; -export type { SteamAppOption, SteamLibraryOption }; - /** * A function that retrieves the root path of the Steam installation. * @@ -32,14 +30,15 @@ export const getLibrary = pipe(steamRoot, steamLibra * @type {Function} * @returns {Promise} A promise that resolves to an array of `SteamAppOption` objects. */ -export const getApps = pipe( - steamRoot, - steamLibrary, - (apps: SteamLibraryOption[]) => apps.map(steamApp), +export const getApps = pipe(steamRoot, steamLibrary, (apps: SteamLibraryOption[]) => + apps.map((app) => steamApp(app)), ); export default { getLibrary, getApps, getRootPath, -} +}; + +export { type SteamAppOption } from './steam-app'; +export { type SteamLibraryOption } from './steam-library'; diff --git a/src/steam-app.ts b/src/steam-app.ts index 4f199cf..653e458 100644 --- a/src/steam-app.ts +++ b/src/steam-app.ts @@ -1,7 +1,6 @@ -import * as VDF from '@node-steam/vdf'; -import { readFileSync } from 'fs'; -import { existsSync } from 'node:fs'; +import { readFileSync, existsSync } from 'node:fs'; import { resolve } from 'node:path'; +import * as VDF from '@node-steam/vdf'; import { expection, partialRight } from './helper'; import type { SteamLibraryOption } from './steam-library'; @@ -48,15 +47,13 @@ interface SteamAppManifest { AppState: AppState; } -const remappingManifest = (appState: AppState, { id, library }: SteamLibraryOption) => ( - { - id: appState.appid, - name: appState.name, - installPath: appState.installdir ? resolve(library, 'steamapps/common', appState.installdir) : undefined, - modPath: resolve(library, 'steamapps/workshop/content', id), - language: appState.UserConfig?.language, - } -); +const remappingManifest = (appState: AppState, { id, library }: SteamLibraryOption) => ({ + id: appState.appid, + name: appState.name, + installPath: appState.installdir ? resolve(library, 'steamapps/common', appState.installdir) : undefined, + modPath: resolve(library, 'steamapps/workshop/content', id), + language: appState.UserConfig?.language, +}); export type SteamAppOption = ReturnType; @@ -66,10 +63,10 @@ export default function steamApp({ id, library }: SteamLibraryOption): SteamAppO customExpection(existsSync(manifestFile), `App ${id} not found in library ${library}`); - const content = readFileSync(manifestFile, 'utf-8'); + const content = readFileSync(manifestFile, 'utf8'); - const record: SteamAppManifest = VDF.parse(content); + const record = VDF.parse(content) as SteamAppManifest; customExpection(record.AppState, 'Invalid manifest file'); return remappingManifest(record.AppState, { id, library }); -} \ No newline at end of file +} diff --git a/src/steam-library.ts b/src/steam-library.ts index 46dd2cc..534550c 100644 --- a/src/steam-library.ts +++ b/src/steam-library.ts @@ -1,6 +1,6 @@ -import * as VDF from '@node-steam/vdf'; import { existsSync, readFileSync } from 'node:fs'; import { resolve } from 'node:path'; +import * as VDF from '@node-steam/vdf'; import { expection, partialRight } from './helper'; interface SteamLibrary { @@ -37,10 +37,10 @@ export default function steamLibrary(rootPath: string): SteamLibraryOption[] { customExpection(existsSync(libraryFile), 'Steam library file not found'); // Read the file content - const content = readFileSync(libraryFile, 'utf-8'); + const content = readFileSync(libraryFile, 'utf8'); // Parse the VDF content into a structured object - const record: SteamLibrary = VDF.parse(content); + const record = VDF.parse(content) as SteamLibrary; // Ensure the parsed content contains valid library folders customExpection(record.libraryfolders, 'Invalid library file'); @@ -49,10 +49,14 @@ export default function steamLibrary(rootPath: string): SteamLibraryOption[] { // Loop through the library folders and extract game IDs and paths for (const index in record.libraryfolders) { - const item = record.libraryfolders[index]; + if (Object.hasOwn(record.libraryfolders, index)) { + const item = record.libraryfolders[index]; - for (const gameId in item.apps) { - apps.push({ library: item.path, id: gameId }); + for (const gameId in item.apps) { + if (Object.hasOwn(item.apps, gameId)) { + apps.push({ library: item.path, id: gameId }); + } + } } } diff --git a/src/steam-root.ts b/src/steam-root.ts index b6693a4..203d03b 100644 --- a/src/steam-root.ts +++ b/src/steam-root.ts @@ -13,18 +13,18 @@ export default async function steamRoot(): Promise { return new Promise((resolve, reject) => { // Define the registry path and key name const regKey = new Registry({ - hive: Registry.HKCU, // HKEY_CURRENT_USER - key: registryKey, // Steam registry key + hive: Registry.HKCU, // HKEY_CURRENT_USER + key: registryKey, // Steam registry key }); // Read the "SteamPath" key from the registry regKey.get('SteamPath', function (error, item) { if (error) { - reject(new NodeError(`${error}`, 'EREGISTRY')); - } else if (!item.value) { - reject(new NodeError('Steam path is empty', 'EREGISTRY')); - } else { + reject(new NodeError(error.toString(), 'EREGISTRY')); + } else if (item.value) { resolve(item.value); + } else { + reject(new NodeError('Steam path is empty', 'EREGISTRY')); } }); });