@opennextjs/aws 3.7.5 → 3.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/compileConfig.d.ts +20 -5
- package/dist/build/compileConfig.js +26 -11
- package/dist/build/createAssets.js +13 -7
- package/dist/build/createImageOptimizationBundle.js +2 -1
- package/dist/build/edge/createEdgeBundle.js +2 -1
- package/dist/build.js +2 -1
- package/dist/core/routing/cacheInterceptor.js +5 -2
- package/dist/overrides/tagCache/fs-dev-nextMode.d.ts +8 -0
- package/dist/overrides/tagCache/fs-dev-nextMode.js +42 -0
- package/dist/overrides/tagCache/fs-dev.js +14 -10
- package/dist/overrides/wrappers/express-dev.js +3 -0
- package/dist/types/open-next.d.ts +1 -1
- package/dist/utils/safe-json-parse.d.ts +1 -0
- package/dist/utils/safe-json-parse.js +10 -0
- package/package.json +1 -1
|
@@ -4,18 +4,33 @@ import type { OpenNextConfig } from "../types/open-next.js";
|
|
|
4
4
|
*
|
|
5
5
|
* The configuration is always compiled for Node.js and for the edge only if needed.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
8
|
-
* @param openNextConfigPath Override the default configuration when provided. Relative to baseDir.
|
|
7
|
+
* @param openNextConfigPath Path to the configuration file. Absolute or relative to cwd.
|
|
9
8
|
* @param nodeExternals Coma separated list of Externals for the Node.js compilation.
|
|
10
9
|
* @param compileEdge Force compiling for the edge runtime when true
|
|
11
10
|
* @return The configuration and the build directory.
|
|
12
11
|
*/
|
|
13
|
-
export declare function compileOpenNextConfig(
|
|
12
|
+
export declare function compileOpenNextConfig(openNextConfigPath: string, { nodeExternals, compileEdge }?: {
|
|
14
13
|
nodeExternals?: string | undefined;
|
|
15
14
|
compileEdge?: boolean | undefined;
|
|
16
15
|
}): Promise<{
|
|
17
16
|
config: OpenNextConfig;
|
|
18
17
|
buildDir: string;
|
|
19
18
|
}>;
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Compiles the OpenNext configuration for Node.
|
|
21
|
+
*
|
|
22
|
+
* @param openNextConfigPath Path to the configuration file. Absolute or relative to cwd.
|
|
23
|
+
* @param outputDir Folder where to output the compiled config file (`open-next.config.mjs`).
|
|
24
|
+
* @param externals List of packages that should not be bundled.
|
|
25
|
+
* @return Path to the compiled config.
|
|
26
|
+
*/
|
|
27
|
+
export declare function compileOpenNextConfigNode(openNextConfigPath: string, outputDir: string, externals: string[]): string;
|
|
28
|
+
/**
|
|
29
|
+
* Compiles the OpenNext configuration for Edge.
|
|
30
|
+
*
|
|
31
|
+
* @param openNextConfigPath Path to the configuration file. Absolute or relative to cwd.
|
|
32
|
+
* @param outputDir Folder where to output the compiled config file (`open-next.config.edge.mjs`).
|
|
33
|
+
* @param externals List of packages that should not be bundled.
|
|
34
|
+
* @return Path to the compiled config.
|
|
35
|
+
*/
|
|
36
|
+
export declare function compileOpenNextConfigEdge(openNextConfigPath: string, outputDir: string, externals: string[]): string;
|
|
@@ -9,16 +9,14 @@ import { validateConfig } from "./validateConfig.js";
|
|
|
9
9
|
*
|
|
10
10
|
* The configuration is always compiled for Node.js and for the edge only if needed.
|
|
11
11
|
*
|
|
12
|
-
* @param
|
|
13
|
-
* @param openNextConfigPath Override the default configuration when provided. Relative to baseDir.
|
|
12
|
+
* @param openNextConfigPath Path to the configuration file. Absolute or relative to cwd.
|
|
14
13
|
* @param nodeExternals Coma separated list of Externals for the Node.js compilation.
|
|
15
14
|
* @param compileEdge Force compiling for the edge runtime when true
|
|
16
15
|
* @return The configuration and the build directory.
|
|
17
16
|
*/
|
|
18
|
-
export async function compileOpenNextConfig(
|
|
19
|
-
const sourcePath = path.join(baseDir, openNextConfigPath ?? "open-next.config.ts");
|
|
17
|
+
export async function compileOpenNextConfig(openNextConfigPath, { nodeExternals = "", compileEdge = false } = {}) {
|
|
20
18
|
const buildDir = fs.mkdtempSync(path.join(os.tmpdir(), "open-next-tmp"));
|
|
21
|
-
let configPath = compileOpenNextConfigNode(
|
|
19
|
+
let configPath = compileOpenNextConfigNode(openNextConfigPath, buildDir, nodeExternals.split(","));
|
|
22
20
|
// On Windows, we need to use file:// protocol to load the config file using import()
|
|
23
21
|
if (process.platform === "win32")
|
|
24
22
|
configPath = `file://${configPath}`;
|
|
@@ -33,7 +31,7 @@ export async function compileOpenNextConfig(baseDir, openNextConfigPath, { nodeE
|
|
|
33
31
|
const usesEdgeRuntime = (config.middleware?.external && config.middleware.runtime !== "node") ||
|
|
34
32
|
Object.values(config.functions || {}).some((fn) => fn.runtime === "edge");
|
|
35
33
|
if (usesEdgeRuntime || compileEdge) {
|
|
36
|
-
compileOpenNextConfigEdge(
|
|
34
|
+
compileOpenNextConfigEdge(openNextConfigPath, buildDir, config.edgeExternals ?? []);
|
|
37
35
|
}
|
|
38
36
|
else {
|
|
39
37
|
// Skip compiling for the edge runtime.
|
|
@@ -41,18 +39,26 @@ export async function compileOpenNextConfig(baseDir, openNextConfigPath, { nodeE
|
|
|
41
39
|
}
|
|
42
40
|
return { config, buildDir };
|
|
43
41
|
}
|
|
44
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Compiles the OpenNext configuration for Node.
|
|
44
|
+
*
|
|
45
|
+
* @param openNextConfigPath Path to the configuration file. Absolute or relative to cwd.
|
|
46
|
+
* @param outputDir Folder where to output the compiled config file (`open-next.config.mjs`).
|
|
47
|
+
* @param externals List of packages that should not be bundled.
|
|
48
|
+
* @return Path to the compiled config.
|
|
49
|
+
*/
|
|
50
|
+
export function compileOpenNextConfigNode(openNextConfigPath, outputDir, externals) {
|
|
45
51
|
const outputPath = path.join(outputDir, "open-next.config.mjs");
|
|
46
52
|
logger.debug("Compiling open-next.config.ts for Node.", outputPath);
|
|
47
53
|
//Check if open-next.config.ts exists
|
|
48
|
-
if (!fs.existsSync(
|
|
54
|
+
if (!fs.existsSync(openNextConfigPath)) {
|
|
49
55
|
//Create a simple open-next.config.mjs file
|
|
50
56
|
logger.debug("Cannot find open-next.config.ts. Using default config.");
|
|
51
57
|
fs.writeFileSync(outputPath, "export default { default: { } };");
|
|
52
58
|
}
|
|
53
59
|
else {
|
|
54
60
|
buildSync({
|
|
55
|
-
entryPoints: [
|
|
61
|
+
entryPoints: [openNextConfigPath],
|
|
56
62
|
outfile: outputPath,
|
|
57
63
|
bundle: true,
|
|
58
64
|
format: "esm",
|
|
@@ -71,11 +77,19 @@ export function compileOpenNextConfigNode(sourcePath, outputDir, externals) {
|
|
|
71
77
|
}
|
|
72
78
|
return outputPath;
|
|
73
79
|
}
|
|
74
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Compiles the OpenNext configuration for Edge.
|
|
82
|
+
*
|
|
83
|
+
* @param openNextConfigPath Path to the configuration file. Absolute or relative to cwd.
|
|
84
|
+
* @param outputDir Folder where to output the compiled config file (`open-next.config.edge.mjs`).
|
|
85
|
+
* @param externals List of packages that should not be bundled.
|
|
86
|
+
* @return Path to the compiled config.
|
|
87
|
+
*/
|
|
88
|
+
export function compileOpenNextConfigEdge(openNextConfigPath, outputDir, externals) {
|
|
75
89
|
const outputPath = path.join(outputDir, "open-next.config.edge.mjs");
|
|
76
90
|
logger.debug("Compiling open-next.config.ts for edge runtime.", outputPath);
|
|
77
91
|
buildSync({
|
|
78
|
-
entryPoints: [
|
|
92
|
+
entryPoints: [openNextConfigPath],
|
|
79
93
|
outfile: outputPath,
|
|
80
94
|
bundle: true,
|
|
81
95
|
format: "esm",
|
|
@@ -88,4 +102,5 @@ export function compileOpenNextConfigEdge(sourcePath, outputDir, externals) {
|
|
|
88
102
|
"process.env.NODE_ENV": '"production"',
|
|
89
103
|
},
|
|
90
104
|
});
|
|
105
|
+
return outputPath;
|
|
91
106
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { loadConfig } from "../adapters/config/util.js";
|
|
4
|
+
import { safeParseJsonFile } from "../utils/safe-json-parse.js";
|
|
4
5
|
import logger from "../logger.js";
|
|
5
6
|
import { isBinaryContentType } from "../utils/binary.js";
|
|
6
7
|
import * as buildHelper from "./helper.js";
|
|
@@ -106,15 +107,20 @@ export function createCacheAssets(options) {
|
|
|
106
107
|
// Generate cache file
|
|
107
108
|
Object.entries(cacheFilesPath).forEach(([cacheFilePath, files]) => {
|
|
108
109
|
const cacheFileMeta = files.meta
|
|
109
|
-
?
|
|
110
|
+
? safeParseJsonFile(fs.readFileSync(files.meta, "utf8"), cacheFilePath)
|
|
110
111
|
: undefined;
|
|
112
|
+
const cacheJson = files.json
|
|
113
|
+
? safeParseJsonFile(fs.readFileSync(files.json, "utf8"), cacheFilePath)
|
|
114
|
+
: undefined;
|
|
115
|
+
if ((files.meta && !cacheFileMeta) || (files.json && !cacheJson)) {
|
|
116
|
+
logger.warn(`Skipping invalid cache file: ${cacheFilePath}`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
111
119
|
const cacheFileContent = {
|
|
112
120
|
type: files.body ? "route" : files.json ? "page" : "app",
|
|
113
121
|
meta: cacheFileMeta,
|
|
114
122
|
html: files.html ? fs.readFileSync(files.html, "utf8") : undefined,
|
|
115
|
-
json:
|
|
116
|
-
? JSON.parse(fs.readFileSync(files.json, "utf8"))
|
|
117
|
-
: undefined,
|
|
123
|
+
json: cacheJson,
|
|
118
124
|
rsc: files.rsc ? fs.readFileSync(files.rsc, "utf8") : undefined,
|
|
119
125
|
body: files.body
|
|
120
126
|
? fs
|
|
@@ -138,7 +144,7 @@ export function createCacheAssets(options) {
|
|
|
138
144
|
fs.cpSync(fetchCachePath, fetchOutputPath, { recursive: true });
|
|
139
145
|
buildHelper.traverseFiles(fetchCachePath, () => true, ({ absolutePath, relativePath }) => {
|
|
140
146
|
const fileContent = fs.readFileSync(absolutePath, "utf8");
|
|
141
|
-
const fileData =
|
|
147
|
+
const fileData = safeParseJsonFile(fileContent, absolutePath);
|
|
142
148
|
fileData?.tags?.forEach((tag) => {
|
|
143
149
|
metaFiles.push({
|
|
144
150
|
tag: { S: path.posix.join(buildId, tag) },
|
|
@@ -156,8 +162,8 @@ export function createCacheAssets(options) {
|
|
|
156
162
|
sourceDirs.forEach((sourceDir) => {
|
|
157
163
|
buildHelper.traverseFiles(sourceDir, ({ absolutePath, relativePath }) => absolutePath.endsWith(".meta") && !isFileSkipped(relativePath), ({ absolutePath, relativePath }) => {
|
|
158
164
|
const fileContent = fs.readFileSync(absolutePath, "utf8");
|
|
159
|
-
const fileData =
|
|
160
|
-
if (fileData
|
|
165
|
+
const fileData = safeParseJsonFile(fileContent, absolutePath);
|
|
166
|
+
if (fileData?.headers?.["x-next-cache-tags"]) {
|
|
161
167
|
fileData.headers["x-next-cache-tags"]
|
|
162
168
|
.split(",")
|
|
163
169
|
.forEach((tag) => {
|
|
@@ -76,7 +76,8 @@ export async function createImageOptimizationBundle(options) {
|
|
|
76
76
|
const sharpVersion = process.env.SHARP_VERSION ?? "0.32.6";
|
|
77
77
|
installDependencies(outputPath, config.imageOptimization?.install ?? {
|
|
78
78
|
packages: [`sharp@${sharpVersion}`],
|
|
79
|
-
arch
|
|
79
|
+
// By not specifying an arch, `npm install` will choose one for us (i.e. our system one)
|
|
80
|
+
arch: config.imageOptimization?.loader === "fs-dev" ? undefined : "arm64",
|
|
80
81
|
nodeVersion: "18",
|
|
81
82
|
libc: "glibc",
|
|
82
83
|
});
|
|
@@ -15,7 +15,8 @@ import { copyOpenNextConfig, esbuildAsync } from "../helper.js";
|
|
|
15
15
|
export async function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, name, additionalPlugins: additionalPluginsFn, }) {
|
|
16
16
|
const isInCloudflare = await isEdgeRuntime(overrides);
|
|
17
17
|
function override(target) {
|
|
18
|
-
return typeof overrides?.[target] === "string"
|
|
18
|
+
return typeof overrides?.[target] === "string" ||
|
|
19
|
+
typeof overrides?.[target] === "function"
|
|
19
20
|
? overrides[target]
|
|
20
21
|
: undefined;
|
|
21
22
|
}
|
package/dist/build.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import url from "node:url";
|
|
2
3
|
import { buildNextjsApp, setStandaloneBuildMode, } from "./build/buildNextApp.js";
|
|
3
4
|
import { compileCache } from "./build/compileCache.js";
|
|
@@ -17,7 +18,7 @@ export async function build(openNextConfigPath, nodeExternals) {
|
|
|
17
18
|
showWarningOnWindows();
|
|
18
19
|
const baseDir = process.cwd();
|
|
19
20
|
const openNextDistDir = url.fileURLToPath(new URL(".", import.meta.url));
|
|
20
|
-
const { config, buildDir } = await compileOpenNextConfig(baseDir, openNextConfigPath, { nodeExternals });
|
|
21
|
+
const { config, buildDir } = await compileOpenNextConfig(path.join(baseDir, openNextConfigPath ?? "open-next.config.ts"), { nodeExternals });
|
|
21
22
|
// Initialize options
|
|
22
23
|
const options = buildHelper.normalizeOptions(config, openNextDistDir, buildDir);
|
|
23
24
|
logger.setLevel(options.debug ? "debug" : "info");
|
|
@@ -175,9 +175,12 @@ export async function cacheInterceptor(event) {
|
|
|
175
175
|
return event;
|
|
176
176
|
}
|
|
177
177
|
// We need to check the tag cache now
|
|
178
|
-
if (cachedData.value?.type === "app"
|
|
178
|
+
if (cachedData.value?.type === "app" ||
|
|
179
|
+
cachedData.value?.type === "route") {
|
|
179
180
|
const tags = getTagsFromValue(cachedData.value);
|
|
180
|
-
const _hasBeenRevalidated =
|
|
181
|
+
const _hasBeenRevalidated = cachedData.shouldBypassTagCache
|
|
182
|
+
? false
|
|
183
|
+
: await hasBeenRevalidated(localizedPath, tags, cachedData);
|
|
181
184
|
if (_hasBeenRevalidated) {
|
|
182
185
|
return event;
|
|
183
186
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
name: string;
|
|
3
|
+
mode: "nextMode";
|
|
4
|
+
getLastRevalidated: (tags: string[]) => Promise<number>;
|
|
5
|
+
hasBeenRevalidated: (tags: string[], lastModified?: number) => Promise<boolean>;
|
|
6
|
+
writeTags: (tags: string[]) => Promise<void>;
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { debug } from "../../adapters/logger";
|
|
2
|
+
const tagsMap = new Map();
|
|
3
|
+
export default {
|
|
4
|
+
name: "fs-dev-nextMode",
|
|
5
|
+
mode: "nextMode",
|
|
6
|
+
getLastRevalidated: async (tags) => {
|
|
7
|
+
if (globalThis.openNextConfig.dangerous?.disableTagCache) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
let lastRevalidated = 0;
|
|
11
|
+
tags.forEach((tag) => {
|
|
12
|
+
const tagTime = tagsMap.get(tag);
|
|
13
|
+
if (tagTime && tagTime > lastRevalidated) {
|
|
14
|
+
lastRevalidated = tagTime;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
debug("getLastRevalidated result:", lastRevalidated);
|
|
18
|
+
return lastRevalidated;
|
|
19
|
+
},
|
|
20
|
+
hasBeenRevalidated: async (tags, lastModified) => {
|
|
21
|
+
if (globalThis.openNextConfig.dangerous?.disableTagCache) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const hasRevalidatedTag = tags.some((tag) => {
|
|
25
|
+
const tagRevalidatedAt = tagsMap.get(tag);
|
|
26
|
+
return tagRevalidatedAt ? tagRevalidatedAt > (lastModified ?? 0) : false;
|
|
27
|
+
});
|
|
28
|
+
debug("hasBeenRevalidated result:", hasRevalidatedTag);
|
|
29
|
+
return hasRevalidatedTag;
|
|
30
|
+
},
|
|
31
|
+
writeTags: async (tags) => {
|
|
32
|
+
if (globalThis.openNextConfig.dangerous?.disableTagCache ||
|
|
33
|
+
tags.length === 0) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
debug("writeTags", { tags: tags });
|
|
37
|
+
tags.forEach((tag) => {
|
|
38
|
+
tagsMap.set(tag, Date.now());
|
|
39
|
+
});
|
|
40
|
+
debug("writeTags completed, written", tags.length, "tags");
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -4,31 +4,35 @@ import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
|
4
4
|
const tagFile = path.join(getMonorepoRelativePath(), "dynamodb-provider/dynamodb-cache.json");
|
|
5
5
|
const tagContent = fs.readFileSync(tagFile, "utf-8");
|
|
6
6
|
let tags = JSON.parse(tagContent);
|
|
7
|
+
const { NEXT_BUILD_ID } = process.env;
|
|
8
|
+
function buildKey(key) {
|
|
9
|
+
return path.posix.join(NEXT_BUILD_ID ?? "", key);
|
|
10
|
+
}
|
|
7
11
|
const tagCache = {
|
|
8
12
|
name: "fs-dev",
|
|
9
13
|
mode: "original",
|
|
10
14
|
getByPath: async (path) => {
|
|
11
15
|
return tags
|
|
12
|
-
.filter((tagPathMapping) => tagPathMapping.path.S === path)
|
|
13
|
-
.map((tag) => tag.tag.S);
|
|
16
|
+
.filter((tagPathMapping) => tagPathMapping.path.S === buildKey(path))
|
|
17
|
+
.map((tag) => tag.tag.S.replace(`${NEXT_BUILD_ID}/`, ""));
|
|
14
18
|
},
|
|
15
19
|
getByTag: async (tag) => {
|
|
16
20
|
return tags
|
|
17
|
-
.filter((tagPathMapping) => tagPathMapping.tag.S === tag)
|
|
18
|
-
.map((
|
|
21
|
+
.filter((tagPathMapping) => tagPathMapping.tag.S === buildKey(tag))
|
|
22
|
+
.map((tagEntry) => tagEntry.path.S.replace(`${NEXT_BUILD_ID}/`, ""));
|
|
19
23
|
},
|
|
20
24
|
getLastModified: async (path, lastModified) => {
|
|
21
|
-
const revalidatedTags = tags.filter((tagPathMapping) => tagPathMapping.path.S === path &&
|
|
25
|
+
const revalidatedTags = tags.filter((tagPathMapping) => tagPathMapping.path.S === buildKey(path) &&
|
|
22
26
|
Number.parseInt(tagPathMapping.revalidatedAt.N) > (lastModified ?? 0));
|
|
23
27
|
return revalidatedTags.length > 0 ? -1 : (lastModified ?? Date.now());
|
|
24
28
|
},
|
|
25
29
|
writeTags: async (newTags) => {
|
|
26
|
-
const newTagsSet = new Set(newTags.map(({ tag, path }) => `${tag}-${path}`));
|
|
30
|
+
const newTagsSet = new Set(newTags.map(({ tag, path }) => `${buildKey(tag)}-${buildKey(path)}`));
|
|
27
31
|
const unchangedTags = tags.filter(({ tag, path }) => !newTagsSet.has(`${tag.S}-${path.S}`));
|
|
28
|
-
tags = unchangedTags.concat(newTags.map((
|
|
29
|
-
tag: { S:
|
|
30
|
-
path: { S:
|
|
31
|
-
revalidatedAt: { N:
|
|
32
|
+
tags = unchangedTags.concat(newTags.map((item) => ({
|
|
33
|
+
tag: { S: buildKey(item.tag) },
|
|
34
|
+
path: { S: buildKey(item.path) },
|
|
35
|
+
revalidatedAt: { N: `${item.revalidatedAt ?? Date.now()}` },
|
|
32
36
|
})));
|
|
33
37
|
},
|
|
34
38
|
};
|
|
@@ -4,6 +4,9 @@ import { NextConfig } from "../../adapters/config/index";
|
|
|
4
4
|
import { getMonorepoRelativePath } from "../../utils/normalize-path";
|
|
5
5
|
const wrapper = async (handler, converter) => {
|
|
6
6
|
const app = express();
|
|
7
|
+
// We disable this cause we wanna use it ourself
|
|
8
|
+
// https://stackoverflow.com/a/13055495/16587222
|
|
9
|
+
app.disable("x-powered-by");
|
|
7
10
|
// To serve static assets
|
|
8
11
|
const basePath = NextConfig.basePath ?? "";
|
|
9
12
|
app.use(basePath, express.static(path.join(getMonorepoRelativePath(), "assets")));
|
|
@@ -100,7 +100,7 @@ export interface MiddlewareResult extends RoutingResult, BaseEventOrResult<"midd
|
|
|
100
100
|
}
|
|
101
101
|
export type IncludedQueue = "sqs" | "sqs-lite" | "direct" | "dummy";
|
|
102
102
|
export type IncludedIncrementalCache = "s3" | "s3-lite" | "multi-tier-ddb-s3" | "fs-dev" | "dummy";
|
|
103
|
-
export type IncludedTagCache = "dynamodb" | "dynamodb-lite" | "dynamodb-nextMode" | "fs-dev" | "dummy";
|
|
103
|
+
export type IncludedTagCache = "dynamodb" | "dynamodb-lite" | "dynamodb-nextMode" | "fs-dev" | "fs-dev-nextMode" | "dummy";
|
|
104
104
|
export type IncludedImageLoader = "s3" | "s3-lite" | "host" | "fs-dev" | "dummy";
|
|
105
105
|
export type IncludedOriginResolver = "pattern-env" | "dummy";
|
|
106
106
|
export type IncludedWarmer = "aws-lambda" | "dummy";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function safeParseJsonFile<T = any>(input: string, filePath: string, fallback?: T): T | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import logger from "../logger.js";
|
|
2
|
+
export function safeParseJsonFile(input, filePath, fallback) {
|
|
3
|
+
try {
|
|
4
|
+
return JSON.parse(input);
|
|
5
|
+
}
|
|
6
|
+
catch (err) {
|
|
7
|
+
logger.warn(`Failed to parse JSON file "${filePath}". Error: ${err.message}`);
|
|
8
|
+
return fallback;
|
|
9
|
+
}
|
|
10
|
+
}
|