refactor: Bring lint config back to original strictness

This commit is contained in:
Joachim Van Herwegen 2023-10-30 14:32:21 +01:00
parent 7a007dc466
commit 3bb3004abb
52 changed files with 239 additions and 132 deletions

View File

@ -29,7 +29,7 @@ jobs:
with:
images: |
solidproject/community-server
# edge will always be executed (without latest tag), semver only on tag push events (with latest tag)
# Edge will always be executed (without latest tag), semver only on tag push events (with latest tag)
tags: |
type=edge
type=semver,pattern={{version}}

View File

@ -56,7 +56,7 @@ markdown_extensions:
- pymdownx.smartsymbols
- pymdownx.superfences:
custom_fences:
# need to fork the theme to make changes https://github.com/squidfunk/mkdocs-material/issues/3665#issuecomment-1060019924
# Need to fork the theme to make changes https://github.com/squidfunk/mkdocs-material/issues/3665#issuecomment-1060019924
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format

View File

@ -3,7 +3,7 @@ const jest = require('eslint-plugin-jest');
// Copied from https://github.com/antfu/eslint-config/blob/main/src/configs/typescript.ts
// Doing it like this, so we can make sure these only try to trigger on *.ts files,
// preventing issues with the *.js files.
// Preventing issues with the *.js files.
const typeAwareRules = {
'dot-notation': 'off',
'no-implied-eval': 'off',
@ -26,8 +26,7 @@ const typeAwareRules = {
'ts/unbound-method': 'error',
};
module.exports = antfu(
{},
const configs = antfu(
{
// Don't want to lint test assets, or TS snippets in markdown files
ignores: [ 'test/assets/*', '**/*.md/**/*.ts' ],
@ -56,6 +55,9 @@ module.exports = antfu(
},
rules: {
...typeAwareRules,
'ts/consistent-type-assertions': [ 'error', {
assertionStyle: 'as',
}],
'ts/naming-convention': [
'error',
{
@ -84,8 +86,22 @@ module.exports = antfu(
prefix: [ 'T' ],
},
],
'ts/explicit-function-return-type': [ 'error', {
allowExpressions: false,
allowTypedFunctionExpressions: false,
allowHigherOrderFunctions: false,
}],
'ts/no-base-to-string': 'error',
'ts/no-floating-promises': [ 'error', { ignoreVoid: false }],
'ts/promise-function-async': 'error',
'ts/no-unnecessary-boolean-literal-compare': 'error',
'ts/no-unnecessary-qualifier': 'error',
'ts/prefer-nullish-coalescing': 'error',
'ts/prefer-readonly': 'error',
'ts/prefer-reduce-type-parameter': 'error',
'ts/prefer-regexp-exec': 'error',
'ts/prefer-string-starts-ends-with': 'error',
'ts/require-array-sort-compare': 'error',
// These are not type specific, but we only care for TS files
'max-len': [ 'error', { code: 120, ignoreUrls: true }],
@ -104,16 +120,38 @@ module.exports = antfu(
// Might want to enable this one but has a drastic impact on the already existing code
'antfu/consistent-list-newline': 'off',
'arrow-body-style': [ 'error', 'as-needed', { requireReturnForObjectLiteral: false }],
'capitalized-comments': [ 'error', 'always', { ignoreConsecutiveComments: true }],
curly: [ 'error', 'all' ],
'default-case': 'error',
eqeqeq: [ 'error', 'always' ],
'for-direction': 'error',
'func-style': [ 'error', 'declaration' ],
'function-call-argument-newline': [ 'error', 'consistent' ],
'function-paren-newline': [ 'error', 'consistent' ],
'jsdoc/no-multi-asterisks': [ 'error', { allowWhitespace: true }],
'getter-return': [ 'error', { allowImplicit: true }],
'grouped-accessor-pairs': [ 'error', 'getBeforeSet' ],
'guard-for-in': 'error',
'line-comment-position': [ 'error', { position: 'above' }],
'linebreak-style': [ 'error', 'unix' ],
'multiline-comment-style': [ 'error', 'separate-lines' ],
// Need to override `allow` value
'no-console': [ 'error', { allow: [ '' ]}],
'no-constructor-return': 'error',
'no-dupe-else-if': 'error',
'no-else-return': [ 'error', { allowElseIf: false }],
'no-implicit-coercion': 'error',
'no-implicit-globals': 'error',
'no-lonely-if': 'error',
'no-plusplus': [ 'error', { allowForLoopAfterthoughts: true }],
'no-sync': [ 'error', { allowAtRootLevel: false }],
'node/prefer-global/buffer': 'off',
'node/prefer-global/process': 'off',
'no-useless-concat': 'error',
'no-useless-escape': 'error',
'operator-assignment': [ 'error', 'always' ],
'prefer-object-spread': 'error',
radix: 'error',
'require-unicode-regexp': 'error',
'require-yield': 'error',
'sort-imports': [
'error',
{
@ -125,6 +163,14 @@ module.exports = antfu(
},
],
'import/extensions': 'error',
'jsdoc/no-multi-asterisks': [ 'error', { allowWhitespace: true }],
// Might want to enable these
'node/prefer-global/buffer': 'off',
'node/prefer-global/process': 'off',
'style/array-bracket-spacing': [ 'error', 'always', {
singleValue: true,
objectsInArrays: false,
@ -133,24 +179,21 @@ module.exports = antfu(
// Conflicts with style/object-curly-spacing
'style/block-spacing': 'off',
'style/brace-style': [ 'error', '1tbs', { allowSingleLine: false }],
'style/generator-star-spacing': [ 'error', { before: false, after: true }],
'style/member-delimiter-style': [ 'error', {
multiline: { delimiter: 'semi', requireLast: true },
singleline: { delimiter: 'semi', requireLast: false },
}],
'style/no-extra-parens': [ 'error', 'all', {
conditionalAssign: false,
enforceForArrowConditionals: false,
ignoreJSX: 'all',
nestedBinaryExpressions: false,
returnAssign: false,
}],
'style/no-extra-parens': [ 'error', 'functions' ],
'style/object-curly-spacing': [ 'error', 'always', {
objectsInObjects: false,
arraysInObjects: false,
}],
'style/operator-linebreak': [ 'error', 'after' ],
'style/semi': [ 'error', 'always' ],
'style/semi-style': [ 'error', 'last' ],
'style/space-before-function-paren': [ 'error', 'never' ],
'style/switch-colon-spacing': 'error',
'style/quote-props': [ 'error', 'as-needed', {
keywords: false,
unnecessary: true,
@ -158,28 +201,80 @@ module.exports = antfu(
}],
'style/yield-star-spacing': [ 'error', 'after' ],
'test/prefer-lowercase-title': 'off',
'ts/adjacent-overload-signatures': 'error',
'ts/array-type': 'error',
'ts/ban-ts-comment': [ 'error', {
'ts-expect-error': true,
}],
'ts/consistent-indexed-object-style': [ 'error', 'record' ],
'ts/consistent-type-definitions': 'off',
'ts/explicit-member-accessibility': 'error',
'ts/method-signature-style': 'error',
'ts/no-confusing-non-null-assertion': 'error',
'ts/no-extraneous-class': [ 'error', {
allowConstructorOnly: false,
allowEmpty: false,
allowStaticOnly: false,
}],
'ts/no-inferrable-types': [ 'error', {
ignoreParameters: false,
ignoreProperties: false,
}],
'ts/prefer-for-of': 'error',
'ts/prefer-function-type': 'error',
'unicorn/better-regex': 'error',
'unicorn/empty-brace-spaces': 'error',
'unicorn/consistent-function-scoping': 'error',
'unicorn/expiring-todo-comments': [ 'error', {
ignoreDatesOnPullRequests: false,
terms: [ 'todo' ],
allowWarningComments: false,
}],
'unicorn/explicit-length-check': 'error',
'unicorn/new-for-builtins': 'error',
'unicorn/no-for-loop': 'error',
'unicorn/no-invalid-remove-event-listener': 'error',
'unicorn/no-lonely-if': 'error',
'unicorn/no-nested-ternary': 'error',
'unicorn/no-process-exit': 'error',
'unicorn/no-thenable': 'error',
'unicorn/no-useless-fallback-in-spread': 'error',
'unicorn/no-useless-length-check': 'error',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/no-useless-spread': 'error',
'unicorn/no-useless-undefined': 'error',
'unicorn/no-zero-fractions': 'error',
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-node-protocol': 'off',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-at': 'error',
'unicorn/prefer-code-point': 'error',
'unicorn/prefer-date-now': 'error',
'unicorn/prefer-default-parameters': 'error',
'unicorn/prefer-math-trunc': 'error',
'unicorn/prefer-native-coercion-functions': 'error',
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-object-from-entries': 'error',
'unicorn/prefer-optional-catch-binding': 'error',
'unicorn/prefer-reflect-apply': 'error',
'unicorn/prefer-regexp-test': 'error',
'unicorn/prefer-set-has': 'error',
'unicorn/prefer-set-size': 'error',
'unicorn/prefer-spread': 'error',
'unicorn/prefer-string-replace-all': 'error',
'unicorn/prefer-string-slice': 'error',
'unicorn/require-array-join-separator': 'error',
'unicorn/require-number-to-fixed-digits-argument': 'error',
// Might want to enable these
'unicorn/no-array-reduce': 'off',
'unicorn/no-array-for-each': 'off',
'unicorn/no-await-expression-member': 'off',
'unicorn/no-negated-condition': 'off',
'unicorn/no-object-as-default-parameter': 'off',
'unicorn/prefer-node-protocol': 'off',
'unused-imports/no-unused-vars': [
'error',
@ -216,6 +311,8 @@ module.exports = antfu(
'jest/prefer-strict-equal': 'off',
'jest/require-hook': 'off',
'test/prefer-lowercase-title': 'off',
'ts/naming-convention': 'off',
'ts/no-unsafe-argument': 'off',
'ts/no-unsafe-assignment': 'off',
@ -247,3 +344,12 @@ module.exports = antfu(
},
},
);
// The default ignore list contains all `output` folders, which conflicts with our src/http/output folder
// See https://github.com/antfu/eslint-config/blob/29f29f1e16d0187f5c870102f910d798acd9b874/src/globs.ts#L53
if (!configs[1].ignores.includes('**/output')) {
throw new Error('Unexpected data in config position. Check if antfu changed how it handles ignores.');
}
delete configs[1].ignores;
module.exports = configs;

View File

@ -3,7 +3,7 @@ const v8 = require('v8');
// Several parts inspired by https://github.com/renovatebot/renovate/blob/main/package.json
const ci = !!process.env.CI;
const ci = Boolean(process.env.CI);
const cpus = os.cpus();
const mem = os.totalmem();

View File

@ -1,5 +1,5 @@
#!/usr/bin/env ts-node
/* eslint-disable no-console */
/* eslint-disable import/extensions, no-console */
import * as readline from 'readline';
import simpleGit from 'simple-git';
import { version } from '../package.json';

View File

@ -18,7 +18,7 @@ import { readFile, writeFile } from 'fs-extra';
* @returns Promise with output string
*/
async function capitalizeListEntries(input: string): Promise<string> {
return input.replace(/^(\W*\* [a-z])/gmu, (match): string => match.toUpperCase());
return input.replaceAll(/^(\W*\* [a-z])/gmu, (match): string => match.toUpperCase());
}
/**

View File

@ -62,6 +62,7 @@ export class ConvertingErrorHandler extends ErrorHandler {
private async extractErrorDetails({ error, request }: ErrorHandlerArgs): Promise<PreparedArguments> {
if (!this.showStackTrace) {
delete error.stack;
// eslint-disable-next-line ts/no-unsafe-member-access
delete (error as any).cause;
}
const representation = new BasicRepresentation([ error ], error.metadata, INTERNAL_ERROR, false);

View File

@ -29,7 +29,7 @@ export class LinkRelMetadataWriter extends MetadataWriter {
const values = input.metadata.getAll(predicate)
.map((term): string => `<${term.value}>; rel="${relValue}"`);
if (values.length > 0) {
this.logger.debug(`Adding Link header ${values}`);
this.logger.debug(`Adding Link header ${values.join(',')}`);
addHeader(input.response, 'Link', values);
}
}

View File

@ -33,7 +33,7 @@ export class WacAllowMetadataWriter extends MetadataWriter {
}
}
private aclToPermission(aclTerm: Term): string {
private aclToPermission(this: void, aclTerm: Term): string {
return aclTerm.value.slice(ACL.namespace.length).toLowerCase();
}

View File

@ -65,7 +65,7 @@ export class MaxKeyLengthStorage<T> implements KeyValueStorage<string, T> {
const parts = key.split('/');
// Prevent non-hashed keys with the prefix to prevent false hits
if (parts[parts.length - 1].startsWith(this.hashPrefix)) {
if (parts.at(-1)?.startsWith(this.hashPrefix)) {
throw new NotImplementedHttpError(`Unable to store keys starting with ${this.hashPrefix}`);
}

View File

@ -38,7 +38,7 @@ export function isGuarded<T extends NodeJS.EventEmitter>(stream: T): stream is G
function guardingErrorListener(this: Guarded, error: Error): void {
// Only fall back to this if no new listeners are attached since guarding started.
const errorListeners = this.listeners('error');
if (errorListeners[errorListeners.length - 1] === guardingErrorListener) {
if (errorListeners.at(-1) === guardingErrorListener) {
this[guardedErrors].push(error);
if (!this[guardedTimeout]) {
this[guardedTimeout] = setTimeout((): void => {

View File

@ -38,7 +38,7 @@ const logger = getLoggerFor('HeaderUtil');
export function transformQuotedStrings(input: string): { result: string; replacements: Record<string, string> } {
let idx = 0;
const replacements: Record<string, string> = {};
const result = input.replace(/"(?:[^"\\]|\\.)*"/gu, (match): string => {
const result = input.replaceAll(/"(?:[^"\\]|\\.)*"/gu, (match): string => {
// Not all characters allowed in quoted strings, see BNF above
if (!QUOTED_STRING.test(match)) {
logger.warn(`Invalid quoted string in header: ${match}`);

View File

@ -173,7 +173,6 @@ async function findNextSorted<T>(iterators: AsyncIterator<T>[], results: (T | un
export async function* sortedAsyncMerge<T>(iterators: AsyncIterator<T>[], comparator?: (left: T, right: T) => number):
AsyncIterable<T> {
if (!comparator) {
// eslint-disable-next-line style/no-extra-parens
comparator = (left, right): number => left < right ? -1 : (left > right ? 1 : 0);
}

View File

@ -15,7 +15,7 @@ import { errorTermsToMetadata } from './errors/HttpErrorUtil';
* @returns The potentially changed path (POSIX).
*/
function windowsToPosixPath(path: string): string {
return path.replace(/\\+/gu, '/');
return path.replaceAll(/\\+/gu, '/');
}
/**

View File

@ -16,7 +16,7 @@ export function splitCommaSeparated(input: string): string[] {
* @returns The sanitized output.
*/
export function sanitizeUrlPart(urlPart: string): string {
return urlPart.replace(/\W/gu, '-');
return urlPart.replaceAll(/\W/gu, '-');
}
/**

View File

@ -4,7 +4,7 @@
* @param ids - IDs of the element (empty to retrieve all elements)
*/
export function getElements(...ids) {
ids = ids.length ? ids : [ ...document.querySelectorAll('[id]') ].map(e => e.id);
ids = ids.length > 0 ? ids : [ ...document.querySelectorAll('[id]') ].map(e => e.id);
return Object.fromEntries(ids.map(id => [ id, document.getElementById(id) ]));
}

View File

@ -60,7 +60,7 @@ describe('A BasicResponseWriter', (): void => {
it('serializes metadata if there is metadata.', async(): Promise<void> => {
result = { statusCode: 201, metadata: new RepresentationMetadata() };
metadataWriter.handle = jest.fn();
jest.spyOn(metadataWriter, 'handle').mockImplementation();
await writer.handle({ response, result });
expect(metadataWriter.handle).toHaveBeenCalledTimes(1);
expect(metadataWriter.handle).toHaveBeenLastCalledWith({ response, metadata: result.metadata });
@ -77,6 +77,7 @@ describe('A BasicResponseWriter', (): void => {
result = { statusCode: 201, data };
response = new PassThrough();
// eslint-disable-next-line jest/prefer-spy-on
response.writeHead = jest.fn();
const end = new Promise<void>((resolve): void => {

View File

@ -27,7 +27,7 @@ describe('A LogoutHandler', (): void => {
expect(outputMetadata?.get(SOLID_HTTP.terms.accountCookie)?.value).toBe(cookie);
const date = outputMetadata?.get(SOLID_HTTP.terms.accountCookieExpiration);
expect(date).toBeDefined();
expect(new Date(date!.value).getTime()).toBeLessThan(new Date().getTime());
expect(new Date(date!.value).getTime()).toBeLessThan(Date.now());
expect(cookieStore.delete).toHaveBeenCalledTimes(1);
expect(cookieStore.delete).toHaveBeenLastCalledWith(cookie);
});

View File

@ -3,7 +3,7 @@ import { BaseLogger, WrappingLogger } from '../../../src/logging/Logger';
import type { LogMetadata, SimpleLogger } from '../../../src/logging/Logger';
class DummyLogger extends BaseLogger {
log(): this {
public log(): this {
return this;
}
}

View File

@ -25,7 +25,7 @@ function simplifyQuery(query: string | string[]): string {
if (Array.isArray(query)) {
query = query.join(' ');
}
return query.replace(/\n/gu, ' ').trim();
return query.replaceAll('\n', ' ').trim();
}
describe('A SparqlDataAccessor', (): void => {

View File

@ -39,7 +39,7 @@ describe('An RdfPatcher,', (): void => {
};
patcher.handle.mockImplementation(
async(input: RepresentationPatcherInput<RdfDatasetRepresentation>):
Promise<RdfDatasetRepresentation> => Promise.resolve(input.representation!),
Promise<RdfDatasetRepresentation> => input.representation!,
);
rdfPatcher = new RdfPatcher(patcher);

View File

@ -143,7 +143,7 @@ export function mockFileSystem(rootFilepath?: string, time?: Date): { data: any
return { folder: cache, name: 'data' };
}
const name = parts.slice(-1)[0];
const name = parts.at(-1) as string;
parts = parts.slice(0, -1);
let folder = cache.data;
parts.forEach((part): any => {