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

277
.eslintrc
View file

@ -1,41 +1,240 @@
{ {
"root": true, "root": true,
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"], "plugins": ["@typescript-eslint"],
"env": { "env": {
"node": true "node": true
}, },
"extends": [ "extends": [
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/recommended" "plugin:@typescript-eslint/recommended"
], ],
"rules": { "rules": {
"arrow-body-style": ["error", "as-needed"], "array-callback-return": "error",
"complexity": ["warn", { "max": 50 }], "no-constant-binary-expression": "error",
"curly": ["error", "multi-line", "consistent"], "no-constant-condition": ["error", { "checkLoops": false }],
"eqeqeq": ["error", "smart"], "no-constructor-return": "error",
"no-constant-condition": ["error", { "checkLoops": false }], "no-duplicate-imports": "error",
"no-empty": ["error", { "allowEmptyCatch": true }], "no-new-native-nonconstructor": "error",
"no-lonely-if": "error", "no-promise-executor-return": "error",
"no-var": "error", "no-self-compare": "error",
"object-shorthand": "error", "no-template-curly-in-string": "warn",
"one-var": ["error", { "var": "never", "let": "never" }], "no-unmodified-loop-condition": "warn",
"prefer-arrow-callback": "error", "no-unreachable-loop": "warn",
"prefer-const": ["error", { "destructuring": "all" }], "no-unused-private-class-members": "error",
"prefer-object-spread": "error", "@typescript-eslint/no-unused-vars": ["error", {
"prefer-rest-params": "warn", "varsIgnorePattern": "^_",
"prefer-spread": "warn", "argsIgnorePattern": "^_"
"quote-props": ["error", "consistent-as-needed"], }],
"quotes": "error", "no-use-before-define": "off",
"spaced-comment": ["error", "always", { "markers": ["/"] }], "require-atomic-updates": "off",
"yoda": ["error", "never", { "exceptRange": true }],
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }], "accessor-pairs": "error",
"@typescript-eslint/no-namespace": "off", "arrow-body-style": "off",
"@typescript-eslint/no-explicit-any": "off", "block-scoped-var": "error",
"@typescript-eslint/no-non-null-assertion": "off", "camelcase": "off",
"@typescript-eslint/no-unused-vars": ["error", { "capitalized-comments": "off",
"varsIgnorePattern": "^_", "class-methods-use-this": "off",
"argsIgnorePattern": "^_" "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", "generate": "ncc run scripts/generate.ts -t",
"prebuild": "npm run generate", "prebuild": "npm run generate",
"build": "ncc build -s --license license.txt", "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:unit": "jest --testPathPattern=unit --watchAll=false",
"test:integration": "jest --testPathPattern=integration", "test:integration": "jest --testPathPattern=integration",
"test": "npm run test:lint && npm run test:unit && npm run test: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 { TypeScriptDocument } from "@/utils/typescript";
import { basename } from "node:path"; import { basename } from "node:path";
// Configure file paths /**
const ACTION_METADATA_TEMPLATE_FILE = "./action.template.yml"; // Path to the action metadata template file * 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 ACTION_METADATA_TEMPLATE_FILE = "./action.template.yml";
const DYNAMIC_MODULE_LOADER_FILE = "./src/utils/reflection/module-loader.g.ts"; // Path to the output dynamic module loader TypeScript file
// 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 = { const OPTIONS: PrebuildOptions = {
sourceFileName: basename(ACTION_METADATA_TEMPLATE_FILE), // The name of the source file everything else is generated from // The name of the source file everything else is generated from.
encoding: "utf8", // The encoding used for reading and writing files sourceFileName: basename(ACTION_METADATA_TEMPLATE_FILE),
disableESLint: true, // Disable ESLint in the generated TypeScript files // The encoding used for reading and writing files.
generateAutoGeneratedWarningMessage: true, // Add a warning message about auto-generated files encoding: "utf8",
removeTemplateOnlyFields: true, // Remove fields that are only used in the template from the generated files
rootPath: "@/", // The root path for module imports // Disable ESLint in the generated TypeScript files.
pathParser: SPLIT_BY_WORDS_AND_GROUP_ACTION_PARAMETER_PATH_PARSER, // The path parser used for action parameter paths disableESLint: true,
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 // Add a warning message about auto-generated files
lineWidth: 80, // The maximum line width for the 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< type PrebuildOptions = Exclude<
& Parameters<typeof processActionMetadataTemplateFile>[2] & Parameters<typeof processActionMetadataTemplateFile>[2]
& Parameters<typeof parseActionMetadataFromFile>[1] & 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 { FabricDependencyType } from "@/loaders/fabric/fabric-dependency-type";
import { deprecate } from "node:util"; 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. * 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. * 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 { deprecate } from "node:util";
import { GameVersion } from "./game-version"; import { GameVersion } from "./game-version";
// TODO: Remove deprecated stuff in v4.0 // _ TODO: Remove deprecated stuff in v4.0
/** /**
* Represents a game version filter. * Represents a game version filter.

View file

@ -1,3 +1,5 @@
/* eslint-disable no-cond-assign */
import { asArrayLike, isIterable } from "@/utils/collections"; import { asArrayLike, isIterable } from "@/utils/collections";
import { VersionRange, parseVersionRange } from "@/utils/versioning"; import { VersionRange, parseVersionRange } from "@/utils/versioning";
import { MinecraftVersion, MinecraftVersionManifestEntry } from "./minecraft-version"; 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. * Converts {@link FabricDependency} to a {@link Dependency} object.
* *
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid.. * @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
*/ */
export function normalizeFabricDependency(dependency: FabricDependency): Dependency | undefined { export function normalizeFabricDependency(dependency: FabricDependency): Dependency | undefined {
return createDependency({ return createDependency({
id: dependency?.id, id: dependency?.id,

View file

@ -7,7 +7,7 @@ import { PartialRecord } from "@/utils/types";
import { deprecate } from "node:util"; import { deprecate } from "node:util";
import { RawFabricMetadata } from "./raw-fabric-metadata"; 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. * Custom payload for Fabric metadata.

View file

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

View file

@ -8,7 +8,7 @@ import { deprecate } from "node:util";
import { ForgeEnvironmentType } from "./forge-environment-type"; import { ForgeEnvironmentType } from "./forge-environment-type";
import { RawForgeMetadata } from "./raw-forge-metadata"; 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. * 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. * Converts {@link FabricDependency} to a {@link Dependency} object.
* *
* @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid.. * @returns A Dependency object representing the given Fabric dependency, or `undefined` if the input is invalid..
*/ */
export function normalizeForgeDependency(dependency: ForgeDependency): Dependency | undefined { export function normalizeForgeDependency(dependency: ForgeDependency): Dependency | undefined {
const payload = getForgeDependencyCustomPayload(dependency); const payload = getForgeDependencyCustomPayload(dependency);

View file

@ -7,7 +7,7 @@ import { deprecate } from "node:util";
import { RawForgeMetadata } from "./raw-forge-metadata"; import { RawForgeMetadata } from "./raw-forge-metadata";
import { asString } from "@/utils/string-utils"; 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. * Custom payload for Forge metadata.

View file

@ -3,7 +3,7 @@ import { ForgeDependency } from "./forge-dependency";
import { ForgeMod } from "./forge-mod"; import { ForgeMod } from "./forge-mod";
import { ForgeMetadataCustomPayload } from "./forge-metadata-custom-payload"; 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. * 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. * Converts {@link QuiltDependency} to a {@link Dependency} object.
* *
* @returns A Dependency object representing the given Quilt dependency. * @returns A Dependency object representing the given Quilt dependency.
*/ */
export function normalizeQuiltDependency(dependency: QuiltDependency): Dependency { export function normalizeQuiltDependency(dependency: QuiltDependency): Dependency {
const payload = getQuiltDependencyCustomPayload(dependency); const payload = getQuiltDependencyCustomPayload(dependency);

View file

@ -7,7 +7,7 @@ import { deprecate } from "node:util";
import { RawQuiltMetadata } from "./raw-quilt-metadata"; import { RawQuiltMetadata } from "./raw-quilt-metadata";
import { asString } from "@/utils/string-utils"; 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. * Custom payload for Quilt metadata.

View file

@ -1,6 +1,7 @@
import { ZippedTextLoaderMetadataReader } from "@/loaders/zipped-loader-metadata-reader"; import { ZippedTextLoaderMetadataReader } from "@/loaders/zipped-loader-metadata-reader";
import { QuiltMetadata } from "./quilt-metadata"; import { QuiltMetadata } from "./quilt-metadata";
import { QUILT_MOD_JSON, RawQuiltMetadata } from "./raw-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. * 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 { QuiltPlugin } from "./quilt-plugin";
import { QuiltMetadataCustomPayload } from "./quilt-metadata-custom-payload"; 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. * 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. * 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. * 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. * @returns The project, or `undefined` if not found.
*/ */
async getProject(idOrSlug: number | string): Promise<CurseForgeProject | undefined> { async getProject(idOrSlug: number | string): Promise<CurseForgeProject | undefined> {
if (isCurseForgeProjectId(idOrSlug)) { if (!isCurseForgeProjectId(idOrSlug)) {
const response = await this._fetch(`/mods/${idOrSlug}`);
return await response.json<{ data: CurseForgeProject }>().then(x => x?.data) ?? undefined;
} else {
const response = await this._fetch("/mods/search", HttpRequest.get().with({ gameId: 432, slug: 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; 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 { return {
id: +idOrSlug, id: +idOrSlug,
slug: String(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; } as CurseForgeProject;
} }

View file

@ -361,7 +361,7 @@ export interface GitHubReleaseAssetsPatch {
* @returns The packed {@link GitHubReleaseInitInternal} object. * @returns The packed {@link GitHubReleaseInitInternal} object.
*/ */
export function packGitHubReleaseInit(release: GitHubReleaseInit): GitHubReleaseInitInternal { 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. * @returns The packed {@link GitHubReleasePatchInternal} object.
*/ */
export function packGitHubReleasePatch(release: GitHubReleasePatch): GitHubReleasePatchInternal { 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). * This method **DOES NOT** support slugs (for some reason).
*/ */
async getProjects(ids: Iterable<string>): Promise<ModrinthProject[]> { 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()) ?? []; return (await response.json()) ?? [];
} }
@ -174,7 +174,7 @@ export class ModrinthApiClient {
* @returns An array of versions. * @returns An array of versions.
*/ */
async getVersions(ids: Iterable<string>): Promise<ModrinthVersion[]> { 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()) ?? []; return (await response.json()) ?? [];
} }

View file

@ -180,7 +180,7 @@ export class ModrinthUploader extends GenericPlatformUploader<ModrinthUploaderOp
return; 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 result = await api.unfeaturePreviousProjectVersions(version, unfeatureMode);
const unfeaturedVersions = Object.entries(result).filter(([, success]) => success).map(([version]) => version); const unfeaturedVersions = Object.entries(result).filter(([, success]) => success).map(([version]) => version);
const nonUnfeaturedVersions = 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 * - Hm, seems legit
* *
*/ */
// eslint-disable-next-line no-template-curly-in-string
export const SYNTHETIC_UNDEFINED = "${undefined}"; export const SYNTHETIC_UNDEFINED = "${undefined}";
/** /**
@ -149,7 +150,7 @@ export function getActionInput(name: string, options?: InputOptions, env?: Recor
const environmentVariableName = INPUT_PREFIX + normalizedName; const environmentVariableName = INPUT_PREFIX + normalizedName;
const brokenValue = getEnvironmentVariable(environmentVariableName, env); const brokenValue = getEnvironmentVariable(environmentVariableName, env);
const value = isActionInputDefined(brokenValue) ? brokenValue : undefined; 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) { if (options?.required && value === undefined) {
throw new Error(`Input required and not supplied: ${name}.`); 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 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 filler = options?.style?.filler ?? DEFAULT_FRAME_STYLE.filler;
const lineStart = options?.style?.lineStart ?? `${filler} `; const lineStart = options?.style?.lineStart ?? `${filler} `;
const lineEnd = options?.style?.lineEnd ?? ` ${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 minLineLength = lineStart.length + lineEnd.length;
const maxLineLength = Math.max((options?.lineWidth || 0) - minLineLength, 0); 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; let i = 0;
for (const value of iterable) { for (const value of iterable) {
if (i>= fromIndex && comparer(searchElement, value)) { if (i >= fromIndex && comparer(searchElement, value)) {
return i; return i;
} }
++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 { export function first<T>(iterable: Iterable<T>, predicate?: (value: T, index: number, iterable: Iterable<T>) => unknown, thisArg?: unknown): T | undefined {
if (!predicate) { if (!predicate) {
// eslint-disable-next-line no-unreachable-loop
for (const value of iterable) { for (const value of iterable) {
return value; return value;
} }
return undefined return undefined;
} }
predicate = thisArg === undefined ? predicate : predicate.bind(thisArg); 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. * @returns A new instance of the {@link ArrayLikeIterable} class.
*/ */
static from<T>(iterable: Iterable<T>): ArrayLikeIterable<T> { static from<T>(iterable: Iterable<T>): ArrayLikeIterable<T> {
return new ArrayLikeIterable(iterable); 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 callbackFn - Function to execute for each value in the set.
* @param thisArg - Object to use as `this` when executing `callbackFn`. * @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); callbackFn = thisArg === undefined ? callbackFn : callbackFn.bind(thisArg);
const values = this._values; const values = this._values;

View file

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

View file

@ -63,6 +63,6 @@ export class StringDescriptor implements EnumDescriptor<string> {
} }
const flags = split(value, ENUM_SEPARATORS, { trimEntries: true, removeEmptyEntries: true }); 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. * 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. * The default separator used when converting an enum value to a string.

View file

@ -94,14 +94,14 @@ export class ProcessLogger implements Logger {
* @inheritdoc * @inheritdoc
*/ */
error(message: string | Error): void { error(message: string | Error): void {
this.log(message, "error") this.log(message, "error");
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
warn(message: string | Error): void { 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"; 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. * 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 { export function isBlob(blob: unknown): blob is Blob {
const name = blob?.[Symbol.toStringTag]; 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 { ACTION_NAME } from "@/action";
import { Middleware, MiddlewareHandler } from "@/utils/functions"; import { Middleware, MiddlewareHandler } from "@/utils/functions";
import { asString } from "@/utils/string-utils"; import { asString } from "@/utils/string-utils";
import nodeFetch from "node-fetch";
import { Headers, cloneHeaders, setDefaultHeaders } from "./headers"; import { Headers, cloneHeaders, setDefaultHeaders } from "./headers";
import { HttpMethod, canHttpMethodAcceptBody, httpMethodEquals } from "./http-method"; import { HttpMethod, canHttpMethodAcceptBody, httpMethodEquals } from "./http-method";
import { HttpRequest } from "./http-request"; import { HttpRequest } from "./http-request";
import { HttpResponse } from "./http-response"; import { HttpResponse } from "./http-response";
import { isURLSearchParams } from "./query-string"; 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, * Represents a fetch function that takes a URL and an optional request configuration,
* and returns a promise resolving to an HTTP response. * 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>) => { Object.defineProperty(configurableFetch, "use", { value: (middleware: Middleware<Fetch>) => {
fetchPipeline.use(middleware); fetchPipeline.use(middleware);
return configurableFetch; return configurableFetch;
}}); } });
return configurableFetch; return configurableFetch;
} }
@ -153,7 +155,7 @@ function prepareUrl(fetch: ConfigurableFetch, url: FetchUrl, request?: HttpReque
// Attach `URLSearchParams` to URL // Attach `URLSearchParams` to URL
if (isURLSearchParams(request?.body) && !canHttpMethodAcceptBody(request?.method)) { if (isURLSearchParams(request?.body) && !canHttpMethodAcceptBody(request?.method)) {
if (typeof url === "string") { if (typeof url === "string") {
url = `${url}${url.includes("?") ? "&" : "?"}${request.body}` url = `${url}${url.includes("?") ? "&" : "?"}${request.body}`;
} else { } else {
request.body.forEach((param, key) => (url as URL).searchParams.append(key, param)); 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 { function prepareRequest(fetch: ConfigurableFetch, request?: HttpRequest): HttpRequest {
// Set default headers // Set default headers
if (fetch.defaultHeaders) { if (fetch.defaultHeaders) {
request = request || {}; request ||= {};
request.headers = setDefaultHeaders(request.headers, fetch.defaultHeaders); request.headers = setDefaultHeaders(request.headers, fetch.defaultHeaders);
} }

View file

@ -1,10 +1,12 @@
import { $i } from "@/utils/collections"; import { $i } from "@/utils/collections";
import { getOwnEntries } from "@/utils/reflection"; import { getOwnEntries } from "@/utils/reflection";
import { ConstructorReturnType } from "@/utils/types"; import { ConstructorReturnType } from "@/utils/types";
import { FormData as FormDataPolyfill } from "node-fetch";
import { basename } from "node:path"; import { basename } from "node:path";
import { Blob, readBlobSync } from "./blob"; 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 * 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()`. * 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; return arrayLikeHeaders;
} }
headers = headers || {}; headers ||= {};
headers[header] = value; headers[header] = value;
return headers; return headers;
} }

View file

@ -1,10 +1,12 @@
import { ArgumentNullError } from "@/utils/errors"; import { ArgumentNullError } from "@/utils/errors";
import { asString } from "@/utils/string-utils"; import { asString } from "@/utils/string-utils";
import { Headers as NodeFetchHeaders, Response } from "node-fetch";
import { Blob } from "./blob"; import { Blob } from "./blob";
import { FormData } from "./form-data"; import { FormData } from "./form-data";
import { Headers } from "./headers"; 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. * Represents the response to an HTTP request.
*/ */

View file

@ -1,3 +1,3 @@
export const ACTION_MODULE_LOADER = (path: string): Promise<Record<string, unknown>> => { 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. * 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>; 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. * @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"); return createHash(algorithm).update(input).digest("hex");
} }

View file

@ -23,7 +23,7 @@ export class TypeScriptExport extends AbstractTypeScriptNode {
* @param exportedNode - The exported node. * @param exportedNode - The exported node.
* @param isDefault - Indicates whether this is a default export. Defaults to `false`. * @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(); super();
this._exportedNode = exportedNode; this._exportedNode = exportedNode;
this._isDefault = isDefault || false; this._isDefault = isDefault || false;

View file

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

View file

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

View file

@ -1,13 +1,13 @@
import { getGameVersionProviderByName } from "@/games/game-version-provider"; import { getGameVersionProviderByName } from "@/games/game-version-provider";
describe("getGameVersionProviderByName", () => { 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"); const provider = getGameVersionProviderByName("minecraft");
expect(provider).toBeDefined(); 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"); const provider = getGameVersionProviderByName("unknown-game");
expect(provider).toBeUndefined(); expect(provider).toBeUndefined();

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,9 @@ import { isPromise, sleep, run, runSafely, retry } from "@/utils/async-utils";
describe("isPromise", () => { describe("isPromise", () => {
test("returns true when input is a Promise", () => { 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); 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", () => { describe("generateAutoGeneratedWarningText", () => {
test("generates the correct warning text without a source file name", () => { 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 iterable = [1, 2, 3, 4, 5];
const thisArg = { threshold: 3 }; 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]); expect(result).toEqual([4, 5]);
}); });
@ -86,7 +88,9 @@ describe("map", () => {
const iterable = [1, 2, 3]; const iterable = [1, 2, 3];
const thisArg = { factor: 2 }; 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]); expect(result).toEqual([2, 4, 6]);
}); });
@ -105,7 +109,9 @@ describe("flatMap", () => {
const iterable = [1, 2, 3]; const iterable = [1, 2, 3];
const thisArg = { factor: 2 }; 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]); expect(result).toEqual([1, 2, 2, 4, 3, 6]);
}); });
@ -136,7 +142,9 @@ describe("reduce", () => {
const iterable = [1, 2, 3, 4, 5]; const iterable = [1, 2, 3, 4, 5];
const thisArg = { factor: 2 }; 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); expect(result).toBe(30);
}); });
@ -241,7 +249,7 @@ describe("every", () => {
test("returns true if all elements meet the condition", () => { test("returns true if all elements meet the condition", () => {
const iterable = [2, 4, 6, 8]; 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); expect(result).toBe(true);
}); });
@ -249,7 +257,7 @@ describe("every", () => {
test("returns false if any element does not meet the condition", () => { test("returns false if any element does not meet the condition", () => {
const iterable = [2, 4, 5, 8]; 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); expect(result).toBe(false);
}); });
@ -258,7 +266,9 @@ describe("every", () => {
const iterable = [2, 4, 6, 8]; const iterable = [2, 4, 6, 8];
const thisArg = { factor: 2 }; 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); expect(result).toBe(true);
}); });
@ -268,7 +278,7 @@ describe("some", () => {
test("returns true if any element meets the condition", () => { test("returns true if any element meets the condition", () => {
const iterable = [1, 3, 4, 7]; 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); expect(result).toBe(true);
}); });
@ -276,7 +286,7 @@ describe("some", () => {
test("returns false if no element meets the condition", () => { test("returns false if no element meets the condition", () => {
const iterable = [1, 3, 5, 7]; 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); expect(result).toBe(false);
}); });
@ -285,7 +295,9 @@ describe("some", () => {
const iterable = [1, 3, 4, 7]; const iterable = [1, 3, 4, 7];
const thisArg = { factor: 2 }; 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); expect(result).toBe(true);
}); });
@ -320,7 +332,9 @@ describe("min", () => {
const iterable = [3, 1, 4, 2]; const iterable = [3, 1, 4, 2];
const thisArg = { sign: -1 }; 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); expect(result).toBe(4);
}); });
@ -349,7 +363,9 @@ describe("max", () => {
const iterable = [3, 1, 4, 2]; const iterable = [3, 1, 4, 2];
const thisArg = { sign: -1 }; 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); expect(result).toBe(1);
}); });
@ -382,7 +398,9 @@ describe("count", () => {
const iterable = [1, 2, 3, 4, 5]; const iterable = [1, 2, 3, 4, 5];
const thisArg = { min: 2 }; 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); expect(result).toBe(3);
}); });
@ -660,7 +678,9 @@ describe("findIndex", () => {
const iterable = [1, 2, 3, 4, 5]; const iterable = [1, 2, 3, 4, 5];
const thisArg = { target: 3 }; 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); 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 iterable = [{ id: 1, value: "a" }, { id: 2, value: "b" }, { id: 3, value: "a" }, { id: 4, value: "b" }];
const thisArg = { target: "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" }); 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 iterable = [{ id: 1, value: "a" }, { id: 2, value: "b" }, { id: 3, value: "a" }, { id: 4, value: "b" }];
const thisArg = { target: "a" }; 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" }); expect(result).toEqual({ id: 3, value: "a" });
}); });
@ -1048,7 +1072,7 @@ describe("ArrayLikeIterable", () => {
const record = iterable.toRecord(); 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: () => {}, entries: () => {},
get: () => {}, get: () => {},
has: () => {}, has: () => {},
[Symbol.iterator]: () => {} [Symbol.iterator]: () => {},
}; };
const mapLike = { const mapLike = {
@ -269,7 +269,7 @@ describe("ArrayMap", () => {
const map = new ArrayMap([[1, "one"]]); const map = new ArrayMap([[1, "one"]]);
const thisArg = {}; const thisArg = {};
map.forEach(function (this: typeof thisArg) { map.forEach(function(this: typeof thisArg) {
expect(this).toBe(thisArg); expect(this).toBe(thisArg);
}, thisArg); }, thisArg);
}); });
@ -574,7 +574,7 @@ describe("MultiMap", () => {
const map = new MultiMap([[1, ["one"]]]); const map = new MultiMap([[1, ["one"]]]);
const thisArg = {}; const thisArg = {};
map.forEach(function (this: typeof thisArg) { map.forEach(function(this: typeof thisArg) {
expect(this).toBe(thisArg); expect(this).toBe(thisArg);
}, thisArg); }, thisArg);
}); });
@ -598,7 +598,7 @@ describe("MultiMap", () => {
const map = new MultiMap([[1, ["one"]]]); const map = new MultiMap([[1, ["one"]]]);
const thisArg = {}; const thisArg = {};
map.forEachFlat(function (this: typeof thisArg) { map.forEachFlat(function(this: typeof thisArg) {
expect(this).toBe(thisArg); expect(this).toBe(thisArg);
}, thisArg); }, thisArg);
}); });

View file

@ -6,7 +6,7 @@ const readOnlySetLike = {
values: () => {}, values: () => {},
entries: () => {}, entries: () => {},
has: () => {}, has: () => {},
[Symbol.iterator]: () => {} [Symbol.iterator]: () => {},
}; };
const setLike = { const setLike = {
@ -65,7 +65,7 @@ describe("ArraySet", () => {
const set = new ArraySet(["one", "two"]); const set = new ArraySet(["one", "two"]);
expect(set.size).toBe(2); 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", () => { 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 set = new ArraySet([1, 2]);
const thisArg = {}; const thisArg = {};
set.forEach(function (this: typeof thisArg) { set.forEach(function(this: typeof thisArg) {
expect(this).toBe(thisArg); expect(this).toBe(thisArg);
}, thisArg); }, thisArg);
}); });

View file

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

View file

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

View file

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

View file

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