diff --git a/src/commands/dev-exec/dev-exec.ts b/src/commands/dev-exec/dev-exec.ts index 7bbae8d5521..241df3bb92a 100644 --- a/src/commands/dev-exec/dev-exec.ts +++ b/src/commands/dev-exec/dev-exec.ts @@ -13,7 +13,11 @@ export const devExec = async (cmd: string, options: OptionValues, command: BaseC // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const withEnvelopeEnvVars = await getEnvelopeEnv({ api, context: options.context, env: cachedConfig.env, siteInfo }) - const env = await getDotEnvVariables({ devConfig: { ...config.dev }, env: withEnvelopeEnvVars, site }) + const env = await getDotEnvVariables({ + devConfig: { framework: '#auto', ...config.dev }, + env: withEnvelopeEnvVars, + site, + }) const { capabilities, siteUrl } = await getSiteInformation({ offline: false, diff --git a/src/commands/functions/functions-serve.ts b/src/commands/functions/functions-serve.ts index 453cd9444d3..7cd60070bd5 100644 --- a/src/commands/functions/functions-serve.ts +++ b/src/commands/functions/functions-serve.ts @@ -30,7 +30,7 @@ export const functionsServe = async (options: OptionValues, command: BaseCommand env.NETLIFY_DEV = { sources: ['internal'], value: 'true' } - env = await getDotEnvVariables({ devConfig: { ...config.dev }, env, site }) + env = await getDotEnvVariables({ devConfig: { framework: '#auto', ...config.dev }, env, site }) const { accountId, capabilities, siteUrl, timeouts } = await getSiteInformation({ offline: options.offline, diff --git a/src/utils/dev.ts b/src/utils/dev.ts index 8f929be9270..c1ee2193690 100644 --- a/src/utils/dev.ts +++ b/src/utils/dev.ts @@ -8,6 +8,7 @@ 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 { 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 +42,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: { id?: string }; siteInfo: SiteInfo }) => { if (isEmpty(siteInfo)) { return logAndThrowError( `Failed to retrieve project information for project ${chalk.yellow(site.id)}. ${ERROR_CALL_TO_ACTION}`, @@ -192,10 +192,17 @@ const getEnvSourceName = (source) => { /** * @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 => { - 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 +export const getDotEnvVariables = async ({ + devConfig, + env, + site, +}: { + devConfig: DevConfig + env: EnvironmentVariables + site: { root?: string } +}): Promise => { + const dotEnvFiles = await loadDotEnvFiles({ envFiles: devConfig.envFiles, projectDir: site.root || '' }) + dotEnvFiles.forEach(({ env: fileEnv, file }) => { const newSourceName = `${file} file` @@ -272,9 +279,8 @@ export const acquirePort = async ({ return acquiredPort } -// @ts-expect-error TS(7006) FIXME: Parameter 'fn' implicitly has an 'any' type. -export const processOnExit = (fn) => { - const signals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP', 'exit'] +export const processOnExit = (fn: (...args: unknown[]) => unknown) => { + const signals: (NodeJS.Signals | 'exit')[] = ['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..0c1d2f0032c 100644 --- a/src/utils/dot-env.ts +++ b/src/utils/dot-env.ts @@ -1,44 +1,65 @@ 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 }) { +interface LoadDotEnvFilesOptions { + envFiles?: string[] + projectDir: string +} + +export interface DotEnvFile { + file: string + env: DotenvParseOutput +} + +export interface DotEnvWarning { + warning: string +} + +type DotEnvResult = DotEnvFile | DotEnvWarning + +export const loadDotEnvFiles = async function ({ + envFiles, + projectDir, +}: LoadDotEnvFilesOptions): Promise { const response = 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) + const filesWithWarning = response.filter((result): result is DotEnvWarning => 'warning' in result) + filesWithWarning.forEach((result) => { + warn(result.warning) }) - // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. - return response.filter((el) => el.file && el.env) + return response.filter((result): result is DotEnvFile => 'file' in result && 'env' in result) } // 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 }) => { +interface TryLoadDotEnvFilesOptions { + dotenvFiles?: string[] + projectDir: string +} + +export const tryLoadDotEnvFiles = async ({ + dotenvFiles = defaultEnvFiles, + projectDir, +}: TryLoadDotEnvFilesOptions): Promise => { const results = await Promise.all( - dotenvFiles.map(async (file) => { + dotenvFiles.map(async (file): Promise => { const filepath = path.resolve(projectDir, file) try { const isFile = await isFileAsync(filepath) if (!isFile) { - return + return undefined } } 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 as Error).message}`, } } const content = await readFile(filepath, 'utf-8') @@ -48,5 +69,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 DotEnvResult => result !== undefined).reverse() } diff --git a/src/utils/types.ts b/src/utils/types.ts index f2c33e4b541..c851aaec982 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -219,7 +219,7 @@ export interface Template { } type EnvironmentVariableScope = 'builds' | 'functions' | 'runtime' | 'post_processing' -export type EnvironmentVariableSource = 'account' | 'addons' | 'configFile' | 'general' | 'internal' | 'ui' +export type EnvironmentVariableSource = 'account' | 'addons' | 'configFile' | 'general' | 'internal' | 'ui' | string export type EnvironmentVariables = Record< string,