diff --git a/packages/eslint-config-link/profile/common.js b/packages/eslint-config-link/profile/common.js index b0f1122..eed868e 100644 --- a/packages/eslint-config-link/profile/common.js +++ b/packages/eslint-config-link/profile/common.js @@ -40,6 +40,7 @@ module.exports = { "unicorn/no-useless-undefined": "off", "unicorn/no-array-reduce": "off", "unicorn/no-array-for-each": "off", + "unicorn/prefer-ternary": "off", "function-call-argument-newline": "off", "promise/param-names": "error", "promise/no-return-wrap": [ diff --git a/packages/metamigo-common/.eslintrc.js b/packages/metamigo-common/.eslintrc.js index 2a01087..70c6cdf 100644 --- a/packages/metamigo-common/.eslintrc.js +++ b/packages/metamigo-common/.eslintrc.js @@ -1,13 +1,7 @@ -require('@digiresilience/eslint-config-metamigo/patch/modern-module-resolution'); +require('eslint-config-link/patch/modern-module-resolution'); module.exports = { extends: [ - "@digiresilience/eslint-config-metamigo/profile/node", - "@digiresilience/eslint-config-metamigo/profile/typescript" - ], - rules: { - // TODO: enable this after jest fixes this issue https://github.com/nodejs/node/issues/38343 - "unicorn/prefer-node-protocol": "off" - }, - parserOptions: { tsconfigRootDir: __dirname } -}; - + "eslint-config-link/profile/node", + "eslint-config-link/profile/typescript" + ] +}; \ No newline at end of file diff --git a/packages/metamigo-common/package.json b/packages/metamigo-common/package.json index ec7621c..a038b55 100644 --- a/packages/metamigo-common/package.json +++ b/packages/metamigo-common/package.json @@ -10,13 +10,9 @@ "scripts": { "build": "tsc -p tsconfig.json", "fix:lint": "eslint src --ext .ts --fix", - "fix:prettier": "prettier \"src/**/*.ts\" --write", - "test": "yarn test:jest && yarn test:lint && yarn test:prettier", - "test:lint": "eslint src --ext .ts", - "test:prettier": "prettier \"src/**/*.ts\" --list-different", - "test:jest": "jest --coverage --forceExit --detectOpenHandles --reporters=default --reporters=jest-junit", - "doc": "yarn run doc:html", - "doc:html": "typedoc src/ --exclude '**/*.test.ts' --exclude '**/*.spec.ts' --name $npm_package_name --readme README.md --target es2019 --mode file --out build/docs", + "fmt": "prettier \"src/**/*.ts\" --write", + "lint": "eslint src --ext .ts && prettier \"src/**/*.ts\" --list-different", + "doc": "typedoc src/ --exclude '**/*.test.ts' --exclude '**/*.spec.ts' --name $npm_package_name --readme README.md --target es2019 --mode file --out build/docs", "watch:build": "tsc -p tsconfig.json -w" }, "devDependencies": { diff --git a/packages/metamigo-common/src/config/app-meta.ts b/packages/metamigo-common/src/config/app-meta.ts index ea360b3..4e71d39 100644 --- a/packages/metamigo-common/src/config/app-meta.ts +++ b/packages/metamigo-common/src/config/app-meta.ts @@ -11,14 +11,14 @@ export const AppMetaConfig: ConvictSchema = { doc: "The current application version", format: String, env: "npm_package_version", - default: null, + default: undefined, skipGenerate: true, }, name: { doc: "Application name", format: String, env: "npm_package_name", - default: null, + default: undefined, skipGenerate: true, }, figletFont: { diff --git a/packages/metamigo-common/src/config/formats.ts b/packages/metamigo-common/src/config/formats.ts index d1af899..31c0b87 100644 --- a/packages/metamigo-common/src/config/formats.ts +++ b/packages/metamigo-common/src/config/formats.ts @@ -1,7 +1,9 @@ import * as Joi from "joi"; import type { Format } from "convict"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const coerceString = (v: any): string => v.toString(); +// eslint-disable-next-line @typescript-eslint/no-explicit-any const validator = (s: any) => (v: any) => Joi.assert(v, s); const url = Joi.string().uri({ diff --git a/packages/metamigo-common/src/config/generate.ts b/packages/metamigo-common/src/config/generate.ts index bfaadb9..fbaf46a 100644 --- a/packages/metamigo-common/src/config/generate.ts +++ b/packages/metamigo-common/src/config/generate.ts @@ -1,5 +1,6 @@ import convict from "convict"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const visitLeaf = (acc: any, key: any, leaf: any) => { if (leaf.skipGenerate) { return; @@ -12,9 +13,11 @@ const visitLeaf = (acc: any, key: any, leaf: any) => { } }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const visitNode = (acc: any, node: any, key = "") => { if (node._cvtProperties) { const keys = Object.keys(node._cvtProperties); + // eslint-disable-next-line @typescript-eslint/no-explicit-any let subacc: any; if (key === "") { subacc = acc; diff --git a/packages/metamigo-common/src/config/index.ts b/packages/metamigo-common/src/config/index.ts index 9af67a0..71fca64 100644 --- a/packages/metamigo-common/src/config/index.ts +++ b/packages/metamigo-common/src/config/index.ts @@ -1,4 +1,4 @@ -import process from "process"; +import process from "node:process"; import convict, { SchemaObj } from "convict"; import { IServerConfig, ServerConfig } from "./server"; import { IMetricsConfig, MetricsConfig } from "./metrics-server"; @@ -42,19 +42,14 @@ interface IMetamigoConfig { isProd?: boolean; isTest?: boolean; isDev?: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any frontend: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any nextAuth: any; } export type IMetamigoConvict = ExtendedConvict; -export type { - IServerConfig, - IMetricsConfig, - IAppMetaConfig, - ICorsConfig, - ILoggingConfig, - IMetamigoConfig, -}; +export type { IMetamigoConfig }; export * from "./formats"; export * from "./generate"; @@ -103,6 +98,7 @@ ${error} try { config.validate({ allowed: "strict" }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { const msg = ` @@ -140,3 +136,9 @@ export const loadConfiguration = async ( const c = await loadConfigurationRaw(schema, override); return c.getProperties(); }; + +export { type IServerConfig } from "./server"; +export { type IMetricsConfig } from "./metrics-server"; +export { type IAppMetaConfig } from "./app-meta"; +export { type ICorsConfig } from "./cors"; +export { type ILoggingConfig } from "./logging"; diff --git a/packages/metamigo-common/src/config/print.ts b/packages/metamigo-common/src/config/print.ts index 3cb3c97..70c78e8 100644 --- a/packages/metamigo-common/src/config/print.ts +++ b/packages/metamigo-common/src/config/print.ts @@ -1,6 +1,7 @@ import chalk from "chalk"; import convict from "convict"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const visitLeaf = (path: any, key: any, leaf: any) => { if (leaf.skipGenerate) { return; @@ -20,6 +21,7 @@ const visitLeaf = (path: any, key: any, leaf: any) => { console.log(`\tenv: ${leaf.env}`); }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const visitNode = (path: any, node: any, key = "") => { if (node._cvtProperties) { const keys = Object.keys(node._cvtProperties); diff --git a/packages/metamigo-common/src/controllers/crud-controller.ts b/packages/metamigo-common/src/controllers/crud-controller.ts index d8f2fb0..966e989 100644 --- a/packages/metamigo-common/src/controllers/crud-controller.ts +++ b/packages/metamigo-common/src/controllers/crud-controller.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/ban-types,@typescript-eslint/no-explicit-any,max-params */ +/* eslint-disable @typescript-eslint/no-explicit-any,max-params */ import * as Boom from "@hapi/boom"; import * as Hapi from "@hapi/hapi"; import { CrudRepository } from "../records/crud-repository"; @@ -33,12 +33,8 @@ export abstract class AbstractCrudController< */ abstract repoName: string; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - abstract paramsIdField = "id"; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - abstract dbDecoration = "db"; + abstract paramsIdField; + abstract dbDecoration; abstract recordType: PgRecordInfo; repo(request: Hapi.Request): CrudRepository { @@ -206,7 +202,6 @@ export abstract class AbstractCrudController< }; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function unboundCrudController( aRecordType: TRecordInfo ) { @@ -229,7 +224,6 @@ export function unboundCrudController( }; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function CrudControllerBase(recordType: Rec) { return unboundCrudController(recordType); } @@ -241,53 +235,53 @@ export const crudRoutesFor = ( idParam: string, validate: Record ): Hapi.ServerRoute[] => [ - { - method: "POST", - path: `${path}`, - options: { - handler: controller.create, - validate: validate.create, - description: `Method that creates a new ${name}.`, - tags: ["api", name], - }, + { + method: "POST", + path: `${path}`, + options: { + handler: controller.create, + validate: validate.create, + description: `Method that creates a new ${name}.`, + tags: ["api", name], }, - { - method: "PUT", - path: `${path}/{${idParam}}`, - options: { - handler: controller.updateById, - validate: validate.updateById, - description: `Method that updates a ${name} by its id.`, - tags: ["api", name], - }, + }, + { + method: "PUT", + path: `${path}/{${idParam}}`, + options: { + handler: controller.updateById, + validate: validate.updateById, + description: `Method that updates a ${name} by its id.`, + tags: ["api", name], }, - { - method: "GET", - path: `${path}/{${idParam}}`, - options: { - handler: controller.getById, - validate: validate.getById, - description: `Method that gets a ${name} by its id.`, - tags: ["api", name], - }, + }, + { + method: "GET", + path: `${path}/{${idParam}}`, + options: { + handler: controller.getById, + validate: validate.getById, + description: `Method that gets a ${name} by its id.`, + tags: ["api", name], }, - { - method: "GET", - path: `${path}`, - options: { - handler: controller.getAll, - description: `Method that gets all ${name}s.`, - tags: ["api", name], - }, + }, + { + method: "GET", + path: `${path}`, + options: { + handler: controller.getAll, + description: `Method that gets all ${name}s.`, + tags: ["api", name], }, - { - method: "DELETE", - path: `${path}/{${idParam}}`, - options: { - handler: controller.deleteById, - validate: validate.deleteById, - description: `Method that deletes a ${name} by its id.`, - tags: ["api", name], - }, + }, + { + method: "DELETE", + path: `${path}/{${idParam}}`, + options: { + handler: controller.deleteById, + validate: validate.deleteById, + description: `Method that deletes a ${name} by its id.`, + tags: ["api", name], }, - ]; + }, +]; diff --git a/packages/metamigo-common/src/controllers/nextauth-adapter.ts b/packages/metamigo-common/src/controllers/nextauth-adapter.ts index fe5cf8d..6880628 100644 --- a/packages/metamigo-common/src/controllers/nextauth-adapter.ts +++ b/packages/metamigo-common/src/controllers/nextauth-adapter.ts @@ -1,9 +1,9 @@ /* eslint-disable unicorn/no-null,max-params */ -import { createHash, randomBytes } from "crypto"; +import { createHash, randomBytes } from "node:crypto"; import type { AdapterInstance } from "next-auth/adapters"; import omit from "lodash/omit"; import type { IMetamigoRepositories } from "../records"; -import type { UnsavedAccount, SavedAccount } from "../records/account"; +import type { UnsavedAccount } from "../records/account"; import type { UserId, UnsavedUser, SavedUser } from "../records/user"; import type { UnsavedSession, SavedSession } from "../records/session"; @@ -12,6 +12,7 @@ export const defaultSessionMaxAge = 30 * 24 * 60 * 60 * 1000; // Sessions updated only if session is greater than this value (0 = always) export const defaulteSessionUpdateAge = 24 * 60 * 60 * 1000; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const getCompoundId = (providerId: any, providerAccountId: any) => createHash("sha256") .update(`${providerId}:${providerAccountId}`) @@ -26,10 +27,10 @@ export class NextAuthAdapter private repos: TRepositories, private readonly sessionMaxAge = defaultSessionMaxAge, private readonly sessionUpdateAge = defaulteSessionUpdateAge - ) { } + ) {} async createUser(profile: UnsavedUser): Promise { - // @ts-expect-error + // @ts-expect-error Typescript doesn't like lodash's omit() return this.repos.users.upsert(omit(profile, ["isActive", "id"])); } diff --git a/packages/metamigo-common/src/hapi.ts b/packages/metamigo-common/src/hapi.ts index 1beee15..bfb4e9e 100644 --- a/packages/metamigo-common/src/hapi.ts +++ b/packages/metamigo-common/src/hapi.ts @@ -1,5 +1,5 @@ import * as Hapi from "@hapi/hapi"; -import * as http from "http"; +import * as http from "node:http"; import type { HttpTerminator } from "http-terminator"; import * as Glue from "@hapi/glue"; import * as Promster from "@promster/hapi"; @@ -102,7 +102,6 @@ export const defaultPlugins = ( { plugin: StatusPlugin }, { plugin: Promster.createPlugin() }, ]; - // @ts-ignore return plugins; }; @@ -110,7 +109,7 @@ export const announce = async ( config: T ): Promise => new Promise((resolve, reject) => { - // @ts-expect-error + // @ts-expect-error figlet doesn't have types figlet.text( config.meta.name, { font: config.meta.figletFont }, diff --git a/packages/metamigo-common/src/helpers/validation-error.ts b/packages/metamigo-common/src/helpers/validation-error.ts index a9c161e..07abe69 100644 --- a/packages/metamigo-common/src/helpers/validation-error.ts +++ b/packages/metamigo-common/src/helpers/validation-error.ts @@ -1,4 +1,4 @@ -import process from "process"; +import process from "node:process"; import * as Hapi from "@hapi/hapi"; import * as Joi from "joi"; import Hoek from "@hapi/hoek"; diff --git a/packages/metamigo-common/src/index.ts b/packages/metamigo-common/src/index.ts index 54252cb..59a6e8f 100644 --- a/packages/metamigo-common/src/index.ts +++ b/packages/metamigo-common/src/index.ts @@ -12,12 +12,10 @@ import * as pino from "pino"; declare module "@hapi/hapi" { interface Server { - // @ts-ignore logger: pino.Logger; } interface Request { - // @ts-ignore logger: pino.Logger; } } diff --git a/packages/metamigo-common/src/logger.ts b/packages/metamigo-common/src/logger.ts index 58c9367..bf51686 100644 --- a/packages/metamigo-common/src/logger.ts +++ b/packages/metamigo-common/src/logger.ts @@ -1,7 +1,9 @@ import pino, { LoggerOptions } from "pino"; import { IMetamigoConfig } from "./config"; -export const getPrettyPrint = (config: T): boolean => { +export const getPrettyPrint = ( + config: T +): boolean => { const { prettyPrint } = config.logging; if (prettyPrint === "auto") return config?.isDev || false; return prettyPrint === true; diff --git a/packages/metamigo-common/src/plugins/request-id.ts b/packages/metamigo-common/src/plugins/request-id.ts index d008fae..fcbb610 100644 --- a/packages/metamigo-common/src/plugins/request-id.ts +++ b/packages/metamigo-common/src/plugins/request-id.ts @@ -20,7 +20,6 @@ const register = async ( request.response.output.headers[header] = id; } else { const id = request.headers[header] || uuid(); - // @ts-ignore request.response.header(header, id); } diff --git a/packages/metamigo-common/src/plugins/status.ts b/packages/metamigo-common/src/plugins/status.ts index 97bed0c..9a72781 100644 --- a/packages/metamigo-common/src/plugins/status.ts +++ b/packages/metamigo-common/src/plugins/status.ts @@ -1,12 +1,13 @@ import { Server, RouteOptionsAccess } from "@hapi/hapi"; import { Prometheus } from "@promster/hapi"; +import { Counter } from "prom-client"; interface StatusOptions { path?: string; auth?: RouteOptionsAccess; } -const count = (statusCounter: any) => async () => { +const count = (statusCounter: Counter) => async () => { statusCounter.inc(); return "Incremented metamigo_status_test counter"; }; diff --git a/packages/metamigo-common/src/records/base.ts b/packages/metamigo-common/src/records/base.ts index e4ed2a8..02999db 100644 --- a/packages/metamigo-common/src/records/base.ts +++ b/packages/metamigo-common/src/records/base.ts @@ -12,7 +12,7 @@ export type PgProtocol = IDatabase & T; * @param aRecordType the record type runtime definition */ // haven't figured out a good return type for this function -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + export function unboundRepositoryBase< TRecordInfo extends PgRecordInfo, TDatabaseExtension @@ -48,7 +48,6 @@ export function unboundRepositoryBase< }; } -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function RepositoryBase< Rec extends PgRecordInfo, TDatabaseExtension = unknown diff --git a/packages/metamigo-common/src/records/crud-repository.ts b/packages/metamigo-common/src/records/crud-repository.ts index 97712c6..8007fa1 100644 --- a/packages/metamigo-common/src/records/crud-repository.ts +++ b/packages/metamigo-common/src/records/crud-repository.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/ban-types,@typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { TableName } from "pg-promise"; import decamelcaseKeys from "decamelcase-keys"; import isObject from "lodash/isObject"; @@ -106,7 +106,7 @@ export abstract class CrudRepository< `idsObj(${this.schemaTable}): passed record has multiple primary keys. the ids must be passed as an object or array. ${idValues}` ); } - // @ts-ignore + ids[idKeys[0]] = idValues; } diff --git a/packages/metamigo-common/src/records/record-info.d.ts b/packages/metamigo-common/src/records/record-info.d.ts deleted file mode 100644 index f712d6f..0000000 --- a/packages/metamigo-common/src/records/record-info.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -export interface EntityType { - _saved: TSaved; - _unsaved: TUnsaved; - _idKeys: TIds; - idOf: (rec: TSaved) => TIds; -} -export declare type UnsavedR = T["_unsaved"]; -export declare type SavedR = T["_saved"]; -export declare type KeyType = R["_idKeys"]; -export interface PgRecordInfo extends EntityType { - tableName: string; - schemaName: string; - idKeys: (keyof Saved)[]; -} -/** - * Extract the runtime key name from a recordInfo - */ -export declare function idKeysOf(recordInfoWithIdKey: RI): string[]; -/** - * Turns a record type with possibly more fields than "id" into an array - */ -export declare function collectIdValues(idObj: KeyType, knexRecordType: RecordT): string[]; -/** - * - * Creates a record descriptor that captures the table name, primary key name, - * unsaved type, and saved type of a database record type. Assumes "id" as the - * primary key name - * - */ -export declare function recordInfo(schemaName: string, tableName: string): PgRecordInfo>; -export declare function recordInfo(schemaName: string, tableName: string): PgRecordInfo>; -/** - * - * Creates a record descriptor that captures the table name, primary key name, - * unsaved type, and saved type of a database record type. - * - */ -export declare function recordInfo(schemaName: string, tableName: string, idKey: Id[]): PgRecordInfo>; -/** - * - * Creates a record descriptor for records with composite primary keys - * - */ -export declare function compositeRecordType(schemaName: string, tableName: string): { - withCompositeKeys(keys: TKeys[]): PgRecordInfo>; -}; diff --git a/packages/metamigo-common/src/records/record-info.ts b/packages/metamigo-common/src/records/record-info.ts index 5eb6a4b..6edf880 100644 --- a/packages/metamigo-common/src/records/record-info.ts +++ b/packages/metamigo-common/src/records/record-info.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/ban-types,@typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import at from "lodash/at"; import pick from "lodash/pick"; diff --git a/packages/metamigo-db/src/records/settings.ts b/packages/metamigo-db/src/records/settings.ts index 3412b98..aac5450 100644 --- a/packages/metamigo-db/src/records/settings.ts +++ b/packages/metamigo-db/src/records/settings.ts @@ -81,7 +81,7 @@ export const SettingsService = ( return s.value; }, - async save(settingInfo: SettingInfo, value: T): Promise { + async save(settingInfo: SettingInfo, value: T): Promise { const s = await repo.upsert(settingInfo.name, value); return s.value; },