Skip to content

Commit

Permalink
Improve config validation (#513)
Browse files Browse the repository at this point in the history
* add more validation for the config file

* check if route does exist

* Create good-radios-sleep.md
  • Loading branch information
conico974 authored Sep 22, 2024
1 parent 55a6bcc commit 4894974
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-radios-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"open-next": patch
---

Improve config validation
16 changes: 12 additions & 4 deletions packages/open-next/src/build/copyTracedFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,24 @@ export async function copyTracedFiles(
),
);
} catch (e) {
//TODO: add a link to the docs
throw new Error(
`
if (existsSync(path.join(standaloneNextDir, fullFilePath))) {
//TODO: add a link to the docs
throw new Error(
`
--------------------------------------------------------------------------------
${pagePath} cannot use the edge runtime.
OpenNext requires edge runtime function to be defined in a separate function.
See the docs for more information on how to bundle edge runtime functions.
--------------------------------------------------------------------------------
`,
);
);
} else {
throw new Error(`
--------------------------------------------------------------------------------
We cannot find the route for ${pagePath}.
File ${fullFilePath} does not exist
--------------------------------------------------------------------------------`);
}
}
const dir = path.dirname(fullFilePath);
extractFiles(
Expand Down
61 changes: 59 additions & 2 deletions packages/open-next/src/build/validateConfig.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,68 @@
import {
FunctionOptions,
IncludedConverter,
IncludedWrapper,
OpenNextConfig,
SplittedFunctionOptions,
} from "types/open-next";

import logger from "../logger.js";

const compatibilityMatrix: Record<IncludedWrapper, IncludedConverter[]> = {
"aws-lambda": [
"aws-apigw-v1",
"aws-apigw-v2",
"aws-cloudfront",
"sqs-revalidate",
],
"aws-lambda-streaming": ["aws-apigw-v2"],
cloudflare: ["edge"],
node: ["node"],
};

function validateFunctionOptions(fnOptions: FunctionOptions) {
if (fnOptions.runtime === "edge" && fnOptions.experimentalBundledNextServer) {
logger.warn(
"experimentalBundledNextServer has no effect for edge functions",
);
}
const wrapper =
typeof fnOptions.override?.wrapper === "string"
? fnOptions.override.wrapper
: "aws-lambda";
const converter =
typeof fnOptions.override?.converter === "string"
? fnOptions.override.converter
: "aws-apigw-v2";
if (
fnOptions.override?.generateDockerfile &&
fnOptions.override.converter !== "node" &&
fnOptions.override.wrapper !== "node"
converter !== "node" &&
wrapper !== "node"
) {
logger.warn(
"You've specified generateDockerfile without node converter and wrapper. Without custom converter and wrapper the dockerfile will not work",
);
}
if (converter === "aws-cloudfront" && fnOptions.placement !== "global") {
logger.warn(
"You've specified aws-cloudfront converter without global placement. This may not generate the correct output",
);
}
const isCustomWrapper = typeof fnOptions.override?.wrapper === "function";
const isCustomConverter = typeof fnOptions.override?.converter === "function";
// Check if the wrapper and converter are compatible
// Only check if using one of the included converters or wrapper
if (
!compatibilityMatrix[wrapper].includes(converter) &&
!isCustomWrapper &&
!isCustomConverter
) {
logger.error(
`Wrapper ${wrapper} and converter ${converter} are not compatible. For the wrapper ${wrapper} you should only use the following converters: ${compatibilityMatrix[
wrapper
].join(", ")}`,
);
}
}

function validateSplittedFunctionOptions(
Expand All @@ -31,6 +73,14 @@ function validateSplittedFunctionOptions(
if (fnOptions.routes.length === 0) {
throw new Error(`Splitted function ${name} must have at least one route`);
}
// Check if the routes are properly formated
fnOptions.routes.forEach((route) => {
if (!route.startsWith("app/") && !route.startsWith("pages/")) {
throw new Error(
`Route ${route} in function ${name} is not a valid route. It should starts with app/ or pages/ depending on if you use page or app router`,
);
}
});
if (fnOptions.runtime === "edge" && fnOptions.routes.length > 1) {
throw new Error(`Edge function ${name} can only have one route`);
}
Expand All @@ -53,4 +103,11 @@ export function validateConfig(config: OpenNextConfig) {
It is safe to disable if you only use page router`,
);
}
validateFunctionOptions(config.imageOptimization ?? {});
validateFunctionOptions(config.middleware ?? {});
//@ts-expect-error - Revalidate custom wrapper type is different
validateFunctionOptions(config.revalidate ?? {});
//@ts-expect-error - Warmer custom wrapper type is different
validateFunctionOptions(config.warmer ?? {});
validateFunctionOptions(config.initializationFunction ?? {});
}

0 comments on commit 4894974

Please sign in to comment.