diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 187ede4e35b..f239ef8ee0e 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -228,20 +228,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 return (filename: string) => { + // TODO(serhalp) Per types, this should not be possible. Confirm and remove this check. if (filename == null) { return false } @@ -285,16 +279,20 @@ const prepareProductionDeploy = async ({ api, siteData }) => { } } -// @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 ?? '' diff --git a/src/commands/functions/functions-create.ts b/src/commands/functions/functions-create.ts index 36f2bcec074..65e6ceb773f 100644 --- a/src/commands/functions/functions-create.ts +++ b/src/commands/functions/functions-create.ts @@ -640,7 +640,7 @@ const handleAddonDidInstall = async ({ addonCreated, addonDidInstall, command, f return } - await injectEnvVariables({ + injectEnvVariables({ devConfig: { ...config.dev }, env: command.netlify.cachedConfig.env, site: command.netlify.site, diff --git a/src/commands/types.d.ts b/src/commands/types.d.ts index 05549730643..f879e2121dd 100644 --- a/src/commands/types.d.ts +++ b/src/commands/types.d.ts @@ -14,7 +14,7 @@ export type NetlifySite = { configPath?: string siteId?: string get id(): string | undefined - set id(id: string): void + set id(id: string) } /** diff --git a/src/utils/dev.ts b/src/utils/dev.ts index 4de6efce2fd..86b1a29ced7 100644 --- a/src/utils/dev.ts +++ b/src/utils/dev.ts @@ -8,6 +8,9 @@ import { supportsBackgroundFunctions } from '../lib/account.js' import { NETLIFYDEVLOG, chalk, logAndThrowError, log, warn, APIError } from './command-helpers.js' import { loadDotEnvFiles } from './dot-env.js' +import type { CachedConfig } from '../lib/build.js' +import type { NetlifySite } from '../commands/types.js' +import type { DevConfig } from '../commands/dev/types.js' import type { EnvironmentVariables, SiteInfo } from './types.js' // Possible sources of environment variables. For the purpose of printing log messages only. Order does not matter. @@ -41,8 +44,7 @@ const ENV_VAR_SOURCES = { const ERROR_CALL_TO_ACTION = "Double-check your login status with 'netlify status' or contact support with details of your error." -// @ts-expect-error TS(7031) FIXME: Binding element 'site' implicitly has an 'any' typ... Remove this comment to see the full error message -const validateSiteInfo = ({ site, siteInfo }) => { +const validateSiteInfo = ({ site, siteInfo }: { site: NetlifySite; siteInfo: SiteInfo }): void => { if (isEmpty(siteInfo)) { return logAndThrowError( `Failed to retrieve project information for project ${chalk.yellow(site.id)}. ${ERROR_CALL_TO_ACTION}`, @@ -73,9 +75,9 @@ const getAccounts = async ({ api }: { api: NetlifyAPI }) => { } } -// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message -const getAddons = async ({ api, site }) => { +const getAddons = async ({ api, site }: { api: NetlifyAPI; site: NetlifySite }) => { try { + // @ts-expect-error(serhalp) One of three types is incorrect here (is `site.id` optional?). Dig and fix. const addons = await api.listServiceInstancesForSite({ siteId: site.id }) return addons } catch (error_) { @@ -87,13 +89,11 @@ const getAddons = async ({ api, site }) => { } } -// @ts-expect-error TS(7031) FIXME: Binding element 'addons' implicitly has an 'any' t... Remove this comment to see the full error message -const getAddonsInformation = ({ addons, siteInfo }) => { +type Addons = Awaited> +const getAddonsInformation = ({ addons, siteInfo }: { addons: Addons; siteInfo: SiteInfo }) => { const urls = Object.fromEntries( - // @ts-expect-error TS(7006) FIXME: Parameter 'addon' implicitly has an 'any' type. addons.map((addon) => [addon.service_slug, `${siteInfo.ssl_url}${addon.service_path}`]), ) - // @ts-expect-error TS(7006) FIXME: Parameter 'addon' implicitly has an 'any' type. const env = Object.assign({}, ...addons.map((addon) => addon.env)) return { urls, env } } @@ -113,17 +113,17 @@ const SYNCHRONOUS_FUNCTION_TIMEOUT = 30 // default 15 minutes for background functions const BACKGROUND_FUNCTION_TIMEOUT = 900 -/** - * - * @param {object} config - * @param {boolean} config.offline - * @param {*} config.api - * @param {*} config.site - * @param {*} config.siteInfo - * @returns - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message -export const getSiteInformation = async ({ api, offline, site, siteInfo }) => { +export const getSiteInformation = async ({ + api, + offline, + site, + siteInfo, +}: { + api: NetlifyAPI + offline: boolean + site: NetlifySite + siteInfo: SiteInfo +}) => { if (site.id && !offline) { validateSiteInfo({ site, siteInfo }) const [accounts, addons] = await Promise.all([getAccounts({ api }), getAddons({ api, site })]) @@ -157,21 +157,22 @@ export const getSiteInformation = async ({ api, offline, site, siteInfo }) => { } } -// @ts-expect-error TS(7006) FIXME: Parameter 'source' implicitly has an 'any' type. -const getEnvSourceName = (source) => { - // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - const { name = source, printFn = chalk.green } = ENV_VAR_SOURCES[source] || {} +const getEnvSourceName = (source: string) => { + const { name = source, printFn = chalk.green } = ENV_VAR_SOURCES[source] ?? {} return printFn(name) } -/** - * @param {{devConfig: any, env: Record, site: any}} param0 - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message -export const getDotEnvVariables = async ({ devConfig, env, site }): Promise => { +export const getDotEnvVariables = async ({ + devConfig, + env, + site, +}: { + devConfig: DevConfig + env: CachedConfig['env'] + site: NetlifySite +}): Promise> => { const dotEnvFiles = await loadDotEnvFiles({ envFiles: devConfig.envFiles, projectDir: site.root }) - // @ts-expect-error TS(2339) FIXME: Property 'env' does not exist on type '{ warning: ... Remove this comment to see the full error message dotEnvFiles.forEach(({ env: fileEnv, file }) => { const newSourceName = `${file} file` @@ -183,6 +184,7 @@ export const getDotEnvVariables = async ({ devConfig, env, site }): Promise { +export const processOnExit = (fn: (...args: unknown[]) => void) => { const signals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP', 'exit'] signals.forEach((signal) => { process.on(signal, fn) diff --git a/src/utils/dot-env.ts b/src/utils/dot-env.ts index 27cebc92163..a56187e68dd 100644 --- a/src/utils/dot-env.ts +++ b/src/utils/dot-env.ts @@ -1,35 +1,48 @@ import { readFile } from 'fs/promises' import path from 'path' -import dotenv from 'dotenv' +import dotenv, { type DotenvParseOutput } from 'dotenv' import { isFileAsync } from '../lib/fs.js' import { warn } from './command-helpers.js' -// @ts-expect-error TS(7031) FIXME: Binding element 'envFiles' implicitly has an 'any'... Remove this comment to see the full error message -export const loadDotEnvFiles = async function ({ envFiles, projectDir }) { - const response = await tryLoadDotEnvFiles({ projectDir, dotenvFiles: envFiles }) +interface LoadedDotEnvFile { + file: string + env: DotenvParseOutput +} + +export const loadDotEnvFiles = async function ({ + envFiles, + projectDir, +}: { + envFiles?: string[] + projectDir?: string +}): Promise { + const loadedDotEnvFiles = await tryLoadDotEnvFiles({ projectDir, dotenvFiles: envFiles }) - // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. - const filesWithWarning = response.filter((el) => el.warning) - filesWithWarning.forEach((el) => { - // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. - warn(el.warning) - }) + loadedDotEnvFiles + .filter((el): el is { warning: string } => 'warning' in el) + .forEach((el) => { + warn(el.warning) + }) - // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. - return response.filter((el) => el.file && el.env) + return loadedDotEnvFiles.filter((el): el is LoadedDotEnvFile => 'file' in el && 'env' in el) } // in the user configuration, the order is highest to lowest const defaultEnvFiles = ['.env.development.local', '.env.local', '.env.development', '.env'] -// @ts-expect-error TS(7031) FIXME: Binding element 'projectDir' implicitly has an 'an... Remove this comment to see the full error message -export const tryLoadDotEnvFiles = async ({ dotenvFiles = defaultEnvFiles, projectDir }) => { +export const tryLoadDotEnvFiles = async ({ + dotenvFiles = defaultEnvFiles, + projectDir, +}: { + dotenvFiles?: string[] + projectDir?: string +}): Promise> => { const results = await Promise.all( dotenvFiles.map(async (file) => { - const filepath = path.resolve(projectDir, file) + const filepath = path.resolve(projectDir ?? '', file) try { const isFile = await isFileAsync(filepath) if (!isFile) { @@ -37,8 +50,9 @@ export const tryLoadDotEnvFiles = async ({ dotenvFiles = defaultEnvFiles, projec } } catch (error) { return { - // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. - warning: `Failed reading env variables from file: ${filepath}: ${error.message}`, + warning: `Failed reading env variables from file: ${filepath}: ${ + error instanceof Error ? error.message : error?.toString() + }`, } } const content = await readFile(filepath, 'utf-8') @@ -48,5 +62,5 @@ export const tryLoadDotEnvFiles = async ({ dotenvFiles = defaultEnvFiles, projec ) // we return in order of lowest to highest priority - return results.filter(Boolean).reverse() + return results.filter((result): result is LoadedDotEnvFile => result != null).reverse() } diff --git a/src/utils/open-browser.ts b/src/utils/open-browser.ts index 22eaebc7e53..8030fa22c0d 100644 --- a/src/utils/open-browser.ts +++ b/src/utils/open-browser.ts @@ -18,12 +18,12 @@ const unableToOpenBrowserMessage = function ({ message, url }: BrowserUnableMess log('---------------------------') } -type OpenBrowsrProps = { +type OpenBrowserProps = { silentBrowserNoneError?: boolean url: string } -const openBrowser = async function ({ silentBrowserNoneError, url }: OpenBrowsrProps) { +const openBrowser = async function ({ silentBrowserNoneError, url }: OpenBrowserProps) { if (isDockerContainer()) { unableToOpenBrowserMessage({ url, message: 'Running inside a docker container' }) return diff --git a/src/utils/proxy-server.ts b/src/utils/proxy-server.ts index 8e8f1159f9f..38fdf01f3ef 100644 --- a/src/utils/proxy-server.ts +++ b/src/utils/proxy-server.ts @@ -64,7 +64,7 @@ export const startProxyServer = async ({ state, }: { accountId: string | undefined - addonsUrls: $TSFixMe + addonsUrls: Record api?: NetlifyOptions['api'] blobsContext?: BlobsContextWithEdgeAccess command: BaseCommand