diff --git a/src/commands/base-command.ts b/src/commands/base-command.ts index 4ec2c680369..90cfda60481 100644 --- a/src/commands/base-command.ts +++ b/src/commands/base-command.ts @@ -410,7 +410,6 @@ export default class BaseCommand extends Command { const authLink = `${webUI}/authorize?response_type=ticket&ticket=${ticket.id}` log(`Opening ${authLink}`) - // @ts-expect-error TS(2345) FIXME: Argument of type '{ url: string; }' is not assigna... Remove this comment to see the full error message await openBrowser({ url: authLink }) const accessToken = await pollForToken({ diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index ef4c0b4396b..4ae56fe9546 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -207,24 +207,14 @@ const validateFolders = async ({ return { deployFolderStat, functionsFolderStat } } -/** - * @param {object} config - * @param {string} config.deployFolder - * @param {*} config.site - * @returns - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'deployFolder' implicitly has an '... Remove this comment to see the full error message -const getDeployFilesFilter = ({ deployFolder, site }) => { +const getDeployFilesFilter = ({ deployFolder, site }: { deployFolder: string; site: { root: string } }) => { // site.root === deployFolder can happen when users run `netlify deploy --dir .` // in that specific case we don't want to publish the repo node_modules // when site.root !== deployFolder the behaviour matches our buildbot const skipNodeModules = site.root === deployFolder - /** - * @param {string} filename - */ - // @ts-expect-error TS(7006) FIXME: Parameter 'filename' implicitly has an 'any' type. - return (filename) => { + return (filename: string) => { + // TODO(serhalp) Per types, this should not be possible. Confirm and remove this check. if (filename == null) { return false } @@ -269,16 +259,20 @@ const prepareProductionDeploy = async ({ api, siteData }) => { log('Deploying to main site URL...') } -// @ts-expect-error TS(7006) FIXME: Parameter 'actual' implicitly has an 'any' type. -const hasErrorMessage = (actual, expected) => { +const hasErrorMessage = (actual: unknown, expected: string): boolean => { if (typeof actual === 'string') { return actual.includes(expected) } return false } -// @ts-expect-error TS(7031) FIXME: Binding element 'error_' implicitly has an 'any' t... Remove this comment to see the full error message -const reportDeployError = ({ error_, failAndExit }) => { +const reportDeployError = ({ + error_, + failAndExit, +}: { + error_: (Error & { json?: Record; status?: number }) | any + failAndExit: (errorOrMessage: Error | string) => void +}) => { switch (true) { case error_.name === 'JSONHTTPError': { const message = error_?.json?.message ?? '' @@ -488,7 +482,6 @@ const runDeploy = async ({ const { headers } = await parseAllHeaders({ configHeaders: config.headers, - // @ts-expect-error TS(2322) FIXME: Type 'string' is not assignable to type 'never'. headersFiles: [headersPath], minimal: true, }) @@ -906,7 +899,6 @@ export const deploy = async (options: OptionValues, command: BaseCommand) => { if (options.open) { const urlToOpen = deployToProduction ? results.siteUrl : results.deployUrl - // @ts-expect-error TS(2345) FIXME: Argument of type '{ url: any; }' is not assignable... Remove this comment to see the full error message await openBrowser({ url: urlToOpen }) exit() } diff --git a/src/commands/open/open-admin.ts b/src/commands/open/open-admin.ts index bd34c37b205..68690eb4cc4 100644 --- a/src/commands/open/open-admin.ts +++ b/src/commands/open/open-admin.ts @@ -12,7 +12,6 @@ export const openAdmin = async (options: OptionValues, command: BaseCommand) => log(`Opening "${siteInfo.name}" site admin UI:`) log(`> ${siteInfo.admin_url}`) - // @ts-expect-error TS(2345) FIXME: Argument of type '{ url: any; }' is not assignable... Remove this comment to see the full error message await openBrowser({ url: siteInfo.admin_url }) exit() } diff --git a/src/commands/open/open-site.ts b/src/commands/open/open-site.ts index a4730a096fc..46969c38831 100644 --- a/src/commands/open/open-site.ts +++ b/src/commands/open/open-site.ts @@ -13,7 +13,6 @@ export const openSite = async (options: OptionValues, command: BaseCommand) => { log(`Opening "${siteInfo.name}" site url:`) log(`> ${url}`) - // @ts-expect-error TS(2345) FIXME: Argument of type '{ url: any; }' is not assignable... Remove this comment to see the full error message await openBrowser({ url }) exit() } diff --git a/src/utils/gh-auth.ts b/src/utils/gh-auth.ts index 1739b91e6b9..516e4ea2c99 100644 --- a/src/utils/gh-auth.ts +++ b/src/utils/gh-auth.ts @@ -81,7 +81,6 @@ export const authWithNetlify = async () => { }) const url = `${webUI}/cli?${urlParams.toString()}` - // @ts-expect-error TS(2345) FIXME: Argument of type '{ url: string; }' is not assigna... Remove this comment to see the full error message await openBrowser({ url }) return deferredPromise diff --git a/src/utils/headers.ts b/src/utils/headers.ts index de5f9cdf5bf..a9bebe254a4 100644 --- a/src/utils/headers.ts +++ b/src/utils/headers.ts @@ -1,33 +1,29 @@ -import { parseAllHeaders } from '@netlify/headers-parser' +import { type Header, type MinimalHeader, parseAllHeaders } from '@netlify/headers-parser' import { NETLIFYDEVERR, log } from './command-helpers.js' /** * Get the matching headers for `path` given a set of `rules`. - * - * @param {Object>!} headers - * The rules to use for matching. - * - * @param {string!} path - * The path to match against. - * - * @returns {Object} */ -// @ts-expect-error TS(7006) FIXME: Parameter 'headers' implicitly has an 'any' type. -export const headersForPath = function (headers, path) { - // @ts-expect-error TS(7031) FIXME: Binding element 'forRegExp' implicitly has an 'any... Remove this comment to see the full error message - const matchingHeaders = headers.filter(({ forRegExp }) => forRegExp.test(path)).map(getHeaderValues) - const headersRules = Object.assign({}, ...matchingHeaders) +export const headersForPath = function (headers: Header[], path: string) { + const matchingHeaders = headers.filter(({ forRegExp }) => forRegExp.test(path)).map(({ values }) => values) + const headersRules = { ...matchingHeaders } return headersRules } -// @ts-expect-error TS(7031) FIXME: Binding element 'values' implicitly has an 'any' t... Remove this comment to see the full error message -const getHeaderValues = function ({ values }) { - return values -} - -// @ts-expect-error TS(7031) FIXME: Binding element 'configPath' implicitly has an 'an... Remove this comment to see the full error message -export const parseHeaders = async function ({ config, configPath, headersFiles }): Promise { +export const parseHeaders = async function ({ + config, + configPath, + headersFiles, +}: { + config?: + | undefined + | { + headers?: undefined | MinimalHeader[] + } + configPath?: undefined | string + headersFiles?: undefined | string[] +}): Promise { const { errors, headers } = await parseAllHeaders({ headersFiles, netlifyConfigPath: configPath, @@ -35,11 +31,10 @@ export const parseHeaders = async function ({ config, configPath, headersFiles } configHeaders: config?.headers || [], }) handleHeadersErrors(errors) - return headers + return headers as Header[] } -// @ts-expect-error TS(7006) FIXME: Parameter 'errors' implicitly has an 'any' type. -const handleHeadersErrors = function (errors) { +const handleHeadersErrors = function (errors: Error[]): void { if (errors.length === 0) { return } @@ -48,8 +43,7 @@ const handleHeadersErrors = function (errors) { log(NETLIFYDEVERR, `Headers syntax errors:\n${errorMessage}`) } -// @ts-expect-error TS(7031) FIXME: Binding element 'message' implicitly has an 'any' ... Remove this comment to see the full error message -const getErrorMessage = function ({ message }) { +const getErrorMessage = function ({ message }: Error): string { return message } diff --git a/src/utils/open-browser.ts b/src/utils/open-browser.ts index 7c7df65db4b..22eaebc7e53 100644 --- a/src/utils/open-browser.ts +++ b/src/utils/open-browser.ts @@ -19,7 +19,7 @@ const unableToOpenBrowserMessage = function ({ message, url }: BrowserUnableMess } type OpenBrowsrProps = { - silentBrowserNoneError: boolean + silentBrowserNoneError?: boolean url: string } diff --git a/src/utils/proxy.ts b/src/utils/proxy.ts index db28d13cb93..a62dc2b16d9 100644 --- a/src/utils/proxy.ts +++ b/src/utils/proxy.ts @@ -18,9 +18,9 @@ import generateETag from 'etag' import getAvailablePort from 'get-port' import httpProxy from 'http-proxy' import { createProxyMiddleware } from 'http-proxy-middleware' -import { jwtDecode } from 'jwt-decode' +import { jwtDecode, type JwtPayload } from 'jwt-decode' import { locatePath } from 'locate-path' -import { Match } from 'netlify-redirector' +import type { Match } from 'netlify-redirector' import pFilter from 'p-filter' import throttle from 'lodash/throttle.js' @@ -102,8 +102,7 @@ const injectHtml = async function ( return await compressResponseBody(bodyWithInjections, proxyRes.headers['content-encoding']) } -// @ts-expect-error TS(7006) FIXME: Parameter 'errorBuffer' implicitly has an 'any' ty... Remove this comment to see the full error message -const formatEdgeFunctionError = (errorBuffer, acceptsHtml) => { +const formatEdgeFunctionError = (errorBuffer: Buffer, acceptsHtml: boolean): string => { const { error: { message, name, stack }, } = JSON.parse(errorBuffer.toString()) @@ -156,13 +155,11 @@ const isEndpointExists = async function (endpoint: string, origin: string) { } } -// @ts-expect-error TS(7006) FIXME: Parameter 'match' implicitly has an 'any' type. -const isExternal = function (match) { - return match.to && match.to.match(/^https?:\/\//) +const isExternal = function (match: Match) { + return 'to' in match && match.to.match(/^https?:\/\//) } -// @ts-expect-error TS(7031) FIXME: Binding element 'hash' implicitly has an 'any' typ... Remove this comment to see the full error message -const stripOrigin = function ({ hash, pathname, search }) { +const stripOrigin = function ({ hash, pathname, search }: URL): string { return `${pathname}${search}${hash}` } @@ -189,21 +186,18 @@ const proxyToExternalUrl = function ({ return handler(req, res, () => {}) } -// @ts-expect-error TS(7031) FIXME: Binding element 'addonUrl' implicitly has an 'any'... Remove this comment to see the full error message -const handleAddonUrl = function ({ addonUrl, req, res }) { +const handleAddonUrl = function ({ addonUrl, req, res }: { req: Request; res: ServerResponse; addonUrl: string }) { const dest = new URL(addonUrl) const destURL = stripOrigin(dest) return proxyToExternalUrl({ req, res, dest, destURL }) } -// @ts-expect-error TS(7006) FIXME: Parameter 'match' implicitly has an 'any' type. -const isRedirect = function (match) { - return match.status && match.status >= 300 && match.status <= 400 +const isRedirect = function (match: Match) { + return 'status' in match && match.status >= 300 && match.status <= 400 } -// @ts-expect-error TS(7006) FIXME: Parameter 'publicFolder' implicitly has an 'any' t... Remove this comment to see the full error message -const render404 = async function (publicFolder) { +const render404 = async function (publicFolder: string) { const maybe404Page = path.resolve(publicFolder, '404.html') try { const isFile = await isFileAsync(maybe404Page) @@ -219,8 +213,7 @@ const render404 = async function (publicFolder) { // Used as an optimization to avoid dual lookups for missing assets const assetExtensionRegExp = /\.(html?|png|jpg|js|css|svg|gif|ico|woff|woff2)$/ -// @ts-expect-error TS(7006) FIXME: Parameter 'url' implicitly has an 'any' type. -const alternativePathsFor = function (url) { +const alternativePathsFor = function (url: string) { if (isFunction(true, url)) { return [] } @@ -317,9 +310,9 @@ const serveRedirect = async function ({ req.url = '/.netlify/non-existent-path' if (token) { - let jwtValue = {} + let jwtValue: JwtPayload = {} try { - jwtValue = jwtDecode(token) || {} + jwtValue = jwtDecode(token) } catch (error) { // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. console.warn(NETLIFYDEVWARN, 'Error while decoding JWT provided in request', error.message) @@ -328,7 +321,6 @@ const serveRedirect = async function ({ return } - // @ts-expect-error TS(2339) FIXME: Property 'exp' does not exist on type '{}'. if ((jwtValue.exp || 0) < Math.round(Date.now() / MILLISEC_TO_SEC)) { console.warn(NETLIFYDEVWARN, 'Expired JWT provided in request', req.url) } else { @@ -463,10 +455,9 @@ const serveRedirect = async function ({ return proxy.web(req, res, options) } -// @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. -const reqToURL = function (req, pathname) { +const reqToURL = function (req: Request, pathname: undefined | string) { return new URL( - pathname, + pathname ?? '', `${req.protocol || (req.headers.scheme && `${req.headers.scheme}:`) || 'http:'}//${ req.headers.host || req.hostname }`, @@ -613,10 +604,8 @@ const initializeProxy = async function ({ }) } - // @ts-expect-error TS(7034) FIXME: Variable 'responseData' implicitly has type 'any[]... Remove this comment to see the full error message - const responseData = [] - // @ts-expect-error TS(2345) FIXME: Argument of type 'string | undefined' is not assig... Remove this comment to see the full error message - const requestURL = new URL(req.url, `http://${req.headers.host || '127.0.0.1'}`) + const responseData: Uint8Array[] = [] + const requestURL = new URL(req.url ?? '', `http://${req.headers.host || '127.0.0.1'}`) const headersRules = headersForPath(headers, requestURL.pathname) const htmlInjections = @@ -650,11 +639,10 @@ const initializeProxy = async function ({ } proxyRes.on('data', function onData(data) { - responseData.push(data) + responseData.push(data as Uint8Array) }) proxyRes.on('end', async function onEnd() { - // @ts-expect-error TS(7005) FIXME: Variable 'responseData' implicitly has an 'any[]' ... Remove this comment to see the full error message let responseBody = Buffer.concat(responseData) // @ts-expect-error TS(2339) FIXME: Property 'proxyOptions' does not exist on type 'In... Remove this comment to see the full error message @@ -685,7 +673,7 @@ const initializeProxy = async function ({ const isUncaughtError = proxyRes.headers['x-nf-uncaught-error'] === '1' if (isEdgeFunctionsRequest(req) && isUncaughtError) { - const acceptsHtml = req.headers && req.headers.accept && req.headers.accept.includes('text/html') + const acceptsHtml = req.headers?.accept?.includes('text/html') ?? false const decompressedBody = await decompressResponseBody(responseBody, proxyRes.headers['content-encoding']) const formattedBody = formatEdgeFunctionError(decompressedBody, acceptsHtml) const errorResponse = acceptsHtml @@ -778,16 +766,13 @@ const onRequest = async ( if (functionMatch) { // Setting an internal header with the function name so that we don't // have to match the URL again in the functions server. - /** @type {Record} */ - const headers = {} + const headers: Record = {} if (functionMatch.func) { - // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message headers[NFFunctionName] = functionMatch.func.name } if (functionMatch.route) { - // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message headers[NFFunctionRoute] = functionMatch.route.pattern } @@ -816,7 +801,7 @@ const onRequest = async ( if (match) { // We don't want to generate an ETag for 3xx redirects. // @ts-expect-error TS(7031) FIXME: Binding element 'statusCode' implicitly has an 'an... Remove this comment to see the full error message - req[shouldGenerateETag] = ({ statusCode }) => statusCode < 300 || statusCode >= 400 + req[shouldGenerateETag] = ({ statusCode }: { statusCode: number }) => statusCode < 300 || statusCode >= 400 return serveRedirect({ req, res, proxy, imageProxy, match, options, siteInfo, env, functionsRegistry }) } @@ -825,7 +810,7 @@ const onRequest = async ( // generate an ETag unless we're rendering an error page. The only way for // us to know that is by looking at the status code // @ts-expect-error TS(7031) FIXME: Binding element 'statusCode' implicitly has an 'an... Remove this comment to see the full error message - req[shouldGenerateETag] = ({ statusCode }) => statusCode >= 200 && statusCode < 300 + req[shouldGenerateETag] = ({ statusCode }: { statusCode: number }) => statusCode >= 200 && statusCode < 300 const hasFormSubmissionHandler: boolean = functionsRegistry && getFormHandler({ functionsRegistry, logWarning: false }) diff --git a/src/utils/rules-proxy.ts b/src/utils/rules-proxy.ts index 924d75e1aac..fe31c837a77 100644 --- a/src/utils/rules-proxy.ts +++ b/src/utils/rules-proxy.ts @@ -1,6 +1,8 @@ +import type { Stats } from 'fs' +import type { IncomingHttpHeaders } from 'http' import path from 'path' -import chokidar from 'chokidar' +import chokidar, { type FSWatcher } from 'chokidar' import cookie from 'cookie' import redirector from 'netlify-redirector' import type { Match, RedirectMatcher } from 'netlify-redirector' @@ -12,12 +14,12 @@ import { NETLIFYDEVLOG } from './command-helpers.js' import { parseRedirects } from './redirects.js' import { Request, Rewriter } from './types.js' -// @ts-expect-error TS(7034) FIXME: Variable 'watchers' implicitly has type 'any[]' in... Remove this comment to see the full error message -const watchers = [] +// Not exported by chokidar for some reason +type FSListener = (path: string, stats?: Stats) => void -// @ts-expect-error TS(7006) FIXME: Parameter 'files' implicitly has an 'any' type. -export const onChanges = function (files, listener) { - // @ts-expect-error TS(7006) FIXME: Parameter 'file' implicitly has an 'any' type. +const watchers: FSWatcher[] = [] + +export const onChanges = function (files: string[], listener: FSListener) { files.forEach((file) => { const watcher = chokidar.watch(file) watcher.on('change', listener) @@ -26,13 +28,11 @@ export const onChanges = function (files, listener) { }) } -export const getWatchers = function () { - // @ts-expect-error TS(7005) FIXME: Variable 'watchers' implicitly has an 'any[]' type... Remove this comment to see the full error message +export const getWatchers = function (): FSWatcher[] { return watchers } -// @ts-expect-error TS(7006) FIXME: Parameter 'headers' implicitly has an 'any' type. -export const getLanguage = function (headers) { +export const getLanguage = function (headers: IncomingHttpHeaders): string { if (headers['accept-language']) { return headers['accept-language'].split(',')[0].slice(0, 2) } @@ -86,7 +86,6 @@ export const createRewriter = async function ({ } } - // @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. return async function rewriter(req: Request): Promise { const matcherFunc = await getMatcher() const reqUrl = new URL( diff --git a/src/utils/types.ts b/src/utils/types.ts index 356ce2be3ff..fa5729b1091 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -61,7 +61,7 @@ export interface Request extends IncomingMessage { hostname?: string } -export type Rewriter = (req: Request) => Match | null +export type Rewriter = (req: Request) => Promise export interface SiteInfo { account_name: string diff --git a/tsconfig.json b/tsconfig.json index df827291514..ef510b4955c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,9 @@ "compilerOptions": { "outDir": "dist", "incremental": true, - "lib": ["es2020"], + "lib": [ + "es2020" + ], "target": "es2020", "module": "NodeNext", "moduleResolution": "NodeNext",