ESLint update

This commit is contained in:
Kir_Antipov 2023-05-18 17:33:21 +00:00
parent b88779a92d
commit dba28c84f8
56 changed files with 465 additions and 163 deletions

279
.eslintrc
View file

@ -1,41 +1,240 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"env": {
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"arrow-body-style": ["error", "as-needed"],
"complexity": ["warn", { "max": 50 }],
"curly": ["error", "multi-line", "consistent"],
"eqeqeq": ["error", "smart"],
"no-constant-condition": ["error", { "checkLoops": false }],
"no-empty": ["error", { "allowEmptyCatch": true }],
"no-lonely-if": "error",
"no-var": "error",
"object-shorthand": "error",
"one-var": ["error", { "var": "never", "let": "never" }],
"prefer-arrow-callback": "error",
"prefer-const": ["error", { "destructuring": "all" }],
"prefer-object-spread": "error",
"prefer-rest-params": "warn",
"prefer-spread": "warn",
"quote-props": ["error", "consistent-as-needed"],
"quotes": "error",
"spaced-comment": ["error", "always", { "markers": ["/"] }],
"yoda": ["error", "never", { "exceptRange": true }],
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }],
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}]
}
}
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"env": {
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"array-callback-return": "error",
"no-constant-binary-expression": "error",
"no-constant-condition": ["error", { "checkLoops": false }],
"no-constructor-return": "error",
"no-duplicate-imports": "error",
"no-new-native-nonconstructor": "error",
"no-promise-executor-return": "error",
"no-self-compare": "error",
"no-template-curly-in-string": "warn",
"no-unmodified-loop-condition": "warn",
"no-unreachable-loop": "warn",
"no-unused-private-class-members": "error",
"@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}],
"no-use-before-define": "off",
"require-atomic-updates": "off",
"accessor-pairs": "error",
"arrow-body-style": "off",
"block-scoped-var": "error",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "off",
"complexity": ["error", 32],
"consistent-return": "error",
"consistent-this": "error",
"curly": "error",
"default-case": "error",
"default-case-last": "error",
"default-param-last": "error",
"dot-notation": "off",
"eqeqeq": "error",
"func-name-matching": "off",
"func-names": "off",
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
"grouped-accessor-pairs": "error",
"guard-for-in": "error",
"id-denylist": "off",
"id-length": "off",
"id-match": "off",
"init-declarations": "off",
"logical-assignment-operators": "error",
"max-classes-per-file": ["error", 2],
"max-depth": "error",
"max-lines": "off",
"max-lines-per-function": "off",
"max-nested-callbacks": "error",
"max-params": ["error", 6],
"max-statements": "off",
"multiline-comment-style": ["error", "separate-lines"],
"new-cap": ["error", { "capIsNewExceptionPattern": "[^\\p{Ll}]*$" }],
"no-alert": "error",
"no-array-constructor": "error",
"no-bitwise": "off",
"no-caller": "error",
"no-case-declarations": "off",
"no-confusing-arrow": "off",
"no-console": "error",
"no-continue": "off",
"no-div-regex": "error",
"no-else-return": "error",
"no-empty": "error",
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }],
"no-empty-static-block": "error",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-floating-decimal": "error",
"no-implicit-coercion": "off",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "error",
"no-invalid-this": "error",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "error",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-multi-assign": "error",
"no-multi-str": "error",
"no-negated-condition": "error",
"no-nested-ternary": "off",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-plusplus": "off",
"no-proto": "error",
"no-restricted-exports": "off",
"no-restricted-globals": "off",
"no-restricted-imports": ["error", {
"name": "node-fetch",
"message": "Please use `import { fetch } from \"@/utils/net\";` instead."
}],
"no-restricted-properties": "off",
"no-restricted-syntax": "off",
"no-return-assign": "error",
"no-return-await": "off",
"no-script-url": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-ternary": "off",
"no-throw-literal": "error",
"no-undef-init": "off",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unneeded-ternary": "error",
"no-unused-expressions": "error",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "off",
"no-useless-rename": "error",
"no-useless-return": "error",
"no-var": "error",
"no-void": "error",
"no-warning-comments": "error",
"object-shorthand": "error",
"one-var": ["error", "never"],
"one-var-declaration-per-line": "error",
"operator-assignment": "error",
"prefer-arrow-callback": "error",
"prefer-const": ["error", { "destructuring": "all" }],
"prefer-destructuring": "off",
"prefer-exponentiation-operator": "error",
"prefer-named-capture-group": "off",
"prefer-numeric-literals": "error",
"prefer-object-has-own": "error",
"prefer-object-spread": "error",
"prefer-promise-reject-errors": "error",
"prefer-regex-literals": "off",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
"quote-props": ["error", "consistent-as-needed"],
"radix": "off",
"require-await": "error",
"require-unicode-regexp": "off",
"sort-imports": "off",
"sort-keys": "off",
"sort-var": "off",
"spaced-comment": "error",
"strict": ["error", "never"],
"symbol-description": "error",
"vars-on-top": "error",
"yoda": "error",
"array-bracket-newline": "off",
"array-bracket-spacing": "error",
"array-element-newline": "off",
"arrow-parens": ["error", "as-needed"],
"arrow-spacing": "error",
"block-spacing": "error",
"brace-style": "error",
"comma-dangle": ["error", "always-multiline"],
"comma-spacing": "error",
"comma-style": "error",
"computed-property-spacing": "error",
"dot-location": ["error", "property"],
"eol-last": "error",
"func-call-spacing": "error",
"function-call-argument-newline": "off",
"function-paren-newline": "off",
"generator-star-spacing": ["error", { "before": false, "after": true, "method": "neither" }],
"implicit-arrow-linebreak": "off",
"indent": "off",
"jsx-quotes": "error",
"key-spacing": "error",
"keyword-spacing": "error",
"line-comment-position": "error",
"linebreak-style": ["error", "windows"],
"@typescript-eslint/lines-around-comment": ["error", {
"allowClassStart": true,
"allowInterfaceStart": true,
"allowTypeStart": true,
"allowEnumStart": true,
"allowModuleStart": true,
"allowBlockStart": true,
"allowObjectStart": true,
"allowArrayStart": true
}],
"lines-between-class-members": "error",
"max-len": "off",
"max-statements-per-line": "error",
"multiline-ternary": "off",
"new-parens": "error",
"newline-per-chained-call": "off",
"no-extra-parens": "off",
"no-multi-spaces": "error",
"no-multiple-empty-lines": "off",
"no-tabs": "error",
"no-trailing-spaces": "error",
"no-whitespace-before-property": "error",
"nonblock-statement-body-position": "error",
"object-curly-newline": "off",
"object-curly-spacing": ["error", "always"],
"object-property-newline": "off",
"operator-linebreak": "off",
"padded-blocks": "off",
"padding-line-between-statements": "off",
"quotes": "error",
"rest-spread-spacing": "error",
"semi": "error",
"semi-spacing": "error",
"semi-style": "error",
"space-before-blocks": "error",
"space-before-function-paren": ["error", { "anonymous": "never", "named": "never", "asyncArrow": "always" }],
"space-in-parens": "error",
"space-infix-ops": "error",
"space-unary-ops": "error",
"switch-colon-spacing": "error",
"template-curly-spacing": "error",
"template-tag-spacing": "error",
"unicode-bom": "error",
"wrap-iife": ["error", "inside"],
"wrap-regex": "off",
"yield-star-spacing": "error"
}
}

