From 1c6870139a76be5d1570248d4a054a9e63608bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20W=C3=BCrbach?= Date: Wed, 12 Jun 2024 10:11:28 +0200 Subject: [PATCH] chore: remove any usage --- eslint.config.mjs | 5 +- src/adapters/humctl/HumctlAdapter.ts | 18 ++-- .../ValidateScoreFileController.ts | 2 +- src/errors/IHumanitecExtensionError.ts | 2 +- src/errors/UnexpectedEmptyOutputError.ts | 2 +- src/repos/ApplicationRepository.ts | 11 ++- src/repos/EnvironmentRepository.ts | 11 ++- src/repos/OrganizationRepository.ts | 11 ++- src/repos/ResourceTypeRepository.ts | 89 ++++++++++++------- src/repos/SecretRepository.ts | 18 ++-- src/services/LoginService.ts | 14 ++- src/services/ScoreValidationService.ts | 8 +- 12 files changed, 137 insertions(+), 54 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 36e0570..3af0a9a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -11,10 +11,7 @@ export default tseslint.config( ecmaVersion: 2022, sourceType: 'module', }, - rules: { - // We should not use `any` in our codebase, but there are quite a few violations today. - '@typescript-eslint/no-explicit-any': 'warn', - }, + rules: {}, files: ['src/**/*.ts'], }, { diff --git a/src/adapters/humctl/HumctlAdapter.ts b/src/adapters/humctl/HumctlAdapter.ts index 40eac1f..c4f65d8 100644 --- a/src/adapters/humctl/HumctlAdapter.ts +++ b/src/adapters/humctl/HumctlAdapter.ts @@ -1,4 +1,4 @@ -import { execFile } from 'child_process'; +import { execFile, ExecFileException } from 'child_process'; import * as util from 'util'; import { HumctlResult } from './HumctlResult'; @@ -61,10 +61,18 @@ export class HumctlAdapter implements IHumctlAdapter { result = await exec(humctlFilePath, command, { env: await this.prepareEnvVars(), }); - } catch (error: any) { - statusCode = error.code; - result.stderr = error.stderr; - result.stdout = error.stdout; + } catch (error: unknown) { + const execErr = error as ExecFileException; + + if (execErr.code) { + if (typeof execErr.code === 'string') { + statusCode = parseInt(execErr.code, 10); + } else { + statusCode = execErr.code; + } + } + result.stderr = execErr.stderr || ''; + result.stdout = execErr.stdout || ''; } // Ensure stderr and stdout is not undefined before its processing diff --git a/src/controllers/ValidateScoreFileController.ts b/src/controllers/ValidateScoreFileController.ts index bb6a8fd..8ee2510 100644 --- a/src/controllers/ValidateScoreFileController.ts +++ b/src/controllers/ValidateScoreFileController.ts @@ -139,7 +139,7 @@ export class ValidateScoreFileController { private isScoreFile(textDocument: TextDocument): boolean { try { - const loadedYamlDocument: any = yaml.load(textDocument.getText()); + const loadedYamlDocument: unknown = yaml.load(textDocument.getText()); if (!(loadedYamlDocument instanceof Object)) { return false; } diff --git a/src/errors/IHumanitecExtensionError.ts b/src/errors/IHumanitecExtensionError.ts index 0b9208b..70120cf 100644 --- a/src/errors/IHumanitecExtensionError.ts +++ b/src/errors/IHumanitecExtensionError.ts @@ -4,7 +4,7 @@ export interface IHumanitecExtensionError { } export function isHumanitecExtensionError( - error: any + error: unknown ): error is IHumanitecExtensionError { const isObject = error !== null && typeof error === 'object'; if (isObject) { diff --git a/src/errors/UnexpectedEmptyOutputError.ts b/src/errors/UnexpectedEmptyOutputError.ts index d8dcebf..99b0f2a 100644 --- a/src/errors/UnexpectedEmptyOutputError.ts +++ b/src/errors/UnexpectedEmptyOutputError.ts @@ -4,7 +4,7 @@ export class UnexpectedEmptyOutputError implements IHumanitecExtensionError { constructor( private binaryPath: string, private command: string[], - private options: any + private options: unknown ) {} message(): string { diff --git a/src/repos/ApplicationRepository.ts b/src/repos/ApplicationRepository.ts index 0370d6c..417bf1b 100644 --- a/src/repos/ApplicationRepository.ts +++ b/src/repos/ApplicationRepository.ts @@ -5,6 +5,15 @@ export interface IApplicationRepository { getFrom(organizationId: string): Promise; } +interface RawApplication { + metadata: { + id: string; + }; + entity: { + name: string; + }; +} + export class ApplicationRepository implements IApplicationRepository { constructor(private humctl: IHumctlAdapter) {} @@ -18,7 +27,7 @@ export class ApplicationRepository implements IApplicationRepository { const applications: Application[] = []; const rawApplications = JSON.parse(result.stdout); - rawApplications.forEach((rawApplication: any) => { + rawApplications.forEach((rawApplication: RawApplication) => { const application = new Application( rawApplication['metadata']['id'], rawApplication['entity']['name'], diff --git a/src/repos/EnvironmentRepository.ts b/src/repos/EnvironmentRepository.ts index b6a1a58..eb74ec6 100644 --- a/src/repos/EnvironmentRepository.ts +++ b/src/repos/EnvironmentRepository.ts @@ -8,6 +8,15 @@ export interface IEnvironmentRepository { ): Promise; } +interface RawEnvironment { + metadata: { + id: string; + }; + entity: { + name: string; + }; +} + export class EnvironmentRepository implements IEnvironmentRepository { constructor(private humctl: IHumctlAdapter) {} @@ -26,7 +35,7 @@ export class EnvironmentRepository implements IEnvironmentRepository { const environments: Environment[] = []; const rawEnvironments = JSON.parse(result.stdout); - rawEnvironments.forEach((rawEnvironment: any) => { + rawEnvironments.forEach((rawEnvironment: RawEnvironment) => { const environment = new Environment( rawEnvironment['metadata']['id'], rawEnvironment['entity']['name'], diff --git a/src/repos/OrganizationRepository.ts b/src/repos/OrganizationRepository.ts index d551bd4..637ffe1 100644 --- a/src/repos/OrganizationRepository.ts +++ b/src/repos/OrganizationRepository.ts @@ -5,6 +5,15 @@ export interface IOrganizationRepository { getAll(): Promise; } +interface RawOrganization { + metadata: { + id: string; + }; + entity: { + name: string; + }; +} + export class OrganizationRepository implements IOrganizationRepository { constructor(private humctl: IHumctlAdapter) {} @@ -13,7 +22,7 @@ export class OrganizationRepository implements IOrganizationRepository { const organizations: Organization[] = []; const rawOrganizations = JSON.parse(result.stdout); - rawOrganizations.forEach((rawOrganization: any) => { + rawOrganizations.forEach((rawOrganization: RawOrganization) => { const organization = new Organization( rawOrganization['metadata']['id'], rawOrganization['entity']['name'] diff --git a/src/repos/ResourceTypeRepository.ts b/src/repos/ResourceTypeRepository.ts index e26a11a..9aec568 100644 --- a/src/repos/ResourceTypeRepository.ts +++ b/src/repos/ResourceTypeRepository.ts @@ -11,14 +11,31 @@ export interface IResourceTypeRepository { get(name: string): Promise; } +interface Properties { + properties: { + [key: string]: { + description: string; + title: string; + type: string; + }; + }; + required: string[]; +} + +interface Schema { + properties: { + values?: Properties; + secrets?: Properties; + }; +} + interface AvailableResourceTypeOutput { Name: string; Type: string; Category: string; - InputsSchema: any; - OutputsSchema: any; - // Casting JSON to Map doesn't work as expected, that's why it has to be any - Classes: any; + InputsSchema: Schema; + OutputsSchema: Schema; + Classes: { [key: string]: string }; } export class ResourceTypeRepository implements IResourceTypeRepository { @@ -51,8 +68,8 @@ export class ResourceTypeRepository implements IResourceTypeRepository { resourceType.Category, resourceType.Name, resourceType.Type, - this.resolveVariables(resourceType.InputsSchema), - this.resolveVariables(resourceType.OutputsSchema), + this.resolveSchema(resourceType.InputsSchema), + this.resolveSchema(resourceType.OutputsSchema), resourceTypeClasses ); } @@ -79,8 +96,8 @@ export class ResourceTypeRepository implements IResourceTypeRepository { availableResourceType.Category, availableResourceType.Name, availableResourceType.Type, - this.resolveVariables(availableResourceType.InputsSchema), - this.resolveVariables(availableResourceType.OutputsSchema), + this.resolveSchema(availableResourceType.InputsSchema), + this.resolveSchema(availableResourceType.OutputsSchema), resourceTypeClasses ); resourceTypes.push(resourceType); @@ -88,47 +105,57 @@ export class ResourceTypeRepository implements IResourceTypeRepository { return resourceTypes; } - private resolveVariables( - rawVariables: any + private resolveSchema( + rawSchema: Schema | null ): Map { const result = new Map(); - if (rawVariables === null) { + if (rawSchema === null) { return result; } - const properties = rawVariables['properties']; + const properties = rawSchema['properties']; if (properties === undefined) { return result; } - if ('values' in properties) { - const values = this.resolveVariables(properties['values']); + if (properties.values) { + const values = this.resolveProperties(properties['values']); values.forEach((value: ResourceTypeVariable, key: string) => { result.set(key, value); }); } - if ('secrets' in properties) { - const secrets = this.resolveVariables(properties['secrets']); + if (properties.secrets) { + const secrets = this.resolveProperties(properties['secrets']); secrets.forEach((value: ResourceTypeVariable, key: string) => { result.set(key, value); }); } - if (!('values' in properties || 'secrets' in properties)) { - let requiredProperties: string[] = rawVariables['required']; - if (requiredProperties === undefined) { - requiredProperties = []; - } + return result; + } - let property: keyof typeof properties; - for (property in properties) { - const variable = new ResourceTypeVariable( - properties[property]['description'], - properties[property]['title'], - properties[property]['type'], - requiredProperties.includes(property) - ); - result.set(property, variable); - } + private resolveProperties( + rawVariables: Properties + ): Map { + const result = new Map(); + const properties = rawVariables['properties']; + if (properties === undefined) { + return result; + } + + let requiredProperties: string[] = rawVariables['required']; + if (requiredProperties === undefined) { + requiredProperties = []; + } + + let property: keyof typeof properties; + for (property in properties) { + const variable = new ResourceTypeVariable( + properties[property]['description'], + properties[property]['title'], + properties[property]['type'], + requiredProperties.includes(property) + ); + result.set(property, variable); } return result; diff --git a/src/repos/SecretRepository.ts b/src/repos/SecretRepository.ts index 9da98f0..9e16355 100644 --- a/src/repos/SecretRepository.ts +++ b/src/repos/SecretRepository.ts @@ -22,9 +22,13 @@ export class SecretRepository implements ISecretRepository { let configFile: Buffer = Buffer.from([]); try { configFile = readFileSync(configPath); - } catch (error: any) { - if (error.code && error.code === 'ENOENT') { - console.log(error); + } catch (error: unknown) { + if ( + error instanceof Error && + 'code' in error && + error.code === 'ENOENT' + ) { + // Ignore } else { throw error; } @@ -51,8 +55,12 @@ export class SecretRepository implements ISecretRepository { value = ''; } return value; - } catch (error: any) { - if (error.code && error.code === 'ENOENT') { + } catch (error: unknown) { + if ( + error instanceof Error && + 'code' in error && + error.code === 'ENOENT' + ) { return ''; } else { throw error; diff --git a/src/services/LoginService.ts b/src/services/LoginService.ts index 70abab7..83127f2 100644 --- a/src/services/LoginService.ts +++ b/src/services/LoginService.ts @@ -8,6 +8,16 @@ export interface ILoginService { confirmDeviceAuthorization(info: DeviceAuthorizationInfo): Promise; } +interface DeviceResponse { + security_code: string; + verification_url: string; +} + +interface DevicePollResponse { + accepted: boolean; + access_token: string; +} + export class LoginService implements ILoginService { constructor() {} async initDeviceAuthorization(): Promise { @@ -22,7 +32,7 @@ export class LoginService implements ILoginService { if (response.status !== 200) { throw new AuthorizationError(await response.text()); } - const body: any = await response.json(); + const body = (await response.json()) as DeviceResponse; if (!body.security_code || !body.verification_url) { throw new AuthorizationError(await response.text()); } @@ -47,7 +57,7 @@ export class LoginService implements ILoginService { } ); if (response.status === 200) { - const body: any = await response.json(); + const body = (await response.json()) as DevicePollResponse; if (!body.accepted) { throw new AuthorizationError(await response.text()); } diff --git a/src/services/ScoreValidationService.ts b/src/services/ScoreValidationService.ts index e6439b4..31c26a4 100644 --- a/src/services/ScoreValidationService.ts +++ b/src/services/ScoreValidationService.ts @@ -16,6 +16,12 @@ export class ValidationError { } } +interface RawValidationError { + Level: string; + Location: string; + Message: string; +} + export class ScoreValidationService implements IScoreValidationService { constructor(private humctl: IHumctlAdapter) {} @@ -28,7 +34,7 @@ export class ScoreValidationService implements IScoreValidationService { return validationErrors; } const validationRawErrors = JSON.parse(result.stdout); - validationRawErrors.forEach((validationRawError: any) => { + validationRawErrors.forEach((validationRawError: RawValidationError) => { validationErrors.push( new ValidationError( validationRawError.Level,