diff --git a/eslint/general.js b/eslint/general.js index ccacf5ae9..b274a15a4 100644 --- a/eslint/general.js +++ b/eslint/general.js @@ -101,6 +101,7 @@ module.exports = { 'ts/explicit-member-accessibility': 'error', 'ts/method-signature-style': 'error', 'ts/no-confusing-non-null-assertion': 'error', + 'ts/no-explicit-any': 'error', 'ts/no-extraneous-class': [ 'error', { allowConstructorOnly: false, allowEmpty: false, diff --git a/eslint/test.js b/eslint/test.js index ad5bb33d4..c62c4efe5 100644 --- a/eslint/test.js +++ b/eslint/test.js @@ -32,6 +32,7 @@ module.exports = { 'test/prefer-lowercase-title': 'off', 'ts/naming-convention': 'off', + 'ts/no-explicit-any': 'off', 'ts/no-unsafe-argument': 'off', 'ts/no-unsafe-assignment': 'off', 'ts/no-unsafe-call': 'off', diff --git a/src/http/output/error/ConvertingErrorHandler.ts b/src/http/output/error/ConvertingErrorHandler.ts index 1a0687529..d58150dec 100644 --- a/src/http/output/error/ConvertingErrorHandler.ts +++ b/src/http/output/error/ConvertingErrorHandler.ts @@ -62,8 +62,8 @@ export class ConvertingErrorHandler extends ErrorHandler { private async extractErrorDetails({ error, request }: ErrorHandlerArgs): Promise { if (!this.showStackTrace) { delete error.stack; - // eslint-disable-next-line ts/no-unsafe-member-access - delete (error as any).cause; + // Cheating here to delete a readonly field + delete (error as { cause: unknown }).cause; } const representation = new BasicRepresentation([ error ], error.metadata, INTERNAL_ERROR, false); const identifier = { path: representation.metadata.identifier.value }; diff --git a/src/http/representation/BasicRepresentation.ts b/src/http/representation/BasicRepresentation.ts index 9c961805b..4cb1a7756 100644 --- a/src/http/representation/BasicRepresentation.ts +++ b/src/http/representation/BasicRepresentation.ts @@ -35,7 +35,7 @@ export class BasicRepresentation implements Representation { * @param binary - Whether the representation is a binary or object stream */ public constructor( - data: Guarded | Readable | any[] | string, + data: Guarded | Readable | unknown[] | string, metadata: RepresentationMetadata | MetadataRecord, binary?: boolean, ); @@ -47,7 +47,7 @@ export class BasicRepresentation implements Representation { * @param binary - Whether the representation is a binary or object stream */ public constructor( - data: Guarded | Readable | any[] | string, + data: Guarded | Readable | unknown[] | string, metadata: RepresentationMetadata | MetadataRecord, contentType?: string, binary?: boolean, @@ -59,7 +59,7 @@ export class BasicRepresentation implements Representation { * @param binary - Whether the representation is a binary or object stream */ public constructor( - data: Guarded | Readable | any[] | string, + data: Guarded | Readable | unknown[] | string, contentType: string, binary?: boolean, ); @@ -71,7 +71,7 @@ export class BasicRepresentation implements Representation { * @param binary - Whether the representation is a binary or object stream */ public constructor( - data: Guarded | Readable | any[] | string, + data: Guarded | Readable | unknown[] | string, identifier: MetadataIdentifier, metadata?: MetadataRecord, binary?: boolean, @@ -84,14 +84,14 @@ export class BasicRepresentation implements Representation { * @param binary - Whether the representation is a binary or object stream */ public constructor( - data: Guarded | Readable | any[] | string, + data: Guarded | Readable | unknown[] | string, identifier: MetadataIdentifier, contentType?: string, binary?: boolean, ); public constructor( - data?: Readable | any[] | string, + data?: Readable | unknown[] | string, metadata?: RepresentationMetadata | MetadataRecord | MetadataIdentifier | string, metadataRest?: MetadataRecord | string | boolean, binary?: boolean, @@ -109,8 +109,7 @@ export class BasicRepresentation implements Representation { } if (!isRepresentationMetadata(metadata) || typeof metadataRest === 'string') { // This combination will always match with a valid overload - // eslint-disable-next-line ts/no-unsafe-argument - metadata = new RepresentationMetadata(metadata as any, metadataRest as any); + metadata = new RepresentationMetadata(metadata as RepresentationMetadata, metadataRest as string); } this.metadata = metadata; diff --git a/src/http/representation/RepresentationMetadata.ts b/src/http/representation/RepresentationMetadata.ts index d85a0f66a..e96465752 100644 --- a/src/http/representation/RepresentationMetadata.ts +++ b/src/http/representation/RepresentationMetadata.ts @@ -15,7 +15,7 @@ export type MetadataGraph = NamedNode | BlankNode | DefaultGraph | string; /** * Determines whether the object is a `RepresentationMetadata`. */ -export function isRepresentationMetadata(object: any): object is RepresentationMetadata { +export function isRepresentationMetadata(object: unknown): object is RepresentationMetadata { return typeof (object as RepresentationMetadata)?.setMetadata === 'function'; } @@ -240,7 +240,7 @@ export class RepresentationMetadata { * @param graph - Optional graph of where to add the values to. */ public add(predicate: NamedNode, object: MetadataValue, graph?: MetadataGraph): this { - return this.forQuads(predicate, object, (pred, obj): any => this.addQuad(this.id, pred, obj, graph)); + return this.forQuads(predicate, object, (pred, obj): unknown => this.addQuad(this.id, pred, obj, graph)); } /** @@ -250,7 +250,7 @@ export class RepresentationMetadata { * @param graph - Optional graph of where to remove the values from. */ public remove(predicate: NamedNode, object: MetadataValue, graph?: MetadataGraph): this { - return this.forQuads(predicate, object, (pred, obj): any => this.removeQuad(this.id, pred, obj, graph)); + return this.forQuads(predicate, object, (pred, obj): unknown => this.removeQuad(this.id, pred, obj, graph)); } /** @@ -290,8 +290,12 @@ export class RepresentationMetadata { ): boolean { // This works with N3.js but at the time of writing the typings have not been updated yet. // If you see this line of code check if the typings are already correct and update this if so. - // eslint-disable-next-line ts/no-unsafe-call - return (this.store.has as any)(this.id, predicate, object, graph) as boolean; + return (this.store as unknown as { + has: (subject: Term, + predicate: Term | string | null, + object: Term | string | null, + graph: Term | string | null) => boolean; + }).has(this.id, predicate, object, graph) as boolean; } /** diff --git a/src/identity/configuration/IdentityProviderFactory.ts b/src/identity/configuration/IdentityProviderFactory.ts index 026ce76aa..094750a4a 100644 --- a/src/identity/configuration/IdentityProviderFactory.ts +++ b/src/identity/configuration/IdentityProviderFactory.ts @@ -187,14 +187,20 @@ export class IdentityProviderFactory implements ProviderFactory { provider.use(async(ctx, next): Promise => { const accepts = ctx.accepts.bind(ctx); - // Using `any` typings to make sure we support all different versions of `ctx.accepts` - ctx.accepts = (...types): any => { + // This is how you get the correct typing for an overloaded function + type AcceptFn = { + (): string[]; + (...types: string[]): string | false; + (types: string[]): string | false; + }; + + ctx.accepts = ((...types): string[] | string | false => { // Make sure we only override our specific case if (types.length === 2 && types[0] === 'json' && types[1] === 'html') { return 'html'; } return accepts(...types as string[]); - }; + }) as AcceptFn; return next(); }); @@ -257,7 +263,7 @@ export class IdentityProviderFactory implements ProviderFactory { * Checks if the given token is an access token. * The AccessToken interface is not exported, so we have to access it like this. */ - private isAccessToken(token: any): token is KoaContextWithOIDC['oidc']['accessToken'] { + private isAccessToken(token: unknown): token is KoaContextWithOIDC['oidc']['accessToken'] { return (token as KoaContextWithOIDC['oidc']['accessToken'])?.kind === 'AccessToken'; } @@ -270,7 +276,7 @@ export class IdentityProviderFactory implements ProviderFactory { // Some fields are still missing, see https://github.com/CommunitySolidServer/CommunitySolidServer/issues/1154#issuecomment-1040233385 config.findAccount = async(ctx: KoaContextWithOIDC, sub: string): Promise => ({ accountId: sub, - async claims(): Promise<{ sub: string; [key: string]: any }> { + async claims(): Promise<{ sub: string; [key: string]: unknown }> { return { sub, webid: sub, azp: ctx.oidc.client?.clientId }; }, }); diff --git a/src/identity/interaction/ControlHandler.ts b/src/identity/interaction/ControlHandler.ts index 0c0506862..a50d5c5c4 100644 --- a/src/identity/interaction/ControlHandler.ts +++ b/src/identity/interaction/ControlHandler.ts @@ -1,5 +1,6 @@ +import type { Json } from '../../util/Json'; import { ACCOUNT_ID_KEY } from './account/AccountIdRoute'; -import type { Json, JsonRepresentation } from './InteractionUtil'; +import type { JsonRepresentation } from './InteractionUtil'; import type { JsonInteractionHandlerInput } from './JsonInteractionHandler'; import { JsonInteractionHandler } from './JsonInteractionHandler'; import type { InteractionRoute } from './routing/InteractionRoute'; diff --git a/src/identity/interaction/InteractionUtil.ts b/src/identity/interaction/InteractionUtil.ts index 3a1646077..6c3541884 100644 --- a/src/identity/interaction/InteractionUtil.ts +++ b/src/identity/interaction/InteractionUtil.ts @@ -3,16 +3,12 @@ import type Provider from '../../../templates/types/oidc-provider'; import type { RepresentationMetadata } from '../../http/representation/RepresentationMetadata'; import { getLoggerFor } from '../../logging/LogUtil'; import { BadRequestHttpError } from '../../util/errors/BadRequestHttpError'; +import type { Json } from '../../util/Json'; import type { Interaction } from './InteractionHandler'; import Dict = NodeJS.Dict; const logger = getLoggerFor('AccountUtil'); -/** - * A JSON object. - */ -export type Json = string | number | boolean | Dict | Json[]; - /** * Contains a JSON object and any associated metadata. * Similar to a {@link Representation} but with all the data in memory instead of as a stream diff --git a/src/identity/interaction/JsonConversionHandler.ts b/src/identity/interaction/JsonConversionHandler.ts index 80af8ada1..d165ca0d7 100644 --- a/src/identity/interaction/JsonConversionHandler.ts +++ b/src/identity/interaction/JsonConversionHandler.ts @@ -3,10 +3,10 @@ import type { Representation } from '../../http/representation/Representation'; import { RepresentationMetadata } from '../../http/representation/RepresentationMetadata'; import type { RepresentationConverter } from '../../storage/conversion/RepresentationConverter'; import { APPLICATION_JSON } from '../../util/ContentTypes'; +import type { Json } from '../../util/Json'; import { readJsonStream } from '../../util/StreamUtil'; import type { InteractionHandlerInput } from './InteractionHandler'; import { InteractionHandler } from './InteractionHandler'; -import type { Json } from './InteractionUtil'; import type { JsonInteractionHandler, JsonInteractionHandlerInput } from './JsonInteractionHandler'; /** diff --git a/src/identity/interaction/JsonInteractionHandler.ts b/src/identity/interaction/JsonInteractionHandler.ts index 9846c95eb..7ccc95b9d 100644 --- a/src/identity/interaction/JsonInteractionHandler.ts +++ b/src/identity/interaction/JsonInteractionHandler.ts @@ -1,8 +1,9 @@ import type { RepresentationMetadata } from '../../http/representation/RepresentationMetadata'; import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier'; import { AsyncHandler } from '../../util/handlers/AsyncHandler'; +import type { Json } from '../../util/Json'; import type { Interaction } from './InteractionHandler'; -import type { Json, JsonRepresentation } from './InteractionUtil'; +import type { JsonRepresentation } from './InteractionUtil'; import Dict = NodeJS.Dict; export interface JsonInteractionHandlerInput { diff --git a/src/identity/interaction/OidcControlHandler.ts b/src/identity/interaction/OidcControlHandler.ts index 7da91bc8c..0282254b0 100644 --- a/src/identity/interaction/OidcControlHandler.ts +++ b/src/identity/interaction/OidcControlHandler.ts @@ -1,5 +1,5 @@ +import type { Json } from '../../util/Json'; import { ControlHandler } from './ControlHandler'; -import type { Json } from './InteractionUtil'; import type { JsonInteractionHandlerInput } from './JsonInteractionHandler'; /** diff --git a/src/identity/interaction/StaticInteractionHandler.ts b/src/identity/interaction/StaticInteractionHandler.ts index 6833a2d2f..661445099 100644 --- a/src/identity/interaction/StaticInteractionHandler.ts +++ b/src/identity/interaction/StaticInteractionHandler.ts @@ -1,4 +1,5 @@ -import type { Json, JsonRepresentation } from './InteractionUtil'; +import type { Json } from '../../util/Json'; +import type { JsonRepresentation } from './InteractionUtil'; import { JsonInteractionHandler } from './JsonInteractionHandler'; /** diff --git a/src/identity/interaction/YupUtil.ts b/src/identity/interaction/YupUtil.ts index fb48caff6..242818658 100644 --- a/src/identity/interaction/YupUtil.ts +++ b/src/identity/interaction/YupUtil.ts @@ -1,11 +1,13 @@ import { string } from 'yup'; -import type { ObjectSchema, Schema, ValidateOptions } from 'yup'; +import type { AnyObject, Maybe, ObjectSchema, Schema, ValidateOptions } from 'yup'; import { BadRequestHttpError } from '../../util/errors/BadRequestHttpError'; import { createErrorMessage } from '../../util/errors/ErrorUtil'; +import type { Json } from '../../util/Json'; import { isUrl } from '../../util/StringUtil'; -import type { Json } from './InteractionUtil'; import Dict = NodeJS.Dict; +type BaseObjectSchema = ObjectSchema>; + // The builtin `url` validator of `yup` does not support localhost URLs, so we create a custom one here. // The reason for having a URL validator on the WebID is to prevent us from generating invalid ACL, // which would break the pod creation causing us to have an incomplete pod. @@ -20,16 +22,16 @@ export const URL_SCHEMA = string().trim().optional().test({ }, }); -function isObjectSchema(schema: Schema): schema is ObjectSchema { +function isObjectSchema(schema: Schema): schema is BaseObjectSchema { return schema.type === 'object'; } // `T` can't extend Schema since it could also be a Reference, which is a type `yup` doesn't export -type SchemaType = T extends ObjectSchema ? ObjectType : { required: boolean; type: string }; +type SchemaType = T extends BaseObjectSchema ? ObjectType : { required: boolean; type: string }; // The type of the fields in an object schema -type FieldType> = T extends { fields: Record } ? R : never; +type FieldType = T extends { fields: Record } ? R : never; // Simplified type we use to represent yup objects -type ObjectType> = +type ObjectType = { required: boolean; type: 'object'; fields: {[ K in FieldType ]: SchemaType }}; /** @@ -50,7 +52,7 @@ function parseSchemaDescription(schema: T): SchemaType { /** * Generates a simplified representation of a yup schema. */ -export function parseSchema>(schema: T): Pick, 'fields'> { +export function parseSchema(schema: T): Pick, 'fields'> { const result = parseSchemaDescription(schema); return { fields: result.fields }; } @@ -58,13 +60,12 @@ export function parseSchema>(schema: T): Pick>( +export async function validateWithError( schema: T, data: unknown, - options?: ValidateOptions, + options?: ValidateOptions, ): Promise { try { - // eslint-disable-next-line ts/no-unsafe-return return await schema.validate(data, options); } catch (error: unknown) { throw new BadRequestHttpError(createErrorMessage(error)); diff --git a/src/identity/interaction/account/util/BaseAccountStore.ts b/src/identity/interaction/account/util/BaseAccountStore.ts index f1e8aa0a2..200d398cb 100644 --- a/src/identity/interaction/account/util/BaseAccountStore.ts +++ b/src/identity/interaction/account/util/BaseAccountStore.ts @@ -22,9 +22,10 @@ export class BaseAccountStore extends Initializer implements AccountStore { private readonly storage: AccountLoginStorage<{ [ACCOUNT_TYPE]: typeof ACCOUNT_STORAGE_DESCRIPTION }>; private initialized = false; - public constructor(storage: AccountLoginStorage) { + // Wrong typings to prevent Components.js typing issues + public constructor(storage: AccountLoginStorage>) { super(); - this.storage = storage as typeof this.storage; + this.storage = storage as unknown as typeof this.storage; } // Initialize the type definitions diff --git a/src/identity/interaction/client-credentials/util/BaseClientCredentialsStore.ts b/src/identity/interaction/client-credentials/util/BaseClientCredentialsStore.ts index 51e043d28..eb075722f 100644 --- a/src/identity/interaction/client-credentials/util/BaseClientCredentialsStore.ts +++ b/src/identity/interaction/client-credentials/util/BaseClientCredentialsStore.ts @@ -27,9 +27,10 @@ export class BaseClientCredentialsStore extends Initializer implements ClientCre private initialized = false; - public constructor(storage: AccountLoginStorage) { + // Wrong typings to prevent Components.js typing issues + public constructor(storage: AccountLoginStorage>) { super(); - this.storage = storage as typeof this.storage; + this.storage = storage as unknown as typeof this.storage; } // Initialize the type definitions diff --git a/src/identity/interaction/login/ResolveLoginHandler.ts b/src/identity/interaction/login/ResolveLoginHandler.ts index 142376f97..ddba472a2 100644 --- a/src/identity/interaction/login/ResolveLoginHandler.ts +++ b/src/identity/interaction/login/ResolveLoginHandler.ts @@ -1,10 +1,11 @@ import { RepresentationMetadata } from '../../../http/representation/RepresentationMetadata'; import { getLoggerFor } from '../../../logging/LogUtil'; +import type { Json } from '../../../util/Json'; import { SOLID_HTTP } from '../../../util/Vocabularies'; import { ACCOUNT_SETTINGS_REMEMBER_LOGIN } from '../account/util/AccountStore'; import type { AccountStore } from '../account/util/AccountStore'; import type { CookieStore } from '../account/util/CookieStore'; -import type { Json, JsonRepresentation } from '../InteractionUtil'; +import type { JsonRepresentation } from '../InteractionUtil'; import { finishInteraction } from '../InteractionUtil'; import type { JsonInteractionHandlerInput } from '../JsonInteractionHandler'; import { JsonInteractionHandler } from '../JsonInteractionHandler'; diff --git a/src/identity/interaction/password/util/BasePasswordStore.ts b/src/identity/interaction/password/util/BasePasswordStore.ts index 495418fee..997f3f998 100644 --- a/src/identity/interaction/password/util/BasePasswordStore.ts +++ b/src/identity/interaction/password/util/BasePasswordStore.ts @@ -29,9 +29,10 @@ export class BasePasswordStore extends Initializer implements PasswordStore { private readonly saltRounds: number; private initialized = false; - public constructor(storage: AccountLoginStorage, saltRounds = 10) { + // Wrong typings to prevent Components.js typing issues + public constructor(storage: AccountLoginStorage>, saltRounds = 10) { super(); - this.storage = storage as typeof this.storage; + this.storage = storage as unknown as typeof this.storage; this.saltRounds = saltRounds; } diff --git a/src/identity/interaction/pod/util/BasePodStore.ts b/src/identity/interaction/pod/util/BasePodStore.ts index 5bd249781..f6f9d2ac3 100644 --- a/src/identity/interaction/pod/util/BasePodStore.ts +++ b/src/identity/interaction/pod/util/BasePodStore.ts @@ -44,9 +44,10 @@ export class BasePodStore extends Initializer implements PodStore { private initialized = false; - public constructor(storage: AccountLoginStorage, manager: PodManager, visible = false) { + // Wrong typings to prevent Components.js typing issues + public constructor(storage: AccountLoginStorage>, manager: PodManager, visible = false) { super(); - this.storage = storage as typeof this.storage; + this.storage = storage as unknown as typeof this.storage; this.visible = visible; this.manager = manager; } diff --git a/src/identity/interaction/routing/InteractionRouteHandler.ts b/src/identity/interaction/routing/InteractionRouteHandler.ts index 45e204484..3482aa4c2 100644 --- a/src/identity/interaction/routing/InteractionRouteHandler.ts +++ b/src/identity/interaction/routing/InteractionRouteHandler.ts @@ -10,7 +10,7 @@ import type { InteractionRoute } from './InteractionRoute'; * Rejects operations that target a different route, * otherwise the input parameters are passed to the source handler. */ -export class InteractionRouteHandler> extends JsonInteractionHandler { +export class InteractionRouteHandler> extends JsonInteractionHandler { protected readonly route: T; protected readonly source: JsonInteractionHandler; diff --git a/src/identity/interaction/webid/util/BaseWebIdStore.ts b/src/identity/interaction/webid/util/BaseWebIdStore.ts index 8c1248c3a..2abd2d24f 100644 --- a/src/identity/interaction/webid/util/BaseWebIdStore.ts +++ b/src/identity/interaction/webid/util/BaseWebIdStore.ts @@ -23,9 +23,10 @@ export class BaseWebIdStore extends Initializer implements WebIdStore { private readonly storage: AccountLoginStorage<{ [WEBID_STORAGE_TYPE]: typeof WEBID_STORAGE_DESCRIPTION }>; private initialized = false; - public constructor(storage: AccountLoginStorage) { + // Wrong typings to prevent Components.js typing issues + public constructor(storage: AccountLoginStorage>) { super(); - this.storage = storage as typeof this.storage; + this.storage = storage as unknown as typeof this.storage; } // Initialize the type definitions diff --git a/src/index.ts b/src/index.ts index a57c18c4c..3e4c844d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -615,6 +615,7 @@ export * from './util/GenericEventEmitter'; export * from './util/GuardedStream'; export * from './util/HeaderUtil'; export * from './util/IterableUtil'; +export * from './util/Json'; export * from './util/PathUtil'; export * from './util/PromiseUtil'; export * from './util/QuadUtil'; diff --git a/src/init/AppRunner.ts b/src/init/AppRunner.ts index 0f2f701c1..0baca15c3 100644 --- a/src/init/AppRunner.ts +++ b/src/init/AppRunner.ts @@ -105,9 +105,9 @@ export class AppRunner { let configs = input.config ?? [ '@css:config/default.json' ]; configs = (Array.isArray(configs) ? configs : [ configs ]).map(resolveAssetPath); - let componentsManager: ComponentsManager; + let componentsManager: ComponentsManager; try { - componentsManager = await this.createComponentsManager(loaderProperties, configs); + componentsManager = await this.createComponentsManager(loaderProperties, configs); } catch (error: unknown) { this.resolveError(`Could not build the config files from ${configs.join(',')}`, error); } @@ -227,7 +227,7 @@ export class AppRunner { // Finally try and read from the config.community-solid-server // field in the root package.json - const pkg = await readJSON(packageJsonPath) as { config?: Record }; + const pkg = await readJSON(packageJsonPath) as { config?: Record }; if (typeof pkg.config?.['community-solid-server'] === 'object') { return pkg.config['community-solid-server'] as Record; } diff --git a/src/init/cli/YargsCliExtractor.ts b/src/init/cli/YargsCliExtractor.ts index 7b711f91b..5b8922701 100644 --- a/src/init/cli/YargsCliExtractor.ts +++ b/src/init/cli/YargsCliExtractor.ts @@ -19,7 +19,7 @@ export class YargsParameter { * @param name - Name of the parameter. Corresponds to the first parameter passed to the `yargs.options` function. * @param options - Options for a single parameter that should be parsed. @range {json} */ - public constructor(name: string, options: Record) { + public constructor(name: string, options: Record) { this.name = name; this.options = options; } diff --git a/src/init/migration/V6MigrationInitializer.ts b/src/init/migration/V6MigrationInitializer.ts index 2a9afe274..a6da3e52f 100644 --- a/src/init/migration/V6MigrationInitializer.ts +++ b/src/init/migration/V6MigrationInitializer.ts @@ -68,11 +68,12 @@ export interface V6MigrationInitializerArgs { /** * Storages for which all entries need to be removed. */ - cleanupStorages: KeyValueStorage[]; + cleanupStorages: KeyValueStorage[]; /** * The storage that will contain the account data in the new format. + * Wrong typings to prevent Components.js typing issues. */ - newAccountStorage: AccountLoginStorage; + newAccountStorage: AccountLoginStorage>; /** * The storage that will contain the setup entries in the new format. */ @@ -100,7 +101,7 @@ export class V6MigrationInitializer extends Initializer { private readonly accountStorage: KeyValueStorage; private readonly clientCredentialsStorage: KeyValueStorage; - private readonly cleanupStorages: KeyValueStorage[]; + private readonly cleanupStorages: KeyValueStorage[]; private readonly newAccountStorage: AccountLoginStorage; private readonly newSetupStorage: KeyValueStorage; @@ -113,7 +114,7 @@ export class V6MigrationInitializer extends Initializer { this.accountStorage = args.accountStorage; this.clientCredentialsStorage = args.clientCredentialsStorage; this.cleanupStorages = args.cleanupStorages; - this.newAccountStorage = args.newAccountStorage as AccountLoginStorage; + this.newAccountStorage = args.newAccountStorage as unknown as AccountLoginStorage; this.newSetupStorage = args.newSetupStorage; } diff --git a/src/init/variables/CombinedShorthandResolver.ts b/src/init/variables/CombinedShorthandResolver.ts index 199706cf2..afa204b28 100644 --- a/src/init/variables/CombinedShorthandResolver.ts +++ b/src/init/variables/CombinedShorthandResolver.ts @@ -14,7 +14,7 @@ export class CombinedShorthandResolver extends ShorthandResolver { } public async handle(input: Record): Promise> { - const vars: Record = {}; + const vars: Record = {}; for (const [ name, computer ] of Object.entries(this.resolvers)) { try { vars[name] = await computer.handleSafe(input); diff --git a/src/logging/WinstonLogger.ts b/src/logging/WinstonLogger.ts index b2f6e9542..86381e357 100644 --- a/src/logging/WinstonLogger.ts +++ b/src/logging/WinstonLogger.ts @@ -13,7 +13,7 @@ export class WinstonLogger extends BaseLogger { this.logger = logger; } - public log(level: LogLevel, message: string, meta?: any): this { + public log(level: LogLevel, message: string, meta?: unknown): this { this.logger.log(level, message, meta); return this; } diff --git a/src/logging/WinstonLoggerFactory.ts b/src/logging/WinstonLoggerFactory.ts index a34c79334..66e0c5873 100644 --- a/src/logging/WinstonLoggerFactory.ts +++ b/src/logging/WinstonLoggerFactory.ts @@ -1,3 +1,4 @@ +import type { TransformableInfo } from 'logform'; import { createLogger, format, transports } from 'winston'; import type * as Transport from 'winston-transport'; import type { Logger, LogMetadata } from './Logger'; @@ -33,7 +34,7 @@ export class WinstonLoggerFactory implements LoggerFactory { format.timestamp(), format.metadata({ fillExcept: [ 'level', 'timestamp', 'label', 'message' ]}), format.printf( - ({ level: levelInner, message, label: labelInner, timestamp, metadata: meta }: Record): string => + ({ level: levelInner, message, label: labelInner, timestamp, metadata: meta }: TransformableInfo): string => `${timestamp} [${labelInner}] {${this.clusterInfo(meta as LogMetadata)}} ${levelInner}: ${message}`, ), ), diff --git a/src/pods/generate/BaseComponentsJsFactory.ts b/src/pods/generate/BaseComponentsJsFactory.ts index e24dd3d6c..d49ac8e88 100644 --- a/src/pods/generate/BaseComponentsJsFactory.ts +++ b/src/pods/generate/BaseComponentsJsFactory.ts @@ -10,7 +10,7 @@ import type { ComponentsJsFactory } from './ComponentsJsFactory'; * but moduleState will be stored in between calls. */ export class BaseComponentsJsFactory implements ComponentsJsFactory { - private readonly options: IComponentsManagerBuilderOptions; + private readonly options: IComponentsManagerBuilderOptions; public constructor(relativeModulePath = '../../../', logLevel = 'error') { this.options = { @@ -21,7 +21,7 @@ export class BaseComponentsJsFactory implements ComponentsJsFactory { }; } - private async buildManager(): Promise> { + private async buildManager(): Promise> { const manager = await ComponentsManager.build(this.options); this.options.moduleState = manager.moduleState; return manager; @@ -35,7 +35,7 @@ export class BaseComponentsJsFactory implements ComponentsJsFactory { * * @returns The resulting object, corresponding to the given component IRI. */ - public async generate(configPath: string, componentIri: string, variables: Record): + public async generate(configPath: string, componentIri: string, variables: Record): Promise { const manager = await this.buildManager(); await manager.configRegistry.register(configPath); diff --git a/src/pods/generate/ComponentsJsFactory.ts b/src/pods/generate/ComponentsJsFactory.ts index 318d6a258..6ce82bcc4 100644 --- a/src/pods/generate/ComponentsJsFactory.ts +++ b/src/pods/generate/ComponentsJsFactory.ts @@ -10,5 +10,5 @@ export interface ComponentsJsFactory { * * @returns The resulting object, corresponding to the given component IRI. */ - generate: (configPath: string, componentIri: string, variables: Record) => Promise; + generate: (configPath: string, componentIri: string, variables: Record) => Promise; } diff --git a/src/server/middleware/CorsHandler.ts b/src/server/middleware/CorsHandler.ts index 4f7dc1890..fb603f835 100644 --- a/src/server/middleware/CorsHandler.ts +++ b/src/server/middleware/CorsHandler.ts @@ -35,10 +35,10 @@ export class CorsHandler extends HttpHandler { req: CorsRequest, res: { statusCode?: number; - setHeader: (key: string, value: string) => any; - end: () => any; + setHeader: (key: string, value: string) => unknown; + end: () => unknown; }, - next: (err?: any) => any, + next: (err?: unknown) => unknown, ) => void; public constructor(options: SimpleCorsOptions = {}) { diff --git a/src/server/util/BaseRouterHandler.ts b/src/server/util/BaseRouterHandler.ts index 7377707a2..8bcf9a927 100644 --- a/src/server/util/BaseRouterHandler.ts +++ b/src/server/util/BaseRouterHandler.ts @@ -5,7 +5,7 @@ import type { AsyncHandlerInput, AsyncHandlerOutput } from '../../util/handlers/ import { AsyncHandler } from '../../util/handlers/AsyncHandler'; import { trimTrailingSlashes } from '../../util/PathUtil'; -export interface BaseRouterHandlerArgs> { +export interface BaseRouterHandlerArgs> { /** * The base URL of the server. * Not required if no value is provided for `allowedPathNames`. @@ -36,7 +36,7 @@ export interface BaseRouterHandlerArgs> { * * `canHandleInput` expects a ResourceIdentifier to indicate it expects the target to have been validated already. */ -export abstract class BaseRouterHandler> +export abstract class BaseRouterHandler> extends AsyncHandler, AsyncHandlerOutput> { protected readonly baseUrlLength: number; protected readonly handler: T; diff --git a/src/storage/LockingResourceStore.ts b/src/storage/LockingResourceStore.ts index e7ceb8079..562c605c5 100644 --- a/src/storage/LockingResourceStore.ts +++ b/src/storage/LockingResourceStore.ts @@ -154,7 +154,7 @@ export class LockingResourceStore implements AtomicResourceStore { // Spy on the source to maintain the lock upon reading. const data = Object.create(source, { read: { - value(size: number): any { + value(size: number): unknown { maintainLock(); return source.read(size); }, diff --git a/src/storage/accessors/FileDataAccessor.ts b/src/storage/accessors/FileDataAccessor.ts index 8d20f70f2..4545689df 100644 --- a/src/storage/accessors/FileDataAccessor.ts +++ b/src/storage/accessors/FileDataAccessor.ts @@ -355,7 +355,7 @@ export class FileDataAccessor implements DataAccessor { * @param data - The data to be put in the file. */ protected async writeDataFile(path: string, data: Readable): Promise { - return new Promise((resolve, reject): any => { + return new Promise((resolve, reject): void => { const writeStream = createWriteStream(path); data.pipe(writeStream); data.on('error', (error): void => { diff --git a/src/storage/accessors/InMemoryDataAccessor.ts b/src/storage/accessors/InMemoryDataAccessor.ts index 6b0434203..38c47e79a 100644 --- a/src/storage/accessors/InMemoryDataAccessor.ts +++ b/src/storage/accessors/InMemoryDataAccessor.ts @@ -13,7 +13,7 @@ import { isInternalContentType } from '../conversion/ConversionUtil'; import type { DataAccessor } from './DataAccessor'; interface DataEntry { - data: any[]; + data: unknown[]; metadata: RepresentationMetadata; } interface ContainerEntry { diff --git a/src/storage/conversion/DynamicJsonToTemplateConverter.ts b/src/storage/conversion/DynamicJsonToTemplateConverter.ts index c715c8a2a..bef7224cb 100644 --- a/src/storage/conversion/DynamicJsonToTemplateConverter.ts +++ b/src/storage/conversion/DynamicJsonToTemplateConverter.ts @@ -58,7 +58,7 @@ export class DynamicJsonToTemplateConverter extends RepresentationConverter { return representation; } - const contents = JSON.parse(await readableToString(representation.data)) as NodeJS.Dict; + const contents = JSON.parse(await readableToString(representation.data)) as NodeJS.Dict; const rendered = await this.templateEngine.handleSafe({ contents, template: { templateFile: typeMap[type] }}); const metadata = new RepresentationMetadata(representation.metadata, { [CONTENT_TYPE]: type }); diff --git a/src/storage/quota/GlobalQuotaStrategy.ts b/src/storage/quota/GlobalQuotaStrategy.ts index 0800cbb3d..7227edfc2 100644 --- a/src/storage/quota/GlobalQuotaStrategy.ts +++ b/src/storage/quota/GlobalQuotaStrategy.ts @@ -8,7 +8,7 @@ import { QuotaStrategy } from './QuotaStrategy'; export class GlobalQuotaStrategy extends QuotaStrategy { private readonly base: string; - public constructor(limit: Size, reporter: SizeReporter, base: string) { + public constructor(limit: Size, reporter: SizeReporter, base: string) { super(reporter, limit); this.base = base; } diff --git a/src/storage/quota/PodQuotaStrategy.ts b/src/storage/quota/PodQuotaStrategy.ts index df765103d..2300a34d1 100644 --- a/src/storage/quota/PodQuotaStrategy.ts +++ b/src/storage/quota/PodQuotaStrategy.ts @@ -17,7 +17,7 @@ export class PodQuotaStrategy extends QuotaStrategy { public constructor( limit: Size, - reporter: SizeReporter, + reporter: SizeReporter, identifierStrategy: IdentifierStrategy, accessor: DataAccessor, ) { diff --git a/src/storage/quota/QuotaStrategy.ts b/src/storage/quota/QuotaStrategy.ts index 8c5d3568e..07efd6095 100644 --- a/src/storage/quota/QuotaStrategy.ts +++ b/src/storage/quota/QuotaStrategy.ts @@ -18,10 +18,10 @@ import type { SizeReporter } from '../size-reporter/SizeReporter'; * This can be bytes, quads, file count, ... */ export abstract class QuotaStrategy { - public readonly reporter: SizeReporter; + public readonly reporter: SizeReporter; public readonly limit: Size; - public constructor(reporter: SizeReporter, limit: Size) { + protected constructor(reporter: SizeReporter, limit: Size) { this.reporter = reporter; this.limit = limit; } @@ -87,7 +87,7 @@ export abstract class QuotaStrategy { const { reporter } = this; return guardStream(new PassThrough({ - async transform(this, chunk: any, enc: string, done: () => void): Promise { + async transform(this, chunk: unknown, enc: string, done: () => void): Promise { total += await reporter.calculateChunkSize(chunk); const availableSpace = await that.getAvailableSpace(identifier); if (availableSpace.amount < total) { diff --git a/src/util/GenericEventEmitter.ts b/src/util/GenericEventEmitter.ts index d10155f3e..b9a1ab823 100644 --- a/src/util/GenericEventEmitter.ts +++ b/src/util/GenericEventEmitter.ts @@ -9,6 +9,7 @@ import { EventEmitter } from 'node:events'; * Use the {@link createGenericEventEmitterClass} function to generate an event emitter class with the correct typings * in case {@link EventEmitter} needs to be extended. */ +// eslint-disable-next-line ts/no-explicit-any export interface GenericEventEmitter void> extends EventEmitter { addListener: (event: TEvent, listener: TFunc) => this; diff --git a/src/util/IterableUtil.ts b/src/util/IterableUtil.ts index dda2cf40f..79a57ebeb 100644 --- a/src/util/IterableUtil.ts +++ b/src/util/IterableUtil.ts @@ -12,7 +12,7 @@ export function* map( iterable: Iterable, callbackFn: (element: TIn, index: number) => TOut, - thisArg?: any, + thisArg?: unknown, ): Iterable { const boundMapFn = callbackFn.bind(thisArg); let count = 0; @@ -31,8 +31,11 @@ export function* map( * @param callbackFn - Function that is called to test every element. * @param thisArg - Value to use as `this` when executing `callbackFn`. */ -export function* filter(iterable: Iterable, callbackFn: (element: T, index: number) => boolean, thisArg?: any): -Iterable { +export function* filter( + iterable: Iterable, + callbackFn: (element: T, index: number) => boolean, + thisArg?: unknown, +): Iterable { const boundFilterFn = callbackFn.bind(thisArg); let count = 0; for (const value of iterable) { @@ -63,7 +66,7 @@ export function* concat(iterables: Iterable>): Iterable { * @param callbackFn - Function that is called to test every element. * @param thisArg - Value to use as `this` when executing `callbackFn`. */ -export function find(iterable: Iterable, callbackFn: (element: T, index: number) => boolean, thisArg?: any): +export function find(iterable: Iterable, callbackFn: (element: T, index: number) => boolean, thisArg?: unknown): T | undefined { const boundMapFn = callbackFn.bind(thisArg); const count = 0; diff --git a/src/util/Json.ts b/src/util/Json.ts new file mode 100644 index 000000000..fa00da4a4 --- /dev/null +++ b/src/util/Json.ts @@ -0,0 +1,4 @@ +/** + * A JSON object. + */ +export type Json = string | number | boolean | NodeJS.Dict | Json[]; diff --git a/src/util/LockUtils.ts b/src/util/LockUtils.ts index 970f265d9..5df47f554 100644 --- a/src/util/LockUtils.ts +++ b/src/util/LockUtils.ts @@ -12,7 +12,7 @@ const logger = getLoggerFor('LockUtil'); export async function setJitterTimeout(delay: number, jitter = 0): Promise { jitter = Math.max(0, Math.floor(Math.random() * jitter)); delay = Math.max(0, delay + jitter); - return new Promise((resolve): any => setTimeout(resolve, delay)); + return new Promise((resolve): unknown => setTimeout(resolve, delay)); } export interface AttemptSettings { diff --git a/src/util/PathUtil.ts b/src/util/PathUtil.ts index cfc2ee9d1..c9c9e6de1 100644 --- a/src/util/PathUtil.ts +++ b/src/util/PathUtil.ts @@ -6,6 +6,7 @@ import type { ResourceIdentifier } from '../http/representation/ResourceIdentifi import type { HttpRequest } from '../server/HttpRequest'; import { BadRequestHttpError } from './errors/BadRequestHttpError'; import { errorTermsToMetadata } from './errors/HttpErrorUtil'; +import type { Json } from './Json'; /** * Changes a potential Windows path into a POSIX path. @@ -305,8 +306,8 @@ export function resolveAssetPath(path = modulePathPlaceholder): string { /** * Reads the project package.json and returns it. */ -export async function readPackageJson(): Promise> { - return readJson(resolveModulePath('package.json')) as Promise>; +export async function readPackageJson(): Promise> { + return readJson(resolveModulePath('package.json')) as Promise>; } /** diff --git a/src/util/RecordObject.ts b/src/util/RecordObject.ts index 30994ab91..5528ade2e 100644 --- a/src/util/RecordObject.ts +++ b/src/util/RecordObject.ts @@ -2,10 +2,11 @@ * Helper class for instantiating multiple objects with Components.js. * See https://github.com/LinkedSoftwareDependencies/Components.js/issues/26 */ -// eslint-disable-next-line ts/no-extraneous-class -export class RecordObject implements Record { - public constructor(record: Record = {}) { +export class RecordObject implements Record { + public constructor(record: Record = {}) { // eslint-disable-next-line no-constructor-return return record; } + + [key: string]: unknown; } diff --git a/src/util/SliceStream.ts b/src/util/SliceStream.ts index f26b1477a..6f8d17d80 100644 --- a/src/util/SliceStream.ts +++ b/src/util/SliceStream.ts @@ -57,7 +57,7 @@ export class SliceStream extends Transform { } // eslint-disable-next-line ts/naming-convention - public _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void { + public _transform(chunk: unknown, encoding: BufferEncoding, callback: TransformCallback): void { this.source.pause(); if (this.writableObjectMode) { this.objectSlice(chunk); @@ -72,12 +72,12 @@ export class SliceStream extends Transform { protected binarySlice(chunk: Buffer): void { let length = chunk.length; if (this.remainingSkip > 0) { - chunk = chunk.slice(this.remainingSkip); + chunk = chunk.subarray(this.remainingSkip); this.remainingSkip -= length - chunk.length; length = chunk.length; } if (length > 0 && this.remainingSkip <= 0) { - chunk = chunk.slice(0, this.remainingRead); + chunk = chunk.subarray(0, this.remainingRead); this.push(chunk); this.remainingRead -= length; this.checkEnd(); diff --git a/src/util/StreamUtil.ts b/src/util/StreamUtil.ts index c6222f0c2..03524ff0c 100644 --- a/src/util/StreamUtil.ts +++ b/src/util/StreamUtil.ts @@ -10,6 +10,7 @@ import { isHttpRequest } from '../server/HttpRequest'; import { InternalServerError } from './errors/InternalServerError'; import type { Guarded } from './GuardedStream'; import { guardStream } from './GuardedStream'; +import type { Json } from './Json'; import type { PromiseOrValue } from './PromiseUtil'; export const endOfStream = promisify(eos); @@ -45,9 +46,9 @@ export async function readableToQuads(stream: Readable): Promise { * * @returns The parsed object. */ -export async function readJsonStream(stream: Readable): Promise> { +export async function readJsonStream(stream: Readable): Promise { const body = await readableToString(stream); - return JSON.parse(body) as NodeJS.Dict; + return JSON.parse(body) as Json; } /** @@ -119,16 +120,16 @@ export function pipeSafely( return guardStream(destination); } -export interface AsyncTransformOptions extends DuplexOptions { +export interface AsyncTransformOptions extends DuplexOptions { /** * Transforms data from the source by calling the `push` method */ - transform?: (this: Transform, data: T, encoding: string) => PromiseOrValue; + transform?: (this: Transform, data: T, encoding: string) => PromiseOrValue; /** * Performs any final actions after the source has ended */ - flush?: (this: Transform) => PromiseOrValue; + flush?: (this: Transform) => PromiseOrValue; } /** @@ -140,7 +141,7 @@ export interface AsyncTransformOptions extends DuplexOptions { * * @returns The transformed stream */ -export function transformSafely( +export function transformSafely( source: NodeJS.ReadableStream, { transform = function(data): void { @@ -179,6 +180,6 @@ export function transformSafely( * @param contents - Data to stream. * @param options - Options to pass to the Readable constructor. See {@link Readable.from}. */ -export function guardedStreamFrom(contents: string | Iterable, options?: ReadableOptions): Guarded { +export function guardedStreamFrom(contents: string | Iterable, options?: ReadableOptions): Guarded { return guardStream(Readable.from(typeof contents === 'string' ? [ contents ] : contents, options)); } diff --git a/src/util/Vocabularies.ts b/src/util/Vocabularies.ts index 681908a55..594f5b558 100644 --- a/src/util/Vocabularies.ts +++ b/src/util/Vocabularies.ts @@ -14,7 +14,7 @@ type ValueVocabulary = /** * A {@link ValueVocabulary} where the URI values are {@link NamedNode}s. */ -type TermVocabulary = T extends ValueVocabulary ? {[K in keyof T]: NamedNode } : never; +type TermVocabulary = T extends ValueVocabulary ? {[K in keyof T]: NamedNode } : never; /** * Contains a namespace and keys linking to the entries in this namespace. @@ -35,15 +35,15 @@ export type PartialVocabulary = /** * A local name of a {@link Vocabulary}. */ -export type VocabularyLocal = T extends Vocabulary ? TKey : never; +export type VocabularyLocal = T extends Vocabulary ? TKey : never; /** * A URI string entry of a {@link Vocabulary}. */ -export type VocabularyValue = T extends Vocabulary ? T[TKey] : never; +export type VocabularyValue = T extends Vocabulary ? T[TKey] : never; /** * A {@link NamedNode} entry of a {@link Vocabulary}. */ -export type VocabularyTerm = T extends Vocabulary ? T['terms'][TKey] : never; +export type VocabularyTerm = T extends Vocabulary ? T['terms'][TKey] : never; /** * Creates a {@link ValueVocabulary} with the given `baseUri` as namespace and all `localNames` as entries. diff --git a/src/util/errors/HttpError.ts b/src/util/errors/HttpError.ts index aeb9b440f..ed039c105 100644 --- a/src/util/errors/HttpError.ts +++ b/src/util/errors/HttpError.ts @@ -44,7 +44,7 @@ export class HttpError extends Error implements HttpE this.generateMetadata(); } - public static isInstance(error: any): error is HttpError { + public static isInstance(error: unknown): error is HttpError { return isError(error) && typeof (error as HttpError).statusCode === 'number' && Boolean((error as HttpError).metadata); @@ -77,7 +77,7 @@ export interface HttpErrorClass { /** * Checks if the given error is an instance of this class. */ - readonly isInstance: (error: any) => error is HttpError; + readonly isInstance: (error: unknown) => error is HttpError; } /** @@ -99,7 +99,7 @@ export function generateHttpErrorClass(statusCode: TCode, super(statusCode, name, message, options); } - public static isInstance(error: any): error is SpecificHttpError { + public static isInstance(error: unknown): error is SpecificHttpError { return HttpError.isInstance(error) && error.statusCode === statusCode; } }; diff --git a/src/util/errors/RedirectHttpError.ts b/src/util/errors/RedirectHttpError.ts index 622e12ca0..64847d400 100644 --- a/src/util/errors/RedirectHttpError.ts +++ b/src/util/errors/RedirectHttpError.ts @@ -16,7 +16,7 @@ export class RedirectHttpError extends HttpError< this.metadata.add(SOLID_HTTP.terms.location, DataFactory.namedNode(location)); } - public static isInstance(error: any): error is RedirectHttpError { + public static isInstance(error: unknown): error is RedirectHttpError { return HttpError.isInstance(error) && typeof (error as RedirectHttpError).location === 'string'; } } @@ -46,7 +46,7 @@ export function generateRedirectHttpErrorClass( super(code, name, location, message, options); } - public static isInstance(error: any): error is SpecificRedirectHttpError { + public static isInstance(error: unknown): error is SpecificRedirectHttpError { return RedirectHttpError.isInstance(error) && error.statusCode === code; } }; diff --git a/src/util/errors/SystemError.ts b/src/util/errors/SystemError.ts index 45604b201..44a9da1c2 100644 --- a/src/util/errors/SystemError.ts +++ b/src/util/errors/SystemError.ts @@ -26,7 +26,7 @@ export interface SystemError extends Error { /** * If present, extra details about the error condition. */ - info?: any; + info?: unknown; /** * If present, the file path when reporting a file system error. */ diff --git a/src/util/handlers/ArrayUnionHandler.ts b/src/util/handlers/ArrayUnionHandler.ts index 243b9b377..b3e4e1170 100644 --- a/src/util/handlers/ArrayUnionHandler.ts +++ b/src/util/handlers/ArrayUnionHandler.ts @@ -4,7 +4,7 @@ import { UnionHandler } from './UnionHandler'; /** * A utility handler that concatenates the results of all its handlers into a single result. */ -export class ArrayUnionHandler> extends UnionHandler { +export class ArrayUnionHandler> extends UnionHandler { public constructor(handlers: T[], requireAll?: boolean, ignoreErrors?: boolean) { super(handlers, requireAll, ignoreErrors); } diff --git a/src/util/handlers/AsyncHandler.ts b/src/util/handlers/AsyncHandler.ts index e0edf3a89..a454d2ab9 100644 --- a/src/util/handlers/AsyncHandler.ts +++ b/src/util/handlers/AsyncHandler.ts @@ -1,6 +1,6 @@ type Awaited = T extends PromiseLike ? U : T; -export type AsyncHandlerInput> = Parameters[0]; -export type AsyncHandlerOutput> = Awaited>; +export type AsyncHandlerInput> = Parameters[0]; +export type AsyncHandlerOutput> = Awaited>; /** * Simple interface for classes that can potentially handle a specific kind of data asynchronously. diff --git a/src/util/handlers/CachedHandler.ts b/src/util/handlers/CachedHandler.ts index 1b4a59b73..0f916a7be 100644 --- a/src/util/handlers/CachedHandler.ts +++ b/src/util/handlers/CachedHandler.ts @@ -12,7 +12,7 @@ type NestedMap = TOut | WeakMap>; * This also means that the cache key needs to be an object. * Errors will be thrown in case a primitive is used. */ -export class CachedHandler, TOut = void> extends AsyncHandler { +export class CachedHandler, TOut = void> extends AsyncHandler { private readonly source: AsyncHandler; private readonly fields?: [keyof TIn, ...(keyof TIn)[]]; diff --git a/src/util/handlers/StaticHandler.ts b/src/util/handlers/StaticHandler.ts index 6c2cd98ab..5c49ca1aa 100644 --- a/src/util/handlers/StaticHandler.ts +++ b/src/util/handlers/StaticHandler.ts @@ -7,7 +7,7 @@ import { AsyncHandler } from './AsyncHandler'; * The generic type extends `any` due to Components.js requirements. */ // eslint-disable-next-line ts/no-unnecessary-type-constraint -export class StaticHandler extends AsyncHandler { +export class StaticHandler extends AsyncHandler { private readonly value?: T; public constructor(value?: T) { diff --git a/src/util/handlers/StaticThrowHandler.ts b/src/util/handlers/StaticThrowHandler.ts index 4df8a3f1d..1928f61d8 100644 --- a/src/util/handlers/StaticThrowHandler.ts +++ b/src/util/handlers/StaticThrowHandler.ts @@ -4,7 +4,7 @@ import { AsyncHandler } from './AsyncHandler'; /** * Utility handler that can handle all input and always throws the given error. */ -export class StaticThrowHandler extends AsyncHandler { +export class StaticThrowHandler extends AsyncHandler { private readonly error: HttpError; public constructor(error: HttpError) { diff --git a/src/util/handlers/UnionHandler.ts b/src/util/handlers/UnionHandler.ts index 239ddd839..c508a393f 100644 --- a/src/util/handlers/UnionHandler.ts +++ b/src/util/handlers/UnionHandler.ts @@ -8,7 +8,7 @@ import { filterHandlers, findHandler } from './HandlerUtil'; * Will run the handlers and then call the abstract `combine` function with the results, * which then generates the handler's output. */ -export abstract class UnionHandler> extends +export abstract class UnionHandler> extends AsyncHandler, AsyncHandlerOutput> { protected readonly handlers: T[]; private readonly requireAll: boolean; diff --git a/src/util/handlers/UnsupportedAsyncHandler.ts b/src/util/handlers/UnsupportedAsyncHandler.ts index 7099ea5d8..230f898eb 100644 --- a/src/util/handlers/UnsupportedAsyncHandler.ts +++ b/src/util/handlers/UnsupportedAsyncHandler.ts @@ -4,7 +4,7 @@ import { AsyncHandler } from './AsyncHandler'; /** * Handler that does not support any input and will always throw an error. */ -export class UnsupportedAsyncHandler extends AsyncHandler { +export class UnsupportedAsyncHandler extends AsyncHandler { private readonly errorMessage?: string; public constructor(errorMessage?: string) { diff --git a/src/util/map/HashMap.ts b/src/util/map/HashMap.ts index 3bddcd44c..1d4194eec 100644 --- a/src/util/map/HashMap.ts +++ b/src/util/map/HashMap.ts @@ -6,7 +6,7 @@ type Entry = { key: TKey; value: TVal }; * A {@link Map} implementation that maps the Key object to a string using the provided hash function. * This ensures that equal objects that are not the same instance are mapped to the same value. */ -export class HashMap implements Map { +export class HashMap implements Map { private readonly hashMap: Map>; private readonly hashFn: (key: TKey) => string; @@ -64,7 +64,7 @@ export class HashMap implements Map { } } - public forEach(callbackfn: (value: TVal, key: TKey, map: Map) => void, thisArg?: any): void { + public forEach(callbackfn: (value: TVal, key: TKey, map: Map) => void, thisArg?: unknown): void { for (const [ key, value ] of this) { callbackfn.bind(thisArg)(value, key, this); } diff --git a/src/util/map/MapUtil.ts b/src/util/map/MapUtil.ts index c24726ee0..c18400c37 100644 --- a/src/util/map/MapUtil.ts +++ b/src/util/map/MapUtil.ts @@ -2,22 +2,22 @@ import { resolvePromiseOrValue } from '../PromiseUtil'; import type { PromiseOrValue } from '../PromiseUtil'; import type { SetMultiMap } from './SetMultiMap'; -export type ArrayElement = TArray[number]; +export type ArrayElement = TArray[number]; export type EmptyObject = Record; -export type MapKey = T extends Map ? TKey : never; -export type MapValue = T extends Map ? TValue : never; -export type MapEntry = T extends Map ? [MapKey, MapValue] : never; +export type MapKey = T extends Map ? TKey : never; +export type MapValue = T extends Map ? TValue : never; +export type MapEntry = T extends Map ? [MapKey, MapValue] : never; /** * A simplified version of {@link MapConstructor} that only allows creating an empty {@link Map}. */ -export type EmptyMapConstructor = new() => Map; +export type EmptyMapConstructor = new() => Map; /** * Options describing the necessary changes when calling {@link modify}. */ -export type ModifyOptions> = { +export type ModifyOptions> = { /** * Entries that need to be added to the Map. */ @@ -35,6 +35,7 @@ export type ModifyOptions> = { * @param map - Map to start from. * @param options - {@link ModifyOptions} describing the necessary changes. */ +// eslint-disable-next-line ts/no-explicit-any export function modify>(map: T, options: ModifyOptions): T { for (const key of options.remove ?? []) { map.delete(key); diff --git a/src/util/map/SetMultiMap.ts b/src/util/map/SetMultiMap.ts index a0a15f30e..8b9a2b668 100644 --- a/src/util/map/SetMultiMap.ts +++ b/src/util/map/SetMultiMap.ts @@ -55,5 +55,5 @@ export interface SetMultiMap extends Map) => void, thisArg?: any) => void; + forEach: (callbackfn: (value: TVal, key: TKey, map: SetMultiMap) => void, thisArg?: unknown) => void; } diff --git a/src/util/map/WrappedSetMultiMap.ts b/src/util/map/WrappedSetMultiMap.ts index 55d6d6ace..8636b8478 100644 --- a/src/util/map/WrappedSetMultiMap.ts +++ b/src/util/map/WrappedSetMultiMap.ts @@ -138,7 +138,7 @@ export class WrappedSetMultiMap implements SetMultiMap { return this.map.values(); } - public forEach(callbackfn: (value: TVal, key: TKey, map: SetMultiMap) => void, thisArg?: any): void { + public forEach(callbackfn: (value: TVal, key: TKey, map: SetMultiMap) => void, thisArg?: unknown): void { for (const [ key, value ] of this) { callbackfn.bind(thisArg)(value, key, this); } diff --git a/src/util/templates/ChainedTemplateEngine.ts b/src/util/templates/ChainedTemplateEngine.ts index 3e20faec1..71dc43c57 100644 --- a/src/util/templates/ChainedTemplateEngine.ts +++ b/src/util/templates/ChainedTemplateEngine.ts @@ -10,7 +10,7 @@ import Dict = NodeJS.Dict; * All subsequent engines will be called with no template parameter. * Contents will still be passed along and another entry will be added for the body of the previous output. */ -export class ChainedTemplateEngine = Dict> extends TemplateEngine { +export class ChainedTemplateEngine = Dict> extends TemplateEngine { private readonly firstEngine: TemplateEngine; private readonly chainedEngines: TemplateEngine[]; private readonly renderedName: string; diff --git a/src/util/templates/EjsTemplateEngine.ts b/src/util/templates/EjsTemplateEngine.ts index 3c86e8566..73866cc6f 100644 --- a/src/util/templates/EjsTemplateEngine.ts +++ b/src/util/templates/EjsTemplateEngine.ts @@ -7,7 +7,7 @@ import Dict = NodeJS.Dict; /** * Fills in EJS templates. */ -export class EjsTemplateEngine = Dict> extends ExtensionBasedTemplateEngine { +export class EjsTemplateEngine = Dict> extends ExtensionBasedTemplateEngine { private readonly baseUrl: string; /** diff --git a/src/util/templates/ExtensionBasedTemplateEngine.ts b/src/util/templates/ExtensionBasedTemplateEngine.ts index 94ed5d1fb..8aab8e121 100644 --- a/src/util/templates/ExtensionBasedTemplateEngine.ts +++ b/src/util/templates/ExtensionBasedTemplateEngine.ts @@ -8,7 +8,7 @@ import Dict = NodeJS.Dict; /** * Parent class for template engines that accept handling based on whether the template extension is supported. */ -export abstract class ExtensionBasedTemplateEngine = Dict> extends TemplateEngine { +export abstract class ExtensionBasedTemplateEngine = Dict> extends TemplateEngine { protected readonly supportedExtensions: string[]; /** diff --git a/src/util/templates/HandlebarsTemplateEngine.ts b/src/util/templates/HandlebarsTemplateEngine.ts index c4f4992ab..f62e0dd79 100644 --- a/src/util/templates/HandlebarsTemplateEngine.ts +++ b/src/util/templates/HandlebarsTemplateEngine.ts @@ -7,7 +7,7 @@ import Dict = NodeJS.Dict; /** * Fills in Handlebars templates. */ -export class HandlebarsTemplateEngine = Dict> extends ExtensionBasedTemplateEngine { +export class HandlebarsTemplateEngine = Dict> extends ExtensionBasedTemplateEngine { private readonly baseUrl: string; /** diff --git a/src/util/templates/StaticTemplateEngine.ts b/src/util/templates/StaticTemplateEngine.ts index b1191c620..3a3bc4913 100644 --- a/src/util/templates/StaticTemplateEngine.ts +++ b/src/util/templates/StaticTemplateEngine.ts @@ -6,7 +6,7 @@ import Dict = NodeJS.Dict; /** * Template engine that renders output based on a static template file. */ -export class StaticTemplateEngine = Dict> extends TemplateEngine { +export class StaticTemplateEngine = Dict> extends TemplateEngine { private readonly template: Template; private readonly templateEngine: AsyncHandler, string>; diff --git a/src/util/templates/TemplateEngine.ts b/src/util/templates/TemplateEngine.ts index 3b51af096..4e5100912 100644 --- a/src/util/templates/TemplateEngine.ts +++ b/src/util/templates/TemplateEngine.ts @@ -31,5 +31,5 @@ export interface TemplateEngineInput { * Generic interface for classes that implement a template engine. * A template engine renders content into a template. */ -export abstract class TemplateEngine = Dict> +export abstract class TemplateEngine = Dict> extends AsyncHandler, string> {}