View file

@ -8,7 +8,7 @@
"generate": "ncc run scripts/generate.ts -t",
"prebuild": "npm run generate",
"build": "ncc build -s --license license.txt",
"test:lint": "eslint src/**/*.ts && eslint test/**/*.ts",
"test:lint": "eslint \"@(src|scripts)/**/*.ts\" && eslint --rule \"no-invalid-this: off\" tests/**/*.ts",
"test:unit": "jest --testPathPattern=unit --watchAll=false",
"test:integration": "jest --testPathPattern=integration",
"test": "npm run test:lint && npm run test:unit && npm run test:integration"

View file

@ -16,29 +16,64 @@ import { FileNotFoundError } from "@/utils/errors";
import { TypeScriptDocument } from "@/utils/typescript";
import { basename } from "node:path";
// Configure file paths
const ACTION_METADATA_TEMPLATE_FILE = "./action.template.yml"; // Path to the action metadata template file
const ACTION_METADATA_FILE = "./action.yml"; // Path to the processed action metadata file
const ACTION_METADATA_TYPESCRIPT_DEFINITION_FILE = "./src/action.ts"; // Path to the output TypeScript definition file for action metadata
const DYNAMIC_MODULE_LOADER_FILE = "./src/utils/reflection/module-loader.g.ts"; // Path to the output dynamic module loader TypeScript file
/**
* Path to the action metadata template file.
*/
const ACTION_METADATA_TEMPLATE_FILE = "./action.template.yml";
// Configure processing options
/**
* Path to the processed action metadata file.
*/
const ACTION_METADATA_FILE = "./action.yml";
/**
* Path to the output TypeScript definition file for action metadata.
*/
const ACTION_METADATA_TYPESCRIPT_DEFINITION_FILE = "./src/action.ts";
/**
* Path to the output dynamic module loader TypeScript file.
*/
const DYNAMIC_MODULE_LOADER_FILE = "./src/utils/reflection/module-loader.g.ts";
/**
* Processing options.
*/
const OPTIONS: PrebuildOptions = {
sourceFileName: basename(ACTION_METADATA_TEMPLATE_FILE), // The name of the source file everything else is generated from
encoding: "utf8", // The encoding used for reading and writing files
// The name of the source file everything else is generated from.
sourceFileName: basename(ACTION_METADATA_TEMPLATE_FILE),
disableESLint: true, // Disable ESLint in the generated TypeScript files
generateAutoGeneratedWarningMessage: true, // Add a warning message about auto-generated files
removeTemplateOnlyFields: true, // Remove fields that are only used in the template from the generated files
// The encoding used for reading and writing files.
encoding: "utf8",
rootPath: "@/", // The root path for module imports
pathParser: SPLIT_BY_WORDS_AND_GROUP_ACTION_PARAMETER_PATH_PARSER, // The path parser used for action parameter paths
newline: WINDOWS_NEWLINE, // The newline character(s) to use in the generated files
tabSize: 4, // The number of spaces for indentation in the generated files
lineWidth: 80, // The maximum line width for the generated files
// Disable ESLint in the generated TypeScript files.
disableESLint: true,
// Add a warning message about auto-generated files
generateAutoGeneratedWarningMessage: true,
// Remove fields that are only used in the template from the generated files.
removeTemplateOnlyFields: true,
// // The root path for module imports.
rootPath: "@/",
// The path parser used for action parameter paths.
pathParser: SPLIT_BY_WORDS_AND_GROUP_ACTION_PARAMETER_PATH_PARSER,
// The newline character(s) to use in the generated files.
newline: WINDOWS_NEWLINE,
// The number of spaces for indentation in the generated files.
tabSize: 4,
// The maximum line width for the generated files.
lineWidth: 80,
};
// Processing options' type
/**
* Processing options' type.
*/
type PrebuildOptions = Exclude<
& Parameters<typeof processActionMetadataTemplateFile>[2]
& Parameters<typeof parseActionMetadataFromFile>[1]

View file

@ -1,4 +1,4 @@
// TODO: Drop support for the legacy format completely.
// _ TODO: Drop support for the legacy format completely.
import { FabricDependencyType } from "@/loaders/fabric/fabric-dependency-type";
import { deprecate } from "node:util";

View file

