Enabled no-explicit-any for majority of packages

refs https://github.com/TryGhost/DevOps/issues/50

- we should default to keeping the rule on and so I've excluded lines
  that currently use `any` to avoid the need to go and fix them all up
This commit is contained in:
Daniel Lockyer 2023-07-27 16:36:01 +02:00 committed by Daniel Lockyer
parent fa40485fb1
commit 6dd18d81d4
24 changed files with 51 additions and 27 deletions

View File

@ -9,15 +9,17 @@ module.exports = {
'ghost', 'ghost',
'tailwindcss' 'tailwindcss'
], ],
settings: {
react: {
version: 'detect'
}
},
rules: { rules: {
// sort multiple import lines into alphabetical groups // sort multiple import lines into alphabetical groups
'ghost/sort-imports-es6-autofix/sort-imports-es6': ['error', { 'ghost/sort-imports-es6-autofix/sort-imports-es6': ['error', {
memberSyntaxSortOrder: ['none', 'all', 'single', 'multiple'] memberSyntaxSortOrder: ['none', 'all', 'single', 'multiple']
}], }],
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
// suppress errors for missing 'import React' in JSX files, as we don't need it // suppress errors for missing 'import React' in JSX files, as we don't need it
'react/react-in-jsx-scope': 'off', 'react/react-in-jsx-scope': 'off',
// ignore prop-types for now // ignore prop-types for now

View File

@ -41,6 +41,7 @@ const App: React.FC<AppProps> = ({scriptTag}) => {
}; };
const PageComponent = pages[page.name]; const PageComponent = pages[page.name];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data = page.data as any; // issue with TypeScript understanding the type here when passing it to the component const data = page.data as any; // issue with TypeScript understanding the type here when passing it to the component
return ( return (
<> <>

View File

@ -21,10 +21,12 @@ export type AppContextType = {
setPage: <T extends PageName>(name: T, data: ComponentProps<typeof pages[T]>) => void, setPage: <T extends PageName>(name: T, data: ComponentProps<typeof pages[T]>) => void,
options: SignupFormOptions, options: SignupFormOptions,
api: GhostApi, api: GhostApi,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
t: any, t: any,
scriptTag: HTMLElement scriptTag: HTMLElement
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const AppContext = React.createContext<AppContextType>({} as any); const AppContext = React.createContext<AppContextType>({} as any);
export const AppContextProvider = AppContext.Provider; export const AppContextProvider = AppContext.Provider;

View File

@ -16,6 +16,7 @@ const Preview: React.FC<SignupFormOptions & {
data: {} data: {}
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const _setPage = (name: PageName, data: any) => { const _setPage = (name: PageName, data: any) => {
setPage(() => ({ setPage(() => ({
name, name,
@ -24,6 +25,7 @@ const Preview: React.FC<SignupFormOptions & {
}; };
const PageComponent = pages[page.name]; const PageComponent = pages[page.name];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data = page.data as any; const data = page.data as any;
const i18n = i18nLib(options.locale || 'en', 'signup-form'); const i18n = i18nLib(options.locale || 'en', 'signup-form');

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {Component} from 'react'; import {Component} from 'react';
import {createPortal} from 'react-dom'; import {createPortal} from 'react-dom';

View File

@ -2,6 +2,7 @@ import {expect} from '@playwright/test';
import {initialize} from '../utils/e2e'; import {initialize} from '../utils/e2e';
import {test} from '@playwright/test'; import {test} from '@playwright/test';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function testHistory({page, embeddedOnUrl, path, urlHistory, localStorageHistory}: {page: any, embeddedOnUrl?: string, path: string, urlHistory: any[], localStorageHistory?: any[]}) { async function testHistory({page, embeddedOnUrl, path, urlHistory, localStorageHistory}: {page: any, embeddedOnUrl?: string, path: string, urlHistory: any[], localStorageHistory?: any[]}) {
const {frame, lastApiRequest} = await initialize({page, title: 'Sign up', embeddedOnUrl, path}); const {frame, lastApiRequest} = await initialize({page, title: 'Sign up', embeddedOnUrl, path});

View File

@ -4,6 +4,7 @@ import {Page} from '@playwright/test';
const MOCKED_SITE_URL = 'https://localhost:1234'; const MOCKED_SITE_URL = 'https://localhost:1234';
type LastApiRequest = { type LastApiRequest = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
body: null | any body: null | any
}; };
@ -44,6 +45,7 @@ export async function initialize({page, path, apiStatus, embeddedOnUrl, ...optio
}; };
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function mockApi({page, status = 200}: {page: any, status?: number}) { export async function mockApi({page, status = 200}: {page: any, status?: number}) {
const lastApiRequest: LastApiRequest = { const lastApiRequest: LastApiRequest = {
body: null body: null

View File

@ -2,9 +2,5 @@ module.exports = {
plugins: ['ghost'], plugins: ['ghost'],
extends: [ extends: [
'plugin:ghost/ts' 'plugin:ghost/ts'
], ]
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
}; };

View File

@ -141,6 +141,7 @@ export class Collection {
this._posts = []; this._posts = [];
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private constructor(data: any) { private constructor(data: any) {
this.id = data.id; this.id = data.id;
this.title = data.title; this.title = data.title;
@ -170,6 +171,7 @@ export class Collection {
}; };
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static validateDateField(date: any, fieldName: string): Date { static validateDateField(date: any, fieldName: string): Date {
if (!date) { if (!date) {
return new Date(); return new Date();
@ -184,6 +186,7 @@ export class Collection {
}); });
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static async create(data: any): Promise<Collection> { static async create(data: any): Promise<Collection> {
let id; let id;

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {Collection} from './Collection'; import {Collection} from './Collection';
export interface CollectionRepository { export interface CollectionRepository {

View File

@ -6,6 +6,7 @@ export class CollectionsRepositoryInMemory extends InMemoryRepository<string, Co
return entity.toJSON(); return entity.toJSON();
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createTransaction(cb: (transaction: any) => Promise<any>): Promise<any> { createTransaction(cb: (transaction: any) => Promise<any>): Promise<any> {
return cb(null); return cb(null);
} }

View File

@ -22,6 +22,7 @@ const messages = {
}; };
interface SlugService { interface SlugService {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
generate(desired: string, options: {transaction: any}): Promise<string>; generate(desired: string, options: {transaction: any}): Promise<string>;
} }
@ -30,6 +31,7 @@ type CollectionsServiceDeps = {
postsRepository: PostsRepository; postsRepository: PostsRepository;
slugService: SlugService; slugService: SlugService;
DomainEvents: { DomainEvents: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
subscribe: (event: any, handler: (e: any) => void) => void; subscribe: (event: any, handler: (e: any) => void) => void;
}; };
}; };
@ -92,6 +94,7 @@ type QueryOptions = {
include?: string; include?: string;
page?: number; page?: number;
limit?: number; limit?: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
transaction?: any; transaction?: any;
} }
@ -103,6 +106,7 @@ export class CollectionsService {
private collectionsRepository: CollectionRepository; private collectionsRepository: CollectionRepository;
private postsRepository: PostsRepository; private postsRepository: PostsRepository;
private DomainEvents: { private DomainEvents: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
subscribe: (event: any, handler: (e: any) => void) => void; subscribe: (event: any, handler: (e: any) => void) => void;
}; };
private uniqueChecker: RepositoryUniqueChecker; private uniqueChecker: RepositoryUniqueChecker;
@ -134,7 +138,9 @@ export class CollectionsService {
}; };
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private fromDTO(data: any): any { private fromDTO(data: any): any {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mappedDTO: {[index: string]:any} = { const mappedDTO: {[index: string]:any} = {
title: data.title, title: data.title,
slug: data.slug, slug: data.slug,
@ -308,6 +314,7 @@ export class CollectionsService {
}); });
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async edit(data: any): Promise<CollectionDTO | null> { async edit(data: any): Promise<CollectionDTO | null> {
return await this.collectionsRepository.createTransaction(async (transaction) => { return await this.collectionsRepository.createTransaction(async (transaction) => {
const collection = await this.collectionsRepository.getById(data.id, {transaction}); const collection = await this.collectionsRepository.getById(data.id, {transaction});
@ -352,6 +359,7 @@ export class CollectionsService {
return await this.collectionsRepository.getBySlug(slug); return await this.collectionsRepository.getBySlug(slug);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async getAll(options?: QueryOptions): Promise<{data: CollectionDTO[], meta: any}> { async getAll(options?: QueryOptions): Promise<{data: CollectionDTO[], meta: any}> {
const collections = await this.collectionsRepository.getAll(options); const collections = await this.collectionsRepository.getAll(options);

View File

@ -16,6 +16,7 @@ export class PostAddedEvent {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static create(data: any, timestamp = new Date()) { static create(data: any, timestamp = new Date()) {
return new PostAddedEvent(data, timestamp); return new PostAddedEvent(data, timestamp);
} }

View File

@ -1,5 +1,6 @@
export class PostDeletedEvent { export class PostDeletedEvent {
id: string; id: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any; data: any;
timestamp: Date; timestamp: Date;
@ -9,6 +10,7 @@ export class PostDeletedEvent {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static create(data: any, timestamp = new Date()) { static create(data: any, timestamp = new Date()) {
return new PostDeletedEvent(data, timestamp); return new PostDeletedEvent(data, timestamp);
} }

View File

@ -23,12 +23,14 @@ export class PostEditedEvent {
data: PostEditData; data: PostEditData;
timestamp: Date; timestamp: Date;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(data: any, timestamp: Date) { constructor(data: any, timestamp: Date) {
this.id = data.id; this.id = data.id;
this.data = data; this.data = data;
this.timestamp = timestamp; this.timestamp = timestamp;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static create(data: any, timestamp = new Date()) { static create(data: any, timestamp = new Date()) {
return new PostEditedEvent(data, timestamp); return new PostEditedEvent(data, timestamp);
} }

View File

@ -9,6 +9,7 @@ export class TagDeletedEvent {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static create(data: any, timestamp = new Date()) { static create(data: any, timestamp = new Date()) {
return new TagDeletedEvent(data, timestamp); return new TagDeletedEvent(data, timestamp);
} }

View File

@ -2,9 +2,5 @@ module.exports = {
plugins: ['ghost'], plugins: ['ghost'],
extends: [ extends: [
'plugin:ghost/ts' 'plugin:ghost/ts'
], ]
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
}; };

View File

@ -10,6 +10,7 @@ type Order<T> = {
direction: 'asc' | 'desc'; direction: 'asc' | 'desc';
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type OrderOption<T extends Entity<any>> = Order<T>[]; type OrderOption<T extends Entity<any>> = Order<T>[];
export abstract class InMemoryRepository<IDType, T extends Entity<IDType>> { export abstract class InMemoryRepository<IDType, T extends Entity<IDType>> {
@ -51,6 +52,7 @@ export abstract class InMemoryRepository<IDType, T extends Entity<IDType>> {
for (const order of options.order) { for (const order of options.order) {
results.sort((a, b) => { results.sort((a, b) => {
if (order.direction === 'asc') { if (order.direction === 'asc') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return a[order.field] as any > (b[order.field] as any) ? 1 : -1; return a[order.field] as any > (b[order.field] as any) ? 1 : -1;
} else { } else {
return a[order.field] < b[order.field] ? 1 : -1; return a[order.field] < b[order.field] ? 1 : -1;

View File

@ -2,9 +2,5 @@ module.exports = {
plugins: ['ghost'], plugins: ['ghost'],
extends: [ extends: [
'plugin:ghost/ts' 'plugin:ghost/ts'
], ]
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
}; };

View File

@ -39,6 +39,7 @@ interface Labs {
} }
interface Config { interface Config {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get(key: string): any; get(key: string): any;
} }

View File

@ -2,9 +2,5 @@ module.exports = {
plugins: ['ghost'], plugins: ['ghost'],
extends: [ extends: [
'plugin:ghost/ts' 'plugin:ghost/ts'
], ]
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
}; };

View File

@ -2,10 +2,13 @@ import { PostDeletedEvent, PostAddedEvent, PostEditedEvent, TagDeletedEvent } fr
type ModelToDomainEventInterceptorDeps = { type ModelToDomainEventInterceptorDeps = {
ModelEvents: { ModelEvents: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
hasRegisteredListener: (event: any, listenerName: string) => boolean; hasRegisteredListener: (event: any, listenerName: string) => boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
on: (eventName: string, callback: (data: any) => void) => void; on: (eventName: string, callback: (data: any) => void) => void;
}, },
DomainEvents: { DomainEvents: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
dispatch: (event: any) => void; dispatch: (event: any) => void;
} }
} }
@ -32,6 +35,7 @@ export class ModelToDomainEventInterceptor {
for (const modelEventName of ghostModelUpdateEvents) { for (const modelEventName of ghostModelUpdateEvents) {
if (!this.ModelEvents.hasRegisteredListener(modelEventName, 'collectionListener')) { if (!this.ModelEvents.hasRegisteredListener(modelEventName, 'collectionListener')) {
const dispatcher = this.domainEventDispatcher.bind(this); const dispatcher = this.domainEventDispatcher.bind(this);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const listener = function (data: any) { const listener = function (data: any) {
dispatcher(modelEventName, data); dispatcher(modelEventName, data);
}; };
@ -42,6 +46,7 @@ export class ModelToDomainEventInterceptor {
} }
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
domainEventDispatcher(modelEventName: string, data: any) { domainEventDispatcher(modelEventName: string, data: any) {
let event; let event;
@ -66,6 +71,7 @@ export class ModelToDomainEventInterceptor {
status: data.attributes.status, status: data.attributes.status,
featured: data.attributes.featured, featured: data.attributes.featured,
published_at: data.attributes.published_at, published_at: data.attributes.published_at,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tags: data.relations?.tags?.models.map((tag: any) => ({ tags: data.relations?.tags?.models.map((tag: any) => ({
slug: tag.get('slug') slug: tag.get('slug')
})) }))
@ -78,6 +84,7 @@ export class ModelToDomainEventInterceptor {
status: data._previousAttributes?.status, status: data._previousAttributes?.status,
featured: data._previousAttributes?.featured, featured: data._previousAttributes?.featured,
published_at: data._previousAttributes?.published_at, published_at: data._previousAttributes?.published_at,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tags: data._previousRelations?.tags?.models.map((tag: any) => ({ tags: data._previousRelations?.tags?.models.map((tag: any) => ({
slug: tag.get('slug') slug: tag.get('slug')
})) }))

View File

@ -2,8 +2,5 @@ module.exports = {
plugins: ['ghost'], plugins: ['ghost'],
extends: [ extends: [
'plugin:ghost/ts' 'plugin:ghost/ts'
], ]
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
}
}; };

View File

@ -29,6 +29,7 @@ type PostRevisionsDeps = {
max_revisions: number; max_revisions: number;
revision_interval_ms: number; revision_interval_ms: number;
}, },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
model: any model: any
} }
@ -41,6 +42,7 @@ type RevisionResult = {
export class PostRevisions { export class PostRevisions {
config: PostRevisionsDeps['config']; config: PostRevisionsDeps['config'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
model: any; model: any;
constructor(deps: PostRevisionsDeps) { constructor(deps: PostRevisionsDeps) {
@ -122,6 +124,7 @@ export class PostRevisions {
}; };
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async removeAuthorFromRevisions(authorId: string, options: any): Promise<void> { async removeAuthorFromRevisions(authorId: string, options: any): Promise<void> {
const revisions = await this.model.findAll({ const revisions = await this.model.findAll({
filter: `author_id:${authorId}`, filter: `author_id:${authorId}`,