Skip to content

Commit e00ff91

Browse files
committed
implemented some dev override
1 parent ce09e57 commit e00ff91

File tree

10 files changed

+547
-19
lines changed

10 files changed

+547
-19
lines changed

packages/open-next/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@
4545
"aws4fetch": "^1.0.18",
4646
"chalk": "^5.3.0",
4747
"esbuild": "0.19.2",
48+
"express": "5.0.1",
4849
"path-to-regexp": "^6.3.0",
4950
"promise.series": "^0.2.0",
5051
"urlpattern-polyfill": "^10.0.0"
5152
},
5253
"devDependencies": {
5354
"@types/aws-lambda": "^8.10.109",
55+
"@types/express": "5.0.0",
5456
"@types/node": "catalog:",
5557
"tsc-alias": "^1.8.8",
5658
"typescript": "catalog:"

packages/open-next/src/build/validateConfig.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const compatibilityMatrix: Record<IncludedWrapper, IncludedConverter[]> = {
2020
"cloudflare-edge": ["edge"],
2121
"cloudflare-node": ["edge"],
2222
node: ["node"],
23-
dummy: [],
23+
"express-dev": ["node"],
24+
dummy: ["dummy"],
2425
};
2526

2627
function validateFunctionOptions(fnOptions: FunctionOptions) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { ImageLoader } from "types/overrides";
2+
import fs from "node:fs/promises";
3+
import { Readable } from "node:stream";
4+
5+
export default {
6+
name: "fs-dev",
7+
load: async (url: string) => {
8+
const basePath = "../../assets";
9+
const fileData = await fs.readFile(`${basePath}/${url}`);
10+
const contentType = url.endsWith(".png") ? "image/png" : "image/jpeg";
11+
return {
12+
body: Readable.from(fileData),
13+
contentType,
14+
cacheControl: "public, max-age=31536000, immutable",
15+
};
16+
},
17+
} satisfies ImageLoader;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { IncrementalCache } from "types/overrides.js";
2+
3+
import fs from "node:fs/promises";
4+
import path from "node:path";
5+
6+
const buildId = process.env.NEXT_BUILD_ID;
7+
const basePath = path.resolve(process.cwd(), `../../cache/${buildId}`);
8+
9+
const getCacheKey = (key: string) => {
10+
return path.join(basePath, `${key}.cache`);
11+
};
12+
13+
const cache: IncrementalCache = {
14+
name: "fs-dev",
15+
get: async (key: string) => {
16+
const fileData = await fs.readFile(getCacheKey(key), "utf-8");
17+
const data = JSON.parse(fileData);
18+
const { mtime } = await fs.stat(getCacheKey(key));
19+
return {
20+
value: data,
21+
lastModified: mtime.getTime(),
22+
};
23+
},
24+
set: async (key, value, isFetch) => {
25+
const data = JSON.stringify(value);
26+
await fs.writeFile(getCacheKey(key), data);
27+
},
28+
delete: async (key) => {
29+
await fs.rm(getCacheKey(key));
30+
},
31+
};
32+
33+
export default cache;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { Queue } from "types/overrides.js";
2+
3+
const queue: Queue = {
4+
name: "dev-queue",
5+
send: async (message) => {
6+
const prerenderManifest = (await import("../../adapters/config/index.js"))
7+
.PrerenderManifest as any;
8+
const { host, url } = message.MessageBody;
9+
const protocol = host.includes("localhost") ? "http" : "https";
10+
const revalidateId: string = prerenderManifest.preview.previewModeId;
11+
await globalThis.internalFetch(`${protocol}://${host}${url}`, {
12+
method: "HEAD",
13+
headers: {
14+
"x-prerender-revalidate": revalidateId,
15+
"x-isr": "1",
16+
},
17+
});
18+
},
19+
};
20+
21+
export default queue;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import type { TagCache } from "types/overrides";
2+
3+
import fs from "node:fs";
4+
5+
const tagFile = "../../dynamodb-provider/dynamodb-cache.json";
6+
7+
const tagContent = fs.readFileSync(tagFile, "utf-8");
8+
9+
let tags = JSON.parse(tagContent) as {
10+
tag: { S: string };
11+
path: { S: string };
12+
revalidatedAt: { N: string };
13+
}[];
14+
15+
const tagCache: TagCache = {
16+
name: "fs-dev",
17+
getByPath: async (path: string) => {
18+
return tags
19+
.filter((tagPathMapping) => tagPathMapping.path.S === path)
20+
.map((tag) => tag.tag.S);
21+
},
22+
getByTag: async (tag: string) => {
23+
return tags
24+
.filter((tagPathMapping) => tagPathMapping.tag.S === tag)
25+
.map((tag) => tag.path.S);
26+
},
27+
getLastModified: async (path: string, lastModified?: number) => {
28+
const revalidatedTags = tags.filter(
29+
(tagPathMapping) =>
30+
tagPathMapping.path.S === path &&
31+
Number.parseInt(tagPathMapping.revalidatedAt.N) > (lastModified ?? 0),
32+
);
33+
return revalidatedTags.length > 0 ? -1 : (lastModified ?? Date.now());
34+
},
35+
writeTags: async (newTags) => {
36+
const unchangedTags = tags.filter((tagPathMapping) =>
37+
newTags.some(
38+
(tag) =>
39+
tag.tag === tagPathMapping.tag.S &&
40+
tag.path === tagPathMapping.path.S,
41+
),
42+
);
43+
tags = unchangedTags.concat(
44+
newTags.map((tag) => ({
45+
tag: { S: tag.tag },
46+
path: { S: tag.path },
47+
revalidatedAt: { N: String(tag.revalidatedAt) },
48+
})),
49+
);
50+
},
51+
};
52+
53+
export default tagCache;
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
import type { InternalEvent, StreamCreator } from "types/open-next";
12
import type { Wrapper, WrapperHandler } from "types/overrides";
23

3-
const dummyWrapper: WrapperHandler = async () => async () => undefined;
4+
const dummyWrapper: WrapperHandler = async (handler, converter) => {
5+
return async (event: InternalEvent, responseStream?: StreamCreator) => {
6+
return await handler(event, responseStream);
7+
};
8+
};
49

510
export default {
611
name: "dummy",
712
wrapper: dummyWrapper,
8-
supportStreaming: false,
13+
supportStreaming: true,
914
} satisfies Wrapper;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// dev/wrapper.ts
2+
// You'll need to install express
3+
import express from "express";
4+
5+
import type { StreamCreator } from "types/open-next.js";
6+
import type { WrapperHandler } from "types/overrides.js";
7+
8+
const wrapper: WrapperHandler = async (handler, converter) => {
9+
const app = express();
10+
// To serve static assets
11+
app.use(express.static("../../assets"));
12+
13+
const imageHandlerPath = "../../image-optimization-function/index.mjs";
14+
const imageHandler = await import(imageHandlerPath).then((m) => m.handler);
15+
16+
app.all("/_next/image", async (req, res) => {
17+
const internalEvent = await converter.convertFrom(req);
18+
const _res: StreamCreator = {
19+
writeHeaders: (prelude) => {
20+
res.writeHead(prelude.statusCode, prelude.headers);
21+
return res;
22+
},
23+
onFinish: () => {},
24+
};
25+
await imageHandler(internalEvent, _res);
26+
});
27+
28+
app.all("*paths", async (req, res) => {
29+
const internalEvent = await converter.convertFrom(req);
30+
const _res: StreamCreator = {
31+
writeHeaders: (prelude) => {
32+
res.writeHead(prelude.statusCode, prelude.headers);
33+
return res;
34+
},
35+
onFinish: () => {},
36+
};
37+
await handler(internalEvent, _res);
38+
});
39+
40+
const server = app.listen(
41+
Number.parseInt(process.env.PORT ?? "3000", 10),
42+
() => {
43+
console.log(`Server running on port ${process.env.PORT ?? 3000}`);
44+
},
45+
);
46+
47+
app.on("error", (err) => {
48+
console.error("error", err);
49+
});
50+
51+
return () => {
52+
server.close();
53+
};
54+
};
55+
56+
export default {
57+
wrapper,
58+
name: "expresss-dev",
59+
supportStreaming: true,
60+
};

packages/open-next/src/types/open-next.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export type IncludedWrapper =
9696
| "cloudflare"
9797
| "cloudflare-edge"
9898
| "cloudflare-node"
99+
| "express-dev"
99100
| "dummy";
100101

101102
export type IncludedConverter =
@@ -133,13 +134,17 @@ export interface MiddlewareResult
133134
extends RoutingResult,
134135
BaseEventOrResult<"middleware"> {}
135136

136-
export type IncludedQueue = "sqs" | "sqs-lite" | "dummy";
137+
export type IncludedQueue = "sqs" | "sqs-lite" | "direct" | "dummy";
137138

138-
export type IncludedIncrementalCache = "s3" | "s3-lite" | "dummy";
139+
export type IncludedIncrementalCache = "s3" | "s3-lite" | "fs-dev" | "dummy";
139140

140-
export type IncludedTagCache = "dynamodb" | "dynamodb-lite" | "dummy";
141+
export type IncludedTagCache =
142+
| "dynamodb"
143+
| "dynamodb-lite"
144+
| "fs-dev"
145+
| "dummy";
141146

142-
export type IncludedImageLoader = "s3" | "host" | "dummy";
147+
export type IncludedImageLoader = "s3" | "host" | "fs-dev" | "dummy";
143148

144149
export type IncludedOriginResolver = "pattern-env" | "dummy";
145150

0 commit comments

Comments
 (0)