@ -104,7 +104,7 @@ export function parseDependency(dependency: string): Dependency | undefined {
/**
* A regex pattern for matching formatted dependency strings.
*/
const DEPENDENCY_REGEX = /^\s*(?<id>[^@{(#]+)(@(?<versionRange>[^@{(#]*))?(?:\((?<type>[^@{(#]*)\))?(?<aliases>(?:\{[^:=]+(?:=|:)[^}]*\})+)?(?<ignore>#\(ignore(?::(?<ignoredPlatforms>[^\)]*))?\))?\s*$/;
const DEPENDENCY_REGEX = /^\s*(?<id>[^@{(#]+)(@(?<versionRange>[^@{(#]*))?(?:\((?<type>[^@{(#]*)\))?(?<aliases>(?:\{[^:=]+(?:=|:)[^}]*\})+)?(?<ignore>#\(ignore(?::(?<ignoredPlatforms>[^)]*))?\))?\s*$/;
/**
* A regex pattern for matching dependency aliases in dependency strings.

View file

@ -3,7 +3,7 @@ import { stringEquals } from "@/utils/string-utils";
import { deprecate } from "node:util";
import { GameVersion } from "./game-version";
// TODO: Remove deprecated stuff in v4.0
// _ TODO: Remove deprecated stuff in v4.0
/**
* Represents a game version filter.

View file

@ -1,3 +1,5 @@
/* eslint-disable no-cond-assign */
import { asArrayLike, isIterable } from "@/utils/collections";
import { VersionRange, parseVersionRange } from "@/utils/versioning";
import { MinecraftVersion, MinecraftVersionManifestEntry } from "./minecraft-version";

View file

@ -80,10 +80,10 @@ export function toFabricDependencyArray(list: FabricDependencyList, type: Fabric
}
/**
* Converts {@link FabricDependency} to a {@link Dependency} object.
*
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
*/
* Converts {@link FabricDependency} to a {@link Dependency} object.
*
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
*/
export function normalizeFabricDependency(dependency: FabricDependency): Dependency | undefined {
return createDependency({
id: dependency?.id,

View file

@ -7,7 +7,7 @@ import { PartialRecord } from "@/utils/types";
import { deprecate } from "node:util";
import { RawFabricMetadata } from "./raw-fabric-metadata";
// TODO: Remove the deprecated stuff in v4.0.
// _ TODO: Remove the deprecated stuff in v4.0.
/**
* Custom payload for Fabric metadata.

View file

@ -172,7 +172,7 @@ export interface RawFabricMetadata {
*/
[ACTION_NAME]?: FabricMetadataCustomPayload;
// TODO: Remove this field in v4.0.
// _ TODO: Remove this field in v4.0.
/**
* Custom `ModManager` payload.
*

View file

@ -8,7 +8,7 @@ import { deprecate } from "node:util";
import { ForgeEnvironmentType } from "./forge-environment-type";
import { RawForgeMetadata } from "./raw-forge-metadata";
// TODO: Remove the deprecated stuff in v4.0.
// _ TODO: Remove the deprecated stuff in v4.0.
/**
* A dependency configuration for a Forge mod.
@ -123,10 +123,10 @@ export function getForgeDependencies(metadata: RawForgeMetadata): ForgeDependenc
}
/**
* Converts {@link FabricDependency} to a {@link Dependency} object.
*
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
*/
* Converts {@link FabricDependency} to a {@link Dependency} object.
*
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
*/
export function normalizeForgeDependency(dependency: ForgeDependency): Dependency | undefined {
const payload = getForgeDependencyCustomPayload(dependency);

View file

@ -7,7 +7,7 @@ import { deprecate } from "node:util";
import { RawForgeMetadata } from "./raw-forge-metadata";
import { asString } from "@/utils/string-utils";
// TODO: Remove the deprecated stuff in v4.0.
// _ TODO: Remove the deprecated stuff in v4.0.
/**
* Custom payload for Forge metadata.

View file

@ -3,7 +3,7 @@ import { ForgeDependency } from "./forge-dependency";
import { ForgeMod } from "./forge-mod";
import { ForgeMetadataCustomPayload } from "./forge-metadata-custom-payload";
// TODO: Remove the deprecated stuff in v4.0.
// _ TODO: Remove the deprecated stuff in v4.0.
/**
* The metadata file for a Forge mod.

View file

@ -130,10 +130,10 @@ function mapQuiltDependencies(dependencies: (string | QuiltDependency)[], custom
}
/**
* Converts {@link QuiltDependency} to a {@link Dependency} object.
*
* @returns A Dependency object representing the given Quilt dependency.
*/
* Converts {@link QuiltDependency} to a {@link Dependency} object.
*
* @returns A Dependency object representing the given Quilt dependency.
*/
export function normalizeQuiltDependency(dependency: QuiltDependency): Dependency {
const payload = getQuiltDependencyCustomPayload(dependency);

View file

@ -7,7 +7,7 @@ import { deprecate } from "node:util";
import { RawQuiltMetadata } from "./raw-quilt-metadata";
import { asString } from "@/utils/string-utils";
// TODO: Remove the deprecated stuff in v4.0.
// _ TODO: Remove the deprecated stuff in v4.0.
/**
* Custom payload for Quilt metadata.

View file

@ -1,6 +1,7 @@
import { ZippedTextLoaderMetadataReader } from "@/loaders/zipped-loader-metadata-reader";
import { QuiltMetadata } from "./quilt-metadata";
import { QUILT_MOD_JSON, RawQuiltMetadata } from "./raw-quilt-metadata";
/**
* A metadata reader that is able to read Quilt mod metadata from a zipped file.
*/

View file

@ -6,7 +6,7 @@ import { QuiltLicense } from "./quilt-license";
import { QuiltPlugin } from "./quilt-plugin";
import { QuiltMetadataCustomPayload } from "./quilt-metadata-custom-payload";
// TODO: Remove the deprecated stuff in v4.0.
// _ TODO: Remove the deprecated stuff in v4.0.
/**
* The metadata file for a Quilt mod.

View file

@ -17,7 +17,7 @@ export const CURSEFORGE_ETERNAL_API_URL = `https://api.curseforge.com/v${CURSEFO
*
* Trust me on this one.
*/
const DEFINITELY_NOT_AN_API_KEY = SecureString.from(Buffer.from([36,50,97,36,49,48,36,81,73,47,121,101,83,110,106,105,69,90,72,90,109,70,108,109,105,74,86,73,46,50,120,109,87,89,108,80,98,107,65,88,87,56,114,81,46,120,77,54,53,118,107,116,65,115,115,97,74,112,109,105])).unwrap();
const DEFINITELY_NOT_AN_API_KEY = SecureString.from(Buffer.from([36, 50, 97, 36, 49, 48, 36, 81, 73, 47, 121, 101, 83, 110, 106, 105, 69, 90, 72, 90, 109, 70, 108, 109, 105, 74, 86, 73, 46, 50, 120, 109, 87, 89, 108, 80, 98, 107, 65, 88, 87, 56, 114, 81, 46, 120, 77, 54, 53, 118, 107, 116, 65, 115, 115, 97, 74, 112, 109, 105])).unwrap();
/**
* Describes the configuration options for the CurseForge Eternal API client.
@ -75,12 +75,12 @@ export class CurseForgeEternalApiClient {
* @returns The project, or `undefined` if not found.
*/
async getProject(idOrSlug: number | string): Promise<CurseForgeProject | undefined> {
if (isCurseForgeProjectId(idOrSlug)) {
const response = await this._fetch(`/mods/${idOrSlug}`);
return await response.json<{ data: CurseForgeProject }>().then(x => x?.data) ?? undefined;
} else {
if (!isCurseForgeProjectId(idOrSlug)) {
const response = await this._fetch("/mods/search", HttpRequest.get().with({ gameId: 432, slug: idOrSlug }));
return await response.json<{ data: CurseForgeProject[] }>().then(x => x?.data?.[0]) ?? undefined;
}
const response = await this._fetch(`/mods/${idOrSlug}`);
return await response.json<{ data: CurseForgeProject }>().then(x => x?.data) ?? undefined;
}
}

View file

@ -92,7 +92,7 @@ export class CurseForgeUploader extends GenericPlatformUploader<CurseForgeUpload
return {
id: +idOrSlug,
slug: String(idOrSlug),
links: { websiteUrl: `https://www.curseforge.com/minecraft/mc-mods/${idOrSlug}` }
links: { websiteUrl: `https://www.curseforge.com/minecraft/mc-mods/${idOrSlug}` },
} as CurseForgeProject;
}

View file

@ -361,7 +361,7 @@ export interface GitHubReleaseAssetsPatch {
* @returns The packed {@link GitHubReleaseInitInternal} object.
*/
export function packGitHubReleaseInit(release: GitHubReleaseInit): GitHubReleaseInitInternal {
return { ...{...release, owner: undefined, repo: undefined, assets: undefined } };
return { ...{ ...release, owner: undefined, repo: undefined, assets: undefined } };
}
/**
@ -373,5 +373,5 @@ export function packGitHubReleaseInit(release: GitHubReleaseInit): GitHubRelease
* @returns The packed {@link GitHubReleasePatchInternal} object.
*/
export function packGitHubReleasePatch(release: GitHubReleasePatch): GitHubReleasePatchInternal {
return { ...{...release, owner: undefined, repo: undefined, id: undefined, assets: undefined } };
return { ...{ ...release, owner: undefined, repo: undefined, id: undefined, assets: undefined } };
}

View file

@ -126,7 +126,7 @@ export class ModrinthApiClient {
* This method **DOES NOT** support slugs (for some reason).
*/
async getProjects(ids: Iterable<string>): Promise<ModrinthProject[]> {
const response = await this._fetch(`/projects`, HttpRequest.get().with({ ids: JSON.stringify(asArray(ids)) }));
const response = await this._fetch("/projects", HttpRequest.get().with({ ids: JSON.stringify(asArray(ids)) }));
return (await response.json()) ?? [];
}
@ -174,7 +174,7 @@ export class ModrinthApiClient {
* @returns An array of versions.
*/
async getVersions(ids: Iterable<string>): Promise<ModrinthVersion[]> {
const response = await this._fetch(`/versions`, HttpRequest.get().with({ ids: JSON.stringify(asArray(ids)) }));
const response = await this._fetch("/versions", HttpRequest.get().with({ ids: JSON.stringify(asArray(ids)) }));
return (await response.json()) ?? [];
}

View file

@ -180,7 +180,7 @@ export class ModrinthUploader extends GenericPlatformUploader<ModrinthUploaderOp
return;
}
this._logger.info(`🔽 Initiating unfeaturing of older Modrinth project versions`);
this._logger.info("🔽 Initiating unfeaturing of older Modrinth project versions");
const result = await api.unfeaturePreviousProjectVersions(version, unfeatureMode);
const unfeaturedVersions = Object.entries(result).filter(([, success]) => success).map(([version]) => version);
const nonUnfeaturedVersions = Object.entries(result).filter(([, success]) => !success).map(([version]) => version);

View file

@ -95,6 +95,7 @@ export interface InputObjectOptions extends InputOptions {
* - Hm, seems legit
*
*/
// eslint-disable-next-line no-template-curly-in-string
export const SYNTHETIC_UNDEFINED = "${undefined}";
/**
@ -149,7 +150,7 @@ export function getActionInput(name: string, options?: InputOptions, env?: Recor
const environmentVariableName = INPUT_PREFIX + normalizedName;
const brokenValue = getEnvironmentVariable(environmentVariableName, env);
const value = isActionInputDefined(brokenValue) ? brokenValue : undefined;
const trimmedValue = (options?.trimWhitespace ?? true) ? value?.trim() : value
const trimmedValue = (options?.trimWhitespace ?? true) ? value?.trim() : value;
if (options?.required && value === undefined) {
throw new Error(`Input required and not supplied: ${name}.`);

View file

@ -30,7 +30,9 @@ export function sleep(ms: number): Promise<void> {
return Promise.resolve();
}
return new Promise(resolve => setTimeout(resolve, ms));
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
/**

View file

@ -143,7 +143,7 @@ export function generateAutoGeneratedWarningFrame(options?: AutoGeneratedWarning
const filler = options?.style?.filler ?? DEFAULT_FRAME_STYLE.filler;
const lineStart = options?.style?.lineStart ?? `${filler} `;
const lineEnd = options?.style?.lineEnd ?? ` ${filler}`;
const newline = options?.newline ?? DEFAULT_NEWLINE
const newline = options?.newline ?? DEFAULT_NEWLINE;
const minLineLength = lineStart.length + lineEnd.length;
const maxLineLength = Math.max((options?.lineWidth || 0) - minLineLength, 0);

View file

@ -561,7 +561,7 @@ export function indexOf<T>(iterable: Iterable<T>, searchElement: T, fromIndex?:
let i = 0;
for (const value of iterable) {
if (i>= fromIndex && comparer(searchElement, value)) {
if (i >= fromIndex && comparer(searchElement, value)) {
return i;
}
++i;
@ -899,10 +899,11 @@ export function first<T>(iterable: Iterable<T>, predicate?: (value: T, index: nu
*/
export function first<T>(iterable: Iterable<T>, predicate?: (value: T, index: number, iterable: Iterable<T>) => unknown, thisArg?: unknown): T | undefined {
if (!predicate) {
// eslint-disable-next-line no-unreachable-loop
for (const value of iterable) {
return value;
}
return undefined
return undefined;
}
predicate = thisArg === undefined ? predicate : predicate.bind(thisArg);
@ -1183,8 +1184,8 @@ export class ArrayLikeIterable<T> implements Iterable<T> {
*
* @returns A new instance of the {@link ArrayLikeIterable} class.
*/
static from<T>(iterable: Iterable<T>): ArrayLikeIterable<T> {
return new ArrayLikeIterable(iterable);
static from<T>(iterable: Iterable<T>): ArrayLikeIterable<T> {
return new ArrayLikeIterable(iterable);
}
/**

View file

@ -205,7 +205,7 @@ export class ArraySet<T> implements Set<T> {
* @param callbackFn - Function to execute for each value in the set.
* @param thisArg - Object to use as `this` when executing `callbackFn`.
*/
forEach(callbackFn: (value: T, theSameValueAgain: T, set: ArraySet<T>) => void, thisArg?: any): void {
forEach(callbackFn: (value: T, theSameValueAgain: T, set: ArraySet<T>) => void, thisArg?: unknown): void {
callbackFn = thisArg === undefined ? callbackFn : callbackFn.bind(thisArg);
const values = this._values;

View file

@ -83,7 +83,12 @@ export function toBoolean(obj: unknown): boolean {
return false;
}
break;
default:
return undefined;
}
// ESLint
return undefined;
}
@ -116,7 +121,12 @@ function toNumber(obj: unknown, parser: (value: string | number) => number): num
return obj.getTime();
}
break;
default:
return undefined;
}
// ESLint
return undefined;
}
@ -165,7 +175,12 @@ export function toDate(obj: unknown): Date {
case "number":
const date = new Date(obj);
return isNaN(date.getTime()) ? undefined : date;
default:
return undefined;
}
// ESLint
return undefined;
}

View file

@ -63,6 +63,6 @@ export class StringDescriptor implements EnumDescriptor<string> {
}
const flags = split(value, ENUM_SEPARATORS, { trimEntries: true, removeEmptyEntries: true });
return flags.filter(x => x !== flag).join(DEFAULT_ENUM_SEPARATOR + " ");
return flags.filter(x => x !== flag).join(`${DEFAULT_ENUM_SEPARATOR} `);
}
}

View file

@ -1,7 +1,7 @@
/**
* An array of characters that can be used to separate enum values in a string.
*/
export const ENUM_SEPARATORS = [",", "|"] as const;
export const ENUM_SEPARATORS = [",", "|"] as const;
/**
* The default separator used when converting an enum value to a string.

View file

@ -94,14 +94,14 @@ export class ProcessLogger implements Logger {
* @inheritdoc
*/
error(message: string | Error): void {
this.log(message, "error")
this.log(message, "error");
}
/**
* @inheritdoc
*/
warn(message: string | Error): void {
this.log(message, "warning")
this.log(message, "warning");
}
/**

View file

@ -1,6 +1,8 @@
import { Blob as BlobPolyfill, blobFrom, blobFromSync } from "node-fetch";
import { ConstructorReturnType } from "@/utils/types";
/* eslint-disable-next-line no-restricted-imports */
import { Blob as BlobPolyfill, blobFrom, blobFromSync } from "node-fetch";
/**
* A `Blob` encapsulates immutable, raw data that can be safely shared across multiple worker threads.
*/
@ -20,7 +22,7 @@ export type Blob = ConstructorReturnType<typeof BlobPolyfill>;
*/
export function isBlob(blob: unknown): blob is Blob {
const name = blob?.[Symbol.toStringTag];
return name === "Blob" || name === "File";
return name === "Blob" || name === "File";
}
/**

View file

@ -1,13 +1,15 @@
import { ACTION_NAME } from "@/action";
import { Middleware, MiddlewareHandler } from "@/utils/functions";
import { asString } from "@/utils/string-utils";
import nodeFetch from "node-fetch";
import { Headers, cloneHeaders, setDefaultHeaders } from "./headers";
import { HttpMethod, canHttpMethodAcceptBody, httpMethodEquals } from "./http-method";
import { HttpRequest } from "./http-request";
import { HttpResponse } from "./http-response";
import { isURLSearchParams } from "./query-string";
/* eslint-disable-next-line no-restricted-imports */
import nodeFetch from "node-fetch";
/**
* Represents a fetch function that takes a URL and an optional request configuration,
* and returns a promise resolving to an HTTP response.
@ -116,7 +118,7 @@ export function createFetch(options?: FetchOptions): ConfigurableFetch {
Object.defineProperty(configurableFetch, "use", { value: (middleware: Middleware<Fetch>) => {
fetchPipeline.use(middleware);
return configurableFetch;
}});
} });
return configurableFetch;
}
@ -153,7 +155,7 @@ function prepareUrl(fetch: ConfigurableFetch, url: FetchUrl, request?: HttpReque
// Attach `URLSearchParams` to URL
if (isURLSearchParams(request?.body) && !canHttpMethodAcceptBody(request?.method)) {
if (typeof url === "string") {
url = `${url}${url.includes("?") ? "&" : "?"}${request.body}`
url = `${url}${url.includes("?") ? "&" : "?"}${request.body}`;
} else {
request.body.forEach((param, key) => (url as URL).searchParams.append(key, param));
}
@ -173,7 +175,7 @@ function prepareUrl(fetch: ConfigurableFetch, url: FetchUrl, request?: HttpReque
function prepareRequest(fetch: ConfigurableFetch, request?: HttpRequest): HttpRequest {
// Set default headers
if (fetch.defaultHeaders) {
request = request || {};
request ||= {};
request.headers = setDefaultHeaders(request.headers, fetch.defaultHeaders);
}

View file

@ -1,10 +1,12 @@
import { $i } from "@/utils/collections";
import { getOwnEntries } from "@/utils/reflection";
import { ConstructorReturnType } from "@/utils/types";
import { FormData as FormDataPolyfill } from "node-fetch";
import { basename } from "node:path";
import { Blob, readBlobSync } from "./blob";
/* eslint-disable-next-line no-restricted-imports */
import { FormData as FormDataPolyfill } from "node-fetch";
/**
* The `FormData` interface provides a way to easily construct a set of key/value pairs representing form fields and
* their values, which can then be easily sent using methods like `fetch()` or `XMLHttpRequest.send()`.

View file

@ -112,7 +112,7 @@ export function setHeader(headers: Headers, header: string, value: string): Head
return arrayLikeHeaders;
}
headers = headers || {};
headers ||= {};
headers[header] = value;
return headers;
}

View file

@ -1,10 +1,12 @@
import { ArgumentNullError } from "@/utils/errors";
import { asString } from "@/utils/string-utils";
import { Headers as NodeFetchHeaders, Response } from "node-fetch";
import { Blob } from "./blob";
import { FormData } from "./form-data";
import { Headers } from "./headers";
/* eslint-disable-next-line no-restricted-imports */
import { Headers as NodeFetchHeaders, Response } from "node-fetch";
/**
* Represents the response to an HTTP request.
*/

View file

@ -1,3 +1,3 @@
export const ACTION_MODULE_LOADER = (path: string): Promise<Record<string, unknown>> => {
return Promise.resolve(undefined);
return Promise.resolve(path ? undefined : null);
};

View file

@ -17,6 +17,7 @@ export interface ModuleLoader {
/**
* A module loader implementation that loads modules using Node.js dynamic `import` syntax.
*/
/* eslint-disable-next-line no-new-func */
export const NODE_MODULE_LOADER: ModuleLoader = new Function("x", "return import(x).catch(() => undefined)") as (name: string) => Promise<unknown>;
/**

View file

@ -460,6 +460,6 @@ export function generateSecureRandomString(length: number): string {
*
* @returns The hashed string in hexadecimal format.
*/
export function hashString(input: string, algorithm: string = "sha256"): string {
export function hashString(input: string, algorithm = "sha256"): string {
return createHash(algorithm).update(input).digest("hex");
}

View file

@ -23,7 +23,7 @@ export class TypeScriptExport extends AbstractTypeScriptNode {
* @param exportedNode - The exported node.
* @param isDefault - Indicates whether this is a default export. Defaults to `false`.
*/
private constructor(exportedNode: TypeScriptNode, isDefault?: boolean) {
private constructor(exportedNode: TypeScriptNode, isDefault?: boolean) {
super();
this._exportedNode = exportedNode;
this._isDefault = isDefault || false;

View file

@ -247,16 +247,16 @@ export class TypeScriptImport extends AbstractTypeScriptNode {
let formatted = `${indent}import `;
if (this.isWildcardImport) {
formatted += `* as ${this._wildcardImportName}`
formatted += `* as ${this._wildcardImportName}`;
}
if (this.isDefaultImport) {
formatted += this.defaultImportName;
}
if (this.isNamedImport) {
const formattedNamedImports = (
"{ "
+ [...this._namedImports].join(", ") +
" }"
`{ ${
[...this._namedImports].join(", ")
} }`
);
formatted += this.isDefaultImport ? ", " : "";

View file

@ -81,8 +81,8 @@ export class TypeScriptImports extends AbstractTypeScriptNode implements Iterabl
this._imports.set(importNode.path, importNode);
if (existingImportNode) {
importNode.addNamedImports(existingImportNode.namedImports());
importNode.defaultImportName = importNode.defaultImportName || existingImportNode.defaultImportName;
importNode.wildcardImportName = importNode.wildcardImportName || existingImportNode.wildcardImportName;
importNode.defaultImportName ||= existingImportNode.defaultImportName;
importNode.wildcardImportName ||= existingImportNode.wildcardImportName;
}
return importNode;
}
@ -139,7 +139,7 @@ export class TypeScriptImports extends AbstractTypeScriptNode implements Iterabl
*
* @returns The {@link TypeScriptImport} instance that was added or merged.
*/
addDefaultImport(path: string, defaultImportName: string): TypeScriptImport {
addDefaultImport(path: string, defaultImportName: string): TypeScriptImport {
const importNode = this.getOrCreateImport(path);
importNode.defaultImportName = defaultImportName;
return importNode;

View file

@ -1,13 +1,13 @@
import { getGameVersionProviderByName } from "@/games/game-version-provider";
describe("getGameVersionProviderByName", () => {
test("returns the correct provider for a given game name", async () => {
test("returns the correct provider for a given game name", () => {
const provider = getGameVersionProviderByName("minecraft");
expect(provider).toBeDefined();
});
test("returns undefined for a non-existing game name", async () => {
test("returns undefined for a non-existing game name", () => {
const provider = getGameVersionProviderByName("unknown-game");
expect(provider).toBeUndefined();

View file

@ -25,7 +25,7 @@ describe("FabricMetadata", () => {
expect(metadata.id).toBe("example-mod");
});
})
});
describe("name", () => {
test("returns name of the mod", () => {

View file

@ -26,7 +26,7 @@ describe("ForgeMetadata", () => {
expect(metadata.id).toBe("example-mod");
});
})
});
describe("name", () => {
test("returns name of the mod", () => {

View file

@ -33,7 +33,7 @@ describe("getQuiltDependencies", () => {
unless: "fixes-conflicts-id-2",
},
],
}
},
} as RawQuiltMetadata;
const dependencies = getQuiltDependencies(metadata);

View file

@ -25,7 +25,7 @@ describe("QuiltMetadata", () => {
expect(metadata.id).toBe("example-mod");
});
})
});
describe("name", () => {
test("returns name of the mod", () => {

View file

@ -2,7 +2,9 @@ import { isPromise, sleep, run, runSafely, retry } from "@/utils/async-utils";
describe("isPromise", () => {
test("returns true when input is a Promise", () => {
const promise = new Promise(resolve => resolve(undefined));
const promise = new Promise(resolve => {
resolve(undefined);
});
expect(isPromise(promise)).toBe(true);
});

View file

@ -1,4 +1,4 @@
import { generateAutoGeneratedWarningText, generateAutoGeneratedWarningFrame, YAML_FRAME_STYLE } from "@/utils/auto-generated";
import { generateAutoGeneratedWarningText, generateAutoGeneratedWarningFrame } from "@/utils/auto-generated";
describe("generateAutoGeneratedWarningText", () => {
test("generates the correct warning text without a source file name", () => {

View file

@ -31,7 +31,9 @@ describe("filter", () => {
const iterable = [1, 2, 3, 4, 5];
const thisArg = { threshold: 3 };
const result = Array.from(Iterable.filter(iterable, function (x) { return x > this.threshold; }, thisArg));
const result = Array.from(Iterable.filter(iterable, function(x) {
return x > this.threshold;
}, thisArg));
expect(result).toEqual([4, 5]);
});
@ -86,7 +88,9 @@ describe("map", () => {
const iterable = [1, 2, 3];
const thisArg = { factor: 2 };
const result = Array.from(Iterable.map(iterable, function (x) { return x * this.factor; }, thisArg));
const result = Array.from(Iterable.map(iterable, function(x) {
return x * this.factor;
}, thisArg));
expect(result).toEqual([2, 4, 6]);
});
@ -105,7 +109,9 @@ describe("flatMap", () => {
const iterable = [1, 2, 3];
const thisArg = { factor: 2 };
const result = Array.from(Iterable.flatMap(iterable, function (x) { return [x, x * this.factor]; }, thisArg));
const result = Array.from(Iterable.flatMap(iterable, function(x) {
return [x, x * this.factor];
}, thisArg));
expect(result).toEqual([1, 2, 2, 4, 3, 6]);
});
@ -136,7 +142,9 @@ describe("reduce", () => {
const iterable = [1, 2, 3, 4, 5];
const thisArg = { factor: 2 };
const result = Iterable.reduce(iterable, function (acc, curr) { return acc + curr * this.factor; }, 0, thisArg);
const result = Iterable.reduce(iterable, function(acc, curr) {
return acc + curr * this.factor;
}, 0, thisArg);
expect(result).toBe(30);
});
@ -241,7 +249,7 @@ describe("every", () => {
test("returns true if all elements meet the condition", () => {
const iterable = [2, 4, 6, 8];
const result = Iterable.every(iterable, (value) => value % 2 === 0);
const result = Iterable.every(iterable, value => value % 2 === 0);
expect(result).toBe(true);
});
@ -249,7 +257,7 @@ describe("every", () => {
test("returns false if any element does not meet the condition", () => {
const iterable = [2, 4, 5, 8];
const result = Iterable.every(iterable, (value) => value % 2 === 0);
const result = Iterable.every(iterable, value => value % 2 === 0);
expect(result).toBe(false);
});
@ -258,7 +266,9 @@ describe("every", () => {
const iterable = [2, 4, 6, 8];
const thisArg = { factor: 2 };
const result = Iterable.every(iterable, function (x) { return x % this.factor === 0; }, thisArg);
const result = Iterable.every(iterable, function(x) {
return x % this.factor === 0;
}, thisArg);
expect(result).toBe(true);
});
@ -268,7 +278,7 @@ describe("some", () => {
test("returns true if any element meets the condition", () => {
const iterable = [1, 3, 4, 7];
const result = Iterable.some(iterable, (value) => value % 2 === 0);
const result = Iterable.some(iterable, value => value % 2 === 0);
expect(result).toBe(true);
});
@ -276,7 +286,7 @@ describe("some", () => {
test("returns false if no element meets the condition", () => {
const iterable = [1, 3, 5, 7];
const result = Iterable.some(iterable, (value) => value % 2 === 0);
const result = Iterable.some(iterable, value => value % 2 === 0);
expect(result).toBe(false);
});
@ -285,7 +295,9 @@ describe("some", () => {
const iterable = [1, 3, 4, 7];
const thisArg = { factor: 2 };
const result = Iterable.some(iterable, function (x) { return x % this.factor === 0; }, thisArg);
const result = Iterable.some(iterable, function(x) {
return x % this.factor === 0;
}, thisArg);
expect(result).toBe(true);
});
@ -320,7 +332,9 @@ describe("min", () => {
const iterable = [3, 1, 4, 2];
const thisArg = { sign: -1 };
const result = Iterable.min(iterable, function (a, b) { return (a - b) * this.sign; }, thisArg);
const result = Iterable.min(iterable, function(a, b) {
return (a - b) * this.sign;
}, thisArg);
expect(result).toBe(4);
});
@ -349,7 +363,9 @@ describe("max", () => {
const iterable = [3, 1, 4, 2];
const thisArg = { sign: -1 };
const result = Iterable.max(iterable, function (a, b) { return (a - b) * this.sign; }, thisArg);
const result = Iterable.max(iterable, function(a, b) {
return (a - b) * this.sign;
}, thisArg);
expect(result).toBe(1);
});
@ -382,7 +398,9 @@ describe("count", () => {
const iterable = [1, 2, 3, 4, 5];
const thisArg = { min: 2 };
const result = Iterable.count(iterable, function (x) { return x > this.min; }, thisArg);
const result = Iterable.count(iterable, function(x) {
return x > this.min;
}, thisArg);
expect(result).toBe(3);
});
@ -660,7 +678,9 @@ describe("findIndex", () => {
const iterable = [1, 2, 3, 4, 5];
const thisArg = { target: 3 };
const result = Iterable.findIndex(iterable, function (x) { return x === this.target; }, thisArg);
const result = Iterable.findIndex(iterable, function(x) {
return x === this.target;
}, thisArg);
expect(result).toBe(2);
});
@ -699,7 +719,9 @@ describe("first", () => {
const iterable = [{ id: 1, value: "a" }, { id: 2, value: "b" }, { id: 3, value: "a" }, { id: 4, value: "b" }];
const thisArg = { target: "b" };
const result = Iterable.first(iterable, function (x) { return x.value === this.target; }, thisArg);
const result = Iterable.first(iterable, function(x) {
return x.value === this.target;
}, thisArg);
expect(result).toEqual({ id: 2, value: "b" });
});
@ -738,7 +760,9 @@ describe("last", () => {
const iterable = [{ id: 1, value: "a" }, { id: 2, value: "b" }, { id: 3, value: "a" }, { id: 4, value: "b" }];
const thisArg = { target: "a" };
const result = Iterable.last(iterable, function (x) { return x.value === this.target; }, thisArg);
const result = Iterable.last(iterable, function(x) {
return x.value === this.target;
}, thisArg);
expect(result).toEqual({ id: 3, value: "a" });
});
@ -1048,7 +1072,7 @@ describe("ArrayLikeIterable", () => {
const record = iterable.toRecord();
expect(record).toEqual({ "zero": 0, "one": 1, "two": 2 });
expect(record).toEqual({ zero: 0, one: 1, two: 2 });
});
});

View file

@ -7,7 +7,7 @@ const readOnlyMapLike = {
entries: () => {},
get: () => {},
has: () => {},
[Symbol.iterator]: () => {}
[Symbol.iterator]: () => {},
};
const mapLike = {
@ -269,7 +269,7 @@ describe("ArrayMap", () => {
const map = new ArrayMap([[1, "one"]]);
const thisArg = {};
map.forEach(function (this: typeof thisArg) {
map.forEach(function(this: typeof thisArg) {
expect(this).toBe(thisArg);
}, thisArg);
});
@ -574,7 +574,7 @@ describe("MultiMap", () => {
const map = new MultiMap([[1, ["one"]]]);
const thisArg = {};
map.forEach(function (this: typeof thisArg) {
map.forEach(function(this: typeof thisArg) {
expect(this).toBe(thisArg);
}, thisArg);
});
@ -598,7 +598,7 @@ describe("MultiMap", () => {
const map = new MultiMap([[1, ["one"]]]);
const thisArg = {};
map.forEachFlat(function (this: typeof thisArg) {
map.forEachFlat(function(this: typeof thisArg) {
expect(this).toBe(thisArg);
}, thisArg);
});

View file

@ -6,7 +6,7 @@ const readOnlySetLike = {
values: () => {},
entries: () => {},
has: () => {},
[Symbol.iterator]: () => {}
[Symbol.iterator]: () => {},
};
const setLike = {
@ -65,7 +65,7 @@ describe("ArraySet", () => {
const set = new ArraySet(["one", "two"]);
expect(set.size).toBe(2);
expect(Array.from(set)).toEqual(["one", "two"])
expect(Array.from(set)).toEqual(["one", "two"]);
});
test("creates a set from an iterable of entries and a custom comparer", () => {
@ -226,7 +226,7 @@ describe("ArraySet", () => {
const set = new ArraySet([1, 2]);
const thisArg = {};
set.forEach(function (this: typeof thisArg) {
set.forEach(function(this: typeof thisArg) {
expect(this).toBe(thisArg);
}, thisArg);
});

View file

@ -24,7 +24,7 @@ describe("FileNotFoundError", () => {
describe("throwIfNotFound", () => {
beforeEach(() => {
mockFs({ "test": "test" });
mockFs({ test: "test" });
});
afterEach(() => {

View file

@ -9,7 +9,7 @@ describe("HttpError", () => {
const error = new HttpError(response, "An error occurred.", false);
expect(error).toBeInstanceOf(HttpError);
expect(error.name).toBe("HttpError")
expect(error.name).toBe("HttpError");
expect(error.message).toBe("An error occurred.");
expect(error.isSoft).toBe(false);
expect(error.response).toBe(response);
@ -41,7 +41,7 @@ describe("HttpError", () => {
const error = await HttpError.fromResponse(response, false);
expect(error).toBeInstanceOf(HttpError);
expect(error.name).toBe("HttpError")
expect(error.name).toBe("HttpError");
});
test("includes text content in the error message", async () => {

View file

@ -5,7 +5,7 @@ describe("NullLogger", () => {
test("can be created without throwing", () => {
expect(() => new NullLogger()).not.toThrow();
});
})
});
describe("fatal", () => {
test("can be called without throwing", () => {

View file

@ -180,13 +180,24 @@ describe("merge", () => {
test("preserves getters and setters when merging objects", () => {
const obj1 = {
_a: 1,
get a() { return this._a; },
set a(val) { this._a = val; },
get a() {
return this._a;
},
set a(val) {
this._a = val;
},
};
const obj2 = {
_b: 2,
get b() { return this._b; },
set b(val) { this._b = val; }
get b() {
return this._b;
},
set b(val) {
this._b = val;
},
};
const merged = merge(obj1, obj2);
@ -239,7 +250,7 @@ describe("getSafe", () => {
const obj = {
get name(): string {
throw new Error();
}
},
};
expect(getSafe(obj, "name")).toBeUndefined();