diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a366fb9..40b8318 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,10 @@ jobs: - name: Install dependencies run: yarn --frozen-lockfile - - name: ESLint + - name: Typescript check + run: yarn tsc + + - name: Biome lint check run: yarn lint - name: Unit tests diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..6bf6de3 --- /dev/null +++ b/biome.json @@ -0,0 +1,48 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "files": { + "includes": [ + "src/**/*.ts" + ] + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 100, + "attributePosition": "auto" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "noForEach": "off", + "noUselessSwitchCase": "off" + }, + "a11y": { + "noSvgWithoutTitle": "off" + }, + "suspicious": { + "noArrayIndexKey": "warn", + "noDoubleEquals": "off" + }, + "style": { + "useImportType": "warn" + } + } + }, + "javascript": { + "formatter": { + "quoteProperties": "asNeeded", + "semicolons": "asNeeded", + "arrowParentheses": "always", + "bracketSpacing": true, + "bracketSameLine": false, + "quoteStyle": "single", + "attributePosition": "auto" + } + } +} diff --git a/package.json b/package.json index 273d613..97ef87c 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "start": "tsc --watch", "prepare": "tsc", "coverage": "jest --coverage", - "lint": "tsc && prettier --list-different --write src tests", + "tsc": "tsc --noEmit", + "lint": "biome lint --diagnostic-level=error src", "test": "jest" }, "repository": { @@ -39,26 +40,20 @@ }, "devDependencies": { "@arethetypeswrong/cli": "0.15.4", + "@biomejs/biome": "2.0.4", "@types/jest": "29.5.12", "@types/node": "20.12.5", "expect-type": "^0.19.0", "husky": "9.0.11", "jest": "29.7.0", - "prettier": "3.2.5", "ts-jest": "29.1.2", "typescript": "5.2.2" }, "author": "Aaron Franks", "license": "MIT", - "prettier": { - "printWidth": 100, - "semi": false, - "singleQuote": true, - "trailingComma": "all" - }, "husky": { "hooks": { - "pre-commit": "yarn lint", + "pre-commit": "yarn lint && yarn tsc", "pre-push": "yarn test" } } diff --git a/src/core.ts b/src/core.ts index 6bbefbc..214e28c 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,5 +1,5 @@ import { EnvError, EnvMissingError } from './errors' -import { CleanOptions, SpecsOutput, Spec, ValidatorSpec } from './types' +import type { CleanOptions, SpecsOutput, Spec, ValidatorSpec } from './types' import { defaultReporter } from './reporter' export const testOnlySymbol = Symbol('envalid - test only') @@ -56,7 +56,7 @@ export function getSanitizedEnv( specs: S, options: CleanOptions> = {}, ): SpecsOutput { - let cleanedEnv = {} as SpecsOutput + const cleanedEnv = {} as SpecsOutput const castedSpecs = specs as unknown as Record> const errors = {} as Record const varKeys = Object.keys(castedSpecs) as Array @@ -72,7 +72,7 @@ export function getSanitizedEnv( if (rawValue === undefined) { // Use devDefault values only if NODE_ENV was explicitly set, and isn't 'production' const usingDevDefault = - rawNodeEnv && rawNodeEnv !== 'production' && spec.hasOwnProperty('devDefault') + rawNodeEnv && rawNodeEnv !== 'production' && Object.hasOwn(spec, 'devDefault') if (usingDevDefault) { cleanedEnv[k] = spec.devDefault diff --git a/src/envalid.ts b/src/envalid.ts index c0c453c..2c97072 100644 --- a/src/envalid.ts +++ b/src/envalid.ts @@ -1,4 +1,4 @@ -import { CleanedEnv, CleanOptions } from './types' +import type { CleanedEnv, CleanOptions } from './types' import { getSanitizedEnv, testOnlySymbol } from './core' import { applyDefaultMiddleware } from './middleware' diff --git a/src/makers.ts b/src/makers.ts index 59ea76e..31e941c 100644 --- a/src/makers.ts +++ b/src/makers.ts @@ -1,4 +1,4 @@ -import { Spec, BaseValidator, StructuredValidator, ExactValidator } from './types' +import type { Spec, BaseValidator, StructuredValidator, ExactValidator } from './types' const internalMakeValidator = (parseFn: (input: string) => T) => { return (spec?: Spec) => ({ ...spec, _parse: parseFn }) diff --git a/src/middleware.ts b/src/middleware.ts index 2287e21..6570eea 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,4 +1,4 @@ -import { CleanedEnvAccessors, StrictProxyMiddlewareOptions } from './types' +import type { CleanedEnvAccessors, StrictProxyMiddlewareOptions } from './types' export const strictProxyMiddleware = ( envObj: T, @@ -43,7 +43,7 @@ export const strictProxyMiddleware = ( return target[name] } - const varExists = target.hasOwnProperty(name) + const varExists = Object.hasOwn(target, name) if (!varExists) { if (typeof rawEnv === 'object' && rawEnv?.hasOwnProperty?.(name)) { throw new ReferenceError( diff --git a/src/reporter.ts b/src/reporter.ts index 9e611b8..0b3b53e 100644 --- a/src/reporter.ts +++ b/src/reporter.ts @@ -1,6 +1,5 @@ -/* eslint-disable no-console */ import { EnvMissingError } from './errors' -import { ReporterOptions } from './types' +import type { ReporterOptions } from './types' type Errors = Partial> type Logger = (data: any, ...args: any[]) => void diff --git a/src/validators.ts b/src/validators.ts index 3272bce..10f0e95 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -5,7 +5,7 @@ import { makeExactValidator, makeStructuredValidator, makeValidator } from './ma const isFQDN = (input: string) => { if (!input.length) return false const parts = input.split('.') - for (let part, i = 0; i < parts.length; i++) { + for (let part: string, i = 0; i < parts.length; i++) { part = parts[i] if (!/^[a-z\u00a1-\uffff0-9-]+$/i.test(part)) return false if (/[\uff01-\uff5e]/.test(part)) return false // disallow full-width chars diff --git a/tests/basics.test.ts b/tests/basics.test.ts index a06c49b..a5f70d1 100644 --- a/tests/basics.test.ts +++ b/tests/basics.test.ts @@ -1,4 +1,4 @@ -import { cleanEnv, str, num, testOnly, ReporterOptions } from '../src' +import { cleanEnv, str, num, testOnly, type ReporterOptions } from '../src' import { assertPassthrough } from './utils' import { expectTypeOf } from 'expect-type' diff --git a/tests/middleware.test.ts b/tests/middleware.test.ts index 857428c..29768a7 100644 --- a/tests/middleware.test.ts +++ b/tests/middleware.test.ts @@ -106,8 +106,8 @@ describe('proxy middleware', () => { }, ) - expect(env.hasOwnProperty('FOO')).toEqual(true) - expect(env.hasOwnProperty('BAR')).toEqual(false) + expect(Object.hasOwn(env, 'FOO')).toEqual(true) + expect(Object.hasOwn(env, 'BAR')).toEqual(false) }) test('proxy does not error out on .length checks (#70)', () => { diff --git a/tests/types.test.ts b/tests/types.test.ts index abb7f40..5ddd036 100644 --- a/tests/types.test.ts +++ b/tests/types.test.ts @@ -3,10 +3,10 @@ import { str, bool, num, - RequiredValidatorSpec, - OptionalValidatorSpec, + type RequiredValidatorSpec, + type OptionalValidatorSpec, json, - CleanedEnvAccessors, + type CleanedEnvAccessors, } from '../src' import { expectTypeOf } from 'expect-type' import { makeStructuredValidator, makeValidator } from '../src/makers' diff --git a/tests/utils.ts b/tests/utils.ts index 5eba3ec..2309713 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,4 +1,4 @@ -import { cleanEnv, ValidatorSpec } from '../src' +import { cleanEnv, type ValidatorSpec } from '../src' // Ensure that a given environment spec passes through all values from the given // env object diff --git a/tsconfig.json b/tsconfig.json index e2e55a4..c81562e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,9 +12,13 @@ "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, - "lib": ["es2019"] + "lib": [ + "es2022" + ] }, - "include": ["src"], + "include": [ + "src" + ], "exclude": [ "node_modules", "**/node_modules/*" diff --git a/yarn.lock b/yarn.lock index be8b543..9f747c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -328,6 +328,60 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@biomejs/biome@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.0.4.tgz#2abd3815d42ca674857c6be6ab4b7dd7098c9518" + integrity sha512-DNA++xe+E7UugTvI/HhzSFl6OwrVgU8SIV0Mb2fPtWPk2/oTr4eOSA5xy1JECrvgJeYxurmUBOS49qxv/OUkrQ== + optionalDependencies: + "@biomejs/cli-darwin-arm64" "2.0.4" + "@biomejs/cli-darwin-x64" "2.0.4" + "@biomejs/cli-linux-arm64" "2.0.4" + "@biomejs/cli-linux-arm64-musl" "2.0.4" + "@biomejs/cli-linux-x64" "2.0.4" + "@biomejs/cli-linux-x64-musl" "2.0.4" + "@biomejs/cli-win32-arm64" "2.0.4" + "@biomejs/cli-win32-x64" "2.0.4" + +"@biomejs/cli-darwin-arm64@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.0.4.tgz#2def86a792b1c01490e864b52a03af47ea326502" + integrity sha512-r5McIUMMiedwJ2rltuXhj0+w0W7IJLpkOS+OGCVZQQOOcrGY9gUSUmOo7O6Z7P0vlv5YYZkPbi+qR9MDDWRBSw== + +"@biomejs/cli-darwin-x64@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.0.4.tgz#eece80ae03e9456c2053613c5965a4421903bcf4" + integrity sha512-aV5Zc/3E3aXFbrjK1IgCMEQc+6PCkBL+NS+vtjoNM2VPFeM5OL5Q82BI4YZyPnebj+k42BPIoYtz0jJ95PGRRg== + +"@biomejs/cli-linux-arm64-musl@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.4.tgz#92bdaada9ef465c9762c6ddd4a8edabb5a31b698" + integrity sha512-cNukq2PthoOa7quqaKoEFz4Zd1pDPJGfTR5jVyk9Z9iFHEm6TI7+7eeIs3aYcEuuJPNFR9xhJ4Uj3E2iUWkV3A== + +"@biomejs/cli-linux-arm64@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.0.4.tgz#2c3b018104164a4df883a48929033f34f51771eb" + integrity sha512-nlJhf7DyuajMj+S7Ygum59cbrHvI/nSRvedfJcEIx4X7SsiZjpRUiC5XtEn77kg7NIKq/KqG5roQIHkmjuFHCw== + +"@biomejs/cli-linux-x64-musl@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.4.tgz#6ce9e45ed186ee85ee3f9c9f6ddb7673a917f28f" + integrity sha512-oWQALSbp8xF0t/wiHU2zdkZOpIHyaI9QxQv0Ytty9GAKsCGP6pczp8qyKD/P49iGJdDozHp5KiuQPxs33APhyA== + +"@biomejs/cli-linux-x64@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.0.4.tgz#102ffb44892c31fef2eb4e4e273953d6eb22c05f" + integrity sha512-jlzrNZ+OzN9wvp2RL3cl5Y4NiV7xSU+QV5A8bWXke1on3jKy7QbXajybSjVQ6aFw1gdrqkO/W8xV5HODhIMT4g== + +"@biomejs/cli-win32-arm64@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.0.4.tgz#d0b109a2b449c774f4236c0d25a3065e390e1d75" + integrity sha512-/PbNhMJo9ONja7hOxLlifM/qgeHpRD9bF2flTz5KIrXnQqpuegaRuwP/HYdJ9TFkTKFjHkPLoE4onOz3HIT5CQ== + +"@biomejs/cli-win32-x64@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.0.4.tgz#ab504167d41c27727a61653ccb0f4e9f467b8bbc" + integrity sha512-dIM4SgO4/Rmsb4X7fwKtciQ682SZDSC1lm42uSM9gt8zNqBIeTaqsMc6eO1DpxYWMlAb/n2SML9+HUHmCib7NA== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -2038,11 +2092,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -prettier@3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" - integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== - pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"