diff --git a/src/constants.ts b/src/constants.ts index 58ee77f39e..e1c7934fb9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -17,7 +17,7 @@ export const HIDDEN_PATHS = [ export const ODB_FUNCTION_PATH = `/.netlify/builders/${ODB_FUNCTION_NAME}` export const HANDLER_FUNCTION_PATH = `/.netlify/functions/${HANDLER_FUNCTION_NAME}` - +export const DEFAULT_FUNCTIONS_SRC = 'netlify/functions' export const CATCH_ALL_REGEX = /\/\[\.{3}(.*)](.json)?$/ export const OPTIONAL_CATCH_ALL_REGEX = /\/\[{2}\.{3}(.*)]{2}(.json)?$/ export const DYNAMIC_PARAMETER_REGEX = /\/\[(.*?)]/g diff --git a/src/helpers/config.ts b/src/helpers/config.ts index 9438610a24..bc99263940 100644 --- a/src/helpers/config.ts +++ b/src/helpers/config.ts @@ -1,16 +1,28 @@ import { readJSON } from 'fs-extra' +import type { NextConfigComplete } from 'next/dist/server/config-shared' import { join, dirname, relative } from 'pathe' import slash from 'slash' import { HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME } from '../constants' -import { RequiredServerFiles } from './requiredServerFilesType' +export interface RequiredServerFiles { + version?: number + config?: NextConfigComplete + appDir?: string + files?: string[] + ignore?: string[] +} + +export type NextConfig = Pick & NextConfigComplete const defaultFailBuild = (message: string, { error }): never => { throw new Error(`${message}\n${error && error.stack}`) } -export const getNextConfig = async function getNextConfig({ publish, failBuild = defaultFailBuild }) { +export const getNextConfig = async function getNextConfig({ + publish, + failBuild = defaultFailBuild, +}): Promise { try { const { config, appDir, ignore }: RequiredServerFiles = await readJSON(join(publish, 'required-server-files.json')) if (!config) { diff --git a/src/helpers/functions.js b/src/helpers/functions.ts similarity index 73% rename from src/helpers/functions.js rename to src/helpers/functions.ts index eda66224b1..e0665487d0 100644 --- a/src/helpers/functions.js +++ b/src/helpers/functions.ts @@ -1,23 +1,23 @@ -const { copyFile, ensureDir, writeFile, writeJSON } = require('fs-extra') -const { join, relative } = require('pathe') +import { NetlifyConfig, NetlifyPluginConstants } from '@netlify/build' +import { copyFile, ensureDir, writeFile, writeJSON } from 'fs-extra' +import type { ImageConfigComplete } from 'next/dist/server/image-config' +import { join, relative } from 'pathe' -const { HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME, IMAGE_FUNCTION_NAME } = require('../constants') -const getHandler = require('../templates/getHandler') -const { getPageResolver } = require('../templates/getPageResolver') +import { HANDLER_FUNCTION_NAME, ODB_FUNCTION_NAME, IMAGE_FUNCTION_NAME, DEFAULT_FUNCTIONS_SRC } from '../constants' +import getHandler from '../templates/getHandler' +import { getPageResolver } from '../templates/getPageResolver' -const DEFAULT_FUNCTIONS_SRC = 'netlify/functions' - -exports.generateFunctions = async ( - { FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC, PUBLISH_DIR }, - appDir, -) => { +export const generateFunctions = async ( + { FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC, PUBLISH_DIR }: NetlifyPluginConstants, + appDir: string, +): Promise => { const functionsDir = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC const bridgeFile = require.resolve('@vercel/node/dist/bridge') const functionDir = join(process.cwd(), functionsDir, HANDLER_FUNCTION_NAME) const publishDir = relative(functionDir, join(process.cwd(), PUBLISH_DIR)) - const writeHandler = async (func, isODB) => { + const writeHandler = async (func: string, isODB: boolean) => { const handlerSource = await getHandler({ isODB, publishDir, appDir: relative(functionDir, appDir) }) await ensureDir(join(functionsDir, func)) await writeFile(join(functionsDir, func, `${func}.js`), handlerSource) @@ -36,11 +36,15 @@ exports.generateFunctions = async ( * Writes a file in each function directory that contains references to every page entrypoint. * This is just so that the nft bundler knows about them. We'll eventually do this better. */ -exports.generatePagesResolver = async ({ +export const generatePagesResolver = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC }, netlifyConfig, target, -}) => { +}: { + constants: NetlifyPluginConstants + netlifyConfig: NetlifyConfig + target: string +}): Promise => { const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC const jsSource = await getPageResolver({ @@ -53,12 +57,17 @@ exports.generatePagesResolver = async ({ } // Move our next/image function into the correct functions directory -exports.setupImageFunction = async ({ +export const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = DEFAULT_FUNCTIONS_SRC }, imageconfig = {}, netlifyConfig, basePath, -}) => { +}: { + constants: NetlifyPluginConstants + netlifyConfig: NetlifyConfig + basePath: string + imageconfig: Partial +}): Promise => { const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC const functionName = `${IMAGE_FUNCTION_NAME}.js` const functionDirectory = join(functionsPath, IMAGE_FUNCTION_NAME) diff --git a/src/helpers/requiredServerFilesType.ts b/src/helpers/requiredServerFilesType.ts deleted file mode 100644 index 486331804e..0000000000 --- a/src/helpers/requiredServerFilesType.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint-disable eslint-comments/disable-enable-pair, @typescript-eslint/no-empty-interface, no-use-before-define */ -/** - * This was generated using @see {@link https://quicktype.io/}, and using the - * demo's {@code demos/default/.next/required-server-files.json} file. I was - * unable to find any types for this file so instead this was manually generated - */ - -export interface RequiredServerFiles { - version?: number; - config?: Config; - appDir?: string; - files?: string[]; - ignore?: string[]; -} - -export interface Env { -} - -export interface Config { - env?: Env; - webpack?: null; - webpackDevMiddleware?: null; - eslint?: Eslint; - typescript?: Typescript; - distDir?: string; - cleanDistDir?: boolean; - assetPrefix?: string; - configOrigin?: string; - useFileSystemPublicRoutes?: boolean; - generateEtags?: boolean; - pageExtensions?: string[]; - target?: string; - poweredByHeader?: boolean; - compress?: boolean; - analyticsId?: string; - images?: Images; - devIndicators?: DevIndicators; - onDemandEntries?: OnDemandEntries; - amp?: Amp; - basePath?: string; - sassOptions?: Env; - trailingSlash?: boolean; - i18n?: I18N; - productionBrowserSourceMaps?: boolean; - optimizeFonts?: boolean; - excludeDefaultMomentLocales?: boolean; - serverRuntimeConfig?: Env; - publicRuntimeConfig?: Env; - reactStrictMode?: boolean; - httpAgentOptions?: HTTPAgentOptions; - outputFileTracing?: boolean; - staticPageGenerationTimeout?: number; - swcMinify?: boolean; - experimental?: Experimental; - future?: Future; - configFileName?: string; -} - -export interface Amp { - canonicalBase?: string; -} - -export interface DevIndicators { - buildActivity?: boolean; - buildActivityPosition?: string; -} - -export interface Eslint { - ignoreDuringBuilds?: boolean; -} - -export interface Experimental { - cpus?: number; - sharedPool?: boolean; - plugins?: boolean; - profiling?: boolean; - isrFlushToDisk?: boolean; - workerThreads?: boolean; - pageEnv?: boolean; - optimizeImages?: boolean; - optimizeCss?: boolean; - scrollRestoration?: boolean; - externalDir?: boolean; - reactRoot?: boolean; - disableOptimizedLoading?: boolean; - gzipSize?: boolean; - craCompat?: boolean; - esmExternals?: boolean; - isrMemoryCacheSize?: number; - concurrentFeatures?: boolean; - serverComponents?: boolean; - fullySpecified?: boolean; - outputFileTracingRoot?: string; - outputStandalone?: boolean; -} - -export interface Future { - strictPostcssConfiguration?: boolean; -} - -export interface HTTPAgentOptions { - keepAlive?: boolean; -} - -export interface I18N { - defaultLocale?: string; - locales?: string[]; -} - -export interface Images { - deviceSizes?: number[]; - imageSizes?: number[]; - path?: string; - loader?: string; - domains?: any[]; - disableStaticImages?: boolean; - minimumCacheTTL?: number; - formats?: string[]; -} - -export interface OnDemandEntries { - maxInactiveAge?: number; - pagesBufferLength?: number; -} - -export interface Typescript { - ignoreBuildErrors?: boolean; - tsconfigPath?: string; -}