fix: eslint config

This commit is contained in:
Eli Bosley
2024-10-18 14:02:35 -04:00
parent 98f2603525
commit 92b5f2226e
29 changed files with 574 additions and 3322 deletions
-47
View File
@@ -1,47 +0,0 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
root: true,
plugins: [
'@typescript-eslint/eslint-plugin',
'unused-imports',
'eslint-plugin-unicorn',
],
ignorePatterns: ['src/graphql/generated/**/*.ts', '*.test.ts', 'tsup.config.ts', 'vite.config.ts'],
parser: '@typescript-eslint/parser',
rules: {
'@typescript-eslint/no-redundant-type-constituents': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/naming-convention': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/consistent-type-imports': [
'warn',
{ fixStyle: 'inline-type-imports' },
],
'unicorn/numeric-separators-style': [
'error',
{ number: { minimumDigits: 0, groupLength: 3 } },
],
'import/no-cycle': 'off', // Change this to "error" to find circular imports
'@typescript-eslint/no-use-before-define': ['error'],
'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 1 }],
},
overrides: [
{
files: ['*.ts'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
],
};
+21
View File
@@ -0,0 +1,21 @@
import type { Linter } from 'eslint';
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommended, {
rules: {
'@typescript-eslint/no-redundant-type-constituents': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/naming-convention': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'no-use-before-define': ['off'],
'no-multiple-empty-lines': ['error', { max: 1, maxBOF: 0, maxEOF: 1 }],
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
},
});
+473 -3196
View File
File diff suppressed because it is too large Load Diff
+10 -11
View File
@@ -32,8 +32,8 @@
"codegen:watch": "DOTENV_CONFIG_PATH='./.env.staging' graphql-codegen --config codegen.yml --watch -r dotenv/config",
"codegen:local": "NODE_TLS_REJECT_UNAUTHORIZED=0 MOTHERSHIP_GRAPHQL_LINK='https://mothership.localhost/ws' graphql-codegen-esm --config codegen.yml --watch",
"tsc": "tsc --noEmit",
"lint": "DEBUG=eslint:cli-engine eslint . --config .eslintrc.cjs",
"lint:fix": "DEBUG=eslint:cli-engine eslint . --fix --config .eslintrc.cjs",
"lint": "eslint --flag unstable_ts_config --config .eslintrc.ts src/",
"lint:fix": "eslint --flag unstable_ts_config --fix --config .eslintrc.ts src/",
"test:watch": "vitest --pool=forks",
"test": "vitest run --pool=forks",
"coverage": "vitest run --coverage",
@@ -178,24 +178,17 @@
"@types/uuid": "^10.0.0",
"@types/ws": "^8.5.10",
"@types/wtfnode": "^0.7.3",
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
"@unraid/eslint-config": "github:unraid/eslint-config",
"@vitest/coverage-v8": "^2.1.1",
"@vitest/ui": "^2.1.1",
"camelcase-keys": "^8.0.2",
"cz-conventional-changelog": "3.3.0",
"eslint": "^8.56.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^53.0.0",
"eslint-plugin-unused-imports": "^3.2.0",
"eslint": "^9.12.0",
"execa": "^7.1.1",
"filter-obj": "^5.1.0",
"got": "^13",
"graphql-codegen-typescript-validation-schema": "^0.14.1",
"ip-regex": "^5.0.0",
"jiti": "^2.3.3",
"json-difference": "^1.16.1",
"map-obj": "^5.0.2",
"p-props": "^5.0.0",
@@ -205,6 +198,7 @@
"pretty-ms": "^8.0.0",
"standard-version": "^9.5.0",
"typescript": "^5.4.5",
"typescript-eslint": "^8.10.0",
"typesync": "^0.12.1",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.1.1",
@@ -217,5 +211,10 @@
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"overrides": {
"eslint": {
"jiti": "2"
}
}
}
@@ -4,7 +4,6 @@ import * as apiKeyValidator from '@app/mothership/api-key/validate-api-key-with-
import { describe, expect, it, vi } from 'vitest';
import { type RecursivePartial } from '@app/types/index';
import { type RootState } from '@app/store/index';
import { logoutUser } from '@app/store/modules/config';
describe('apiKeyCheckJob Tests', () => {
it('API Check Job (with success)', async () => {
+6
View File
@@ -0,0 +1,6 @@
/* eslint-disable */
process.title = 'unraid-api';
setInterval(() => {
console.log('I NEED TO DIE');
}, 5_000);
@@ -0,0 +1,10 @@
/* eslint-disable */
process.title = 'unraid-api';
setInterval(() => {
console.log('I NEED TO DIE (but i am very hard to kill)');
}, 5_000);
process.on('SIGTERM', () => {
// Do nothing
console.log('you cant kill me haha');
});
+1 -2
View File
@@ -258,8 +258,7 @@ const getVerbosity = (argv: string[]): Verbosity => {
return '';
};
// eslint-disable-next-line complexity
export const report = async (...argv: string[]) => {
// Check if the user has raw output enabled
const rawOutput = argv.includes('--raw');
+1 -1
View File
@@ -4,7 +4,7 @@ import { AppError } from '@app/core/errors/app-error';
* API key error.
*/
export class ApiKeyError extends AppError {
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor(message: string) {
super(message);
}
+1 -1
View File
@@ -30,7 +30,7 @@ export const getPermissions = async function (context: CoreContext): Promise<Cor
const grants = Object.entries(ac.getGrants())
.map(([name, grant]) => {
// @ts-expect-error - $extend and grants are any
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { $extend: _, ...grants } = grant;
return [name, grants];
})
+4 -4
View File
@@ -78,7 +78,7 @@ export const updateDisk = async (context: Context): Promise<Result> => {
7: '7 hours',
8: '8 hours',
9: '9 hours',
/* eslint-enable @typescript-eslint/naming-convention */
});
// Defines the type of partition layout to create when formatting hard drives 2TB in size and smaller **only**. (All devices larger then 2TB are always set up with GPT partition tables.)
@@ -89,7 +89,7 @@ export const updateDisk = async (context: Context): Promise<Result> => {
1: 'MBR: unaligned',
2: 'MBR: 4K-aligned',
/* eslint-enable @typescript-eslint/naming-convention */
});
// Selects the method to employ when writing to enabled disk in parity protected array.
@@ -98,7 +98,7 @@ export const updateDisk = async (context: Context): Promise<Result> => {
0: 'read/modify/write',
1: 'reconstruct write',
/* eslint-enable @typescript-eslint/naming-convention */
});
// Defines the default file system type to create when an * unmountable * array device is formatted.
@@ -111,7 +111,7 @@ export const updateDisk = async (context: Context): Promise<Result> => {
'luks:xfs': 'xfs - encrypted',
'luks:btrfs': 'btrfs - encrypted',
'luks:reiserfs': 'reiserfs - encrypted',
/* eslint-enable @typescript-eslint/naming-convention */
});
const {
+1 -2
View File
@@ -8,8 +8,7 @@ export type Options = NotifierOptions
*/
export class HttpNotifier extends Notifier {
readonly $http = got;
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor(options: Options) {
super(options);
}
@@ -23,7 +23,7 @@ type ConfigObject<T> = T extends 'flash'
* @param mode 'flash' or 'memory', changes what fields are included in the writeable payload
* @returns
*/
// eslint-disable-next-line complexity
export const getWriteableConfig = <T extends ConfigType>(
config: ConfigSliceState,
mode: T
@@ -32,7 +32,7 @@ export const getWriteableConfig = <T extends ConfigType>(
const { api, local, notifier, remote, upc, connectionStatus } = config;
// Create new state
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const newState: ConfigObject<T> = {
api: {
version: api?.version ?? initialState.api.version,
+1 -1
View File
@@ -43,7 +43,7 @@ const fixObjectArrays = (object: Record<string, any>) => {
// An object without any array items
const filteredObject = includeKeys(object, (key, value) => {
// eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
const [, name, index] = [...((key).match(/(.*):(\d+$)/) ?? [])];
if (!name || !index) {
return true;
@@ -8,6 +8,6 @@ export const getPermissions = (role: string): Record<string, Record<string, stri
const grants: Record<string, Record<string, string[]>> = ac.getGrants();
const { $extend, ...roles } = grants[role] ?? {};
const inheritedRoles = Array.isArray($extend) ? $extend.map(role => getPermissions(role))[0] : {};
// eslint-disable-next-line prefer-object-spread
return Object.assign({}, roles, inheritedRoles);
};
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { getters } from '@app/store';
import type { DiskShare, Share, UserShare } from '@app/core/types/states/share';
import { type ArrayDisk } from '@app/graphql/generated/api/types';
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable */
import * as types from './graphql.js';
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
@@ -1,4 +1,3 @@
/* eslint-disable */
import { z } from 'zod'
import { AccessUrlInput, ArrayCapacityBytesInput, ArrayCapacityInput, ClientType, ConfigErrorState, DashboardAppsInput, DashboardArrayInput, DashboardCaseInput, DashboardConfigInput, DashboardDisplayInput, DashboardInput, DashboardOsInput, DashboardServiceInput, DashboardServiceUptimeInput, DashboardTwoFactorInput, DashboardTwoFactorLocalInput, DashboardTwoFactorRemoteInput, DashboardVarsInput, DashboardVersionsInput, DashboardVmsInput, EventType, Importance, NetworkInput, NotificationInput, NotificationStatus, PingEventSource, RegistrationState, RemoteAccessEventActionType, RemoteAccessInput, RemoteGraphQLClientInput, RemoteGraphQLEventType, RemoteGraphQLServerInput, ServerStatus, URL_TYPE, UpdateType } from '@app/graphql/generated/client/graphql'
+2 -2
View File
@@ -281,7 +281,7 @@ export const generateDevices = async (): Promise<Devices> => {
const usbHubs = await execa('cat /sys/bus/usb/drivers/hub/*/modalias', { shell: true })
.then(({ stdout }) =>
stdout.split('\n').map((line) => {
// eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
const [, id] = line.match(/usb:v(\w{9})/) ?? [];
return id.replace('p', ':');
})
@@ -316,7 +316,7 @@ export const generateDevices = async (): Promise<Devices> => {
// Parse the line
const [, _] = line.split(/[ \t]{2,}/).filter(Boolean);
// eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
const match = _.match(/^(\S+)\s(.*)/)?.slice(1);
// If there's no match return nothing
@@ -128,8 +128,7 @@ const getUrlTypeFromFqdn = (fqdnType: string): URL_TYPE => {
return URL_TYPE.WIREGUARD;
}
};
// eslint-disable-next-line complexity
export const getServerIps = (
state: RootState = store.getState()
): { urls: AccessUrl[]; errors: Error[] } => {
+1 -5
View File
@@ -32,8 +32,6 @@ export const getWsConnectionCount = () => Object.values(subscriptions).filter(su
*/
export const getWsConnectionCountInChannel = (channel: string) => Object.values(subscriptions).filter(subscription => subscription.channels.includes(channel)).length;
export const hasSubscribedToChannel = (id: string, channel: string) => {
graphqlLogger.debug('Subscribing to %s', channel);
@@ -51,7 +49,6 @@ export const hasSubscribedToChannel = (id: string, channel: string) => {
subscriptions[id].channels.push(channel);
};
/**
* Create a pubsub subscription.
* @param channel The pubsub channel to subscribe to.
@@ -74,8 +71,7 @@ export const createSubscription = (channel: string, resource?: string) => ({
return pubsub.asyncIterator(channel);
},
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const getLocalServer = (getState = store.getState): Array<Server> => {
const { emhttp, config, minigraph } = getState();
const guid = emhttp.var.regGuid;
+2 -3
View File
@@ -56,12 +56,11 @@ export const isAPIStateDataFullyLoaded = (state = store.getState()) => {
Boolean(emhttp.var.version)
);
};
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class GraphQLClient {
public static instance: ApolloClient<NormalizedCacheObject> | null = null;
public static client: Client | null = null;
// eslint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {}
/**
@@ -1,4 +1,3 @@
/* eslint-disable max-depth */
import { minigraphLogger, mothershipLogger } from '@app/core/log';
import { GraphQLClient } from './graphql-client';
import { store } from '@app/store';
+2 -2
View File
@@ -11,12 +11,12 @@ export function buildDelayFunction(
const baseDelay = jitter ? initial : initial / 2;
return (count: number) => {
// eslint-disable-next-line no-mixed-operators
let delay = Math.min(max, baseDelay * 2 ** count);
if (jitter) {
// We opt for a full jitter approach for a mostly uniform distribution,
// but bound it within initialDelay and delay for everyone's sanity.
// eslint-disable-next-line operator-assignment
delay = Math.random() * delay;
}
@@ -18,8 +18,7 @@ export class RemoteAccessController implements IRemoteAccessController {
static _instance: RemoteAccessController | null = null;
activeRemoteAccess: UpnpRemoteAccess | StaticRemoteAccess | null = null;
notifier: UnraidLocalNotifier = new UnraidLocalNotifier({ level: 'info' });
// eslint-disable-next-line @typescript-eslint/no-useless-constructor, @typescript-eslint/no-empty-function
constructor() {}
public static get instance(): RemoteAccessController {
@@ -114,7 +114,7 @@ describe.sequential('NotificationsService', () => {
}
// currently unused b/c of difficulty implementing NotificationOverview tests
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function forAllTypesAndImportances(
action: (type: NotificationType, importance: Importance) => Promise<void>
) {
@@ -134,7 +134,7 @@ describe.sequential('NotificationsService', () => {
}
// currently unused b/c of difficulty implementing NotificationOverview tests
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function diffOverview(current: NotificationOverview, previous: NotificationOverview) {
return Object.fromEntries(
Object.entries(current).map(([key]) => {
+30
View File
@@ -0,0 +1,30 @@
import { Cron, Expression, Initializer } from '@reflet/cron';
import { store } from '@app/store';
import { enableUpnp } from '@app/store/modules/upnp';
import { upnpLogger } from '@app/core/log';
export class UPNPJobManager extends Initializer<typeof UPNPJobManager> {
@Cron.PreventOverlap
@Cron(Expression.EVERY_30_MINUTES)
async renewUpnpLeaseJob() {
upnpLogger.trace('Running UPNP Renewal Job');
await store.dispatch(enableUpnp());
}
}
export const initUpnpJobs = (): boolean => {
if (!upnpJobs) {
upnpJobs = UPNPJobManager.init();
}
upnpJobs.get('renewUpnpLeaseJob').start();
return upnpJobs.get('renewUpnpLeaseJob').running ?? false;
};
export const stopUpnpJobs = (): boolean => {
upnpLogger.debug('Stopping UPNP Jobs');
upnpJobs?.get('renewUpnpLeaseJob').stop();
return upnpJobs?.get('renewUpnpLeaseJob').running ?? false;
};
let upnpJobs: ReturnType<typeof UPNPJobManager.init<UPNPJobManager>> | null = null;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"include": [
"src/**/*",
".eslintrc.cjs",
".eslintrc.ts",
"vite.config.ts"
],
"exclude": [
-30
View File
@@ -1,30 +0,0 @@
import { execSync } from 'child_process';
import 'dotenv/config';
import { defineConfig } from 'tsup';
import { version } from './package.json';
import getTags from './scripts/get-tags.mjs'
export default defineConfig({
name: 'tsup',
target: 'node18',
entry: {
'unraid-api': 'src/cli.ts',
index: 'src/index.ts',
},
metafile: true,
splitting: false,
sourcemap: true,
clean: true,
external: ['@vmngr/libvirt'],
esbuildOptions(options) {
if (!options.define) options.define = {};
const tags = getTags(process.env);
options.define['process.env.VERSION'] = tags.isTagged
? `"${version}"`
: `"${version}+${tags.shortSha}"`;
},
});