@opennextjs/cloudflare 0.0.0-e62af72 → 0.0.3

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.
@@ -17,7 +17,7 @@ function existsSync(path: string) {
17
17
  return FILES.has(path);
18
18
  }
19
19
 
20
- async function readFile(path: string, options: unknown): Promise<any> {
20
+ async function readFile(path: string, options: unknown): Promise<unknown> {
21
21
  console.log(
22
22
  "readFile",
23
23
  { path, options }
@@ -1,17 +1,19 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- import Stream from "node:stream";
3
- import type { NextConfig } from "next";
1
+ import type { ExportedHandler, Fetcher } from "@cloudflare/workers-types";
4
2
  import { NodeNextRequest, NodeNextResponse } from "next/dist/server/base-http/node";
5
- import { MockedResponse } from "next/dist/server/lib/mock-request";
6
- import NextNodeServer, { NodeRequestHandler } from "next/dist/server/next-server";
3
+ import { AsyncLocalStorage } from "node:async_hooks";
4
+ import type { CloudflareContext } from "../../api";
7
5
  import type { IncomingMessage } from "node:http";
8
- import { type CloudflareContext } from "../../api";
6
+ import { MockedResponse } from "next/dist/server/lib/mock-request";
7
+ import type { NextConfig } from "next";
8
+ import type { NodeRequestHandler } from "next/dist/server/next-server";
9
+ import Stream from "node:stream";
9
10
 
10
11
  const NON_BODY_RESPONSES = new Set([101, 204, 205, 304]);
11
12
 
12
13
  const cloudflareContextALS = new AsyncLocalStorage<CloudflareContext>();
13
14
 
14
15
  // Note: this symbol needs to be kept in sync with the one defined in `src/api/get-cloudflare-context.ts`
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
17
  (globalThis as any)[Symbol.for("__cloudflare-context__")] = new Proxy(
16
18
  {},
17
19
  {
@@ -29,12 +31,18 @@ const nextConfig: NextConfig = JSON.parse(process.env.__NEXT_PRIVATE_STANDALONE_
29
31
  let requestHandler: NodeRequestHandler | null = null;
30
32
 
31
33
  export default {
32
- async fetch(request: Request & { cf: IncomingRequestCfProperties }, env: any, ctx: any) {
34
+ async fetch(request, env, ctx) {
33
35
  return cloudflareContextALS.run({ env, ctx, cf: request.cf }, async () => {
34
36
  if (requestHandler == null) {
35
37
  globalThis.process.env = { ...globalThis.process.env, ...env };
38
+ // Note: "next/dist/server/next-server" is a cjs module so we have to `require` it not to confuse esbuild
39
+ // (since esbuild can run in projects with different module resolutions)
40
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
41
+ const NextNodeServer = require("next/dist/server/next-server")
42
+ .default as typeof import("next/dist/server/next-server").default;
43
+
36
44
  requestHandler = new NextNodeServer({
37
- conf: { ...nextConfig, env },
45
+ conf: nextConfig,
38
46
  customServer: false,
39
47
  dev: false,
40
48
  dir: "",
@@ -45,29 +53,29 @@ export default {
45
53
  const url = new URL(request.url);
46
54
 
47
55
  if (url.pathname === "/_next/image") {
48
- let imageUrl =
56
+ const imageUrl =
49
57
  url.searchParams.get("url") ?? "https://developers.cloudflare.com/_astro/logo.BU9hiExz.svg";
50
58
  if (imageUrl.startsWith("/")) {
51
59
  return env.ASSETS.fetch(new URL(imageUrl, request.url));
52
60
  }
53
- return fetch(imageUrl, { cf: { cacheEverything: true } } as any);
61
+ return fetch(imageUrl, { cf: { cacheEverything: true } });
54
62
  }
55
63
 
56
64
  const { req, res, webResponse } = getWrappedStreams(request, ctx);
57
65
 
58
- ctx.waitUntil(requestHandler(new NodeNextRequest(req), new NodeNextResponse(res)));
66
+ ctx.waitUntil(Promise.resolve(requestHandler(new NodeNextRequest(req), new NodeNextResponse(res))));
59
67
 
60
68
  return await webResponse();
61
69
  });
62
70
  },
63
- };
71
+ } as ExportedHandler<{ ASSETS: Fetcher }>;
64
72
 
65
- function getWrappedStreams(request: Request, ctx: any) {
73
+ function getWrappedStreams(request: Request, ctx: ExecutionContext) {
66
74
  const url = new URL(request.url);
67
75
 
68
- const req = (
69
- request.body ? Stream.Readable.fromWeb(request.body as any) : Stream.Readable.from([])
70
- ) as IncomingMessage;
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ const reqBody = request.body && Stream.Readable.fromWeb(request.body as any);
78
+ const req = (reqBody ?? Stream.Readable.from([])) as IncomingMessage;
71
79
  req.httpVersion = "1.0";
72
80
  req.httpVersionMajor = 1;
73
81
  req.httpVersionMinor = 0;
@@ -94,7 +102,7 @@ function getWrappedStreams(request: Request, ctx: any) {
94
102
 
95
103
  const res = new MockedResponse({
96
104
  resWriter: (chunk) => {
97
- resBodyWriter.write(typeof chunk === "string" ? Buffer.from(chunk) : chunk).catch((err: any) => {
105
+ resBodyWriter.write(typeof chunk === "string" ? Buffer.from(chunk) : chunk).catch((err) => {
98
106
  if (
99
107
  err.message.includes("WritableStream has been closed") ||
100
108
  err.message.includes("Network connection lost")
@@ -110,6 +118,7 @@ function getWrappedStreams(request: Request, ctx: any) {
110
118
  });
111
119
 
112
120
  // It's implemented as a no-op, but really it should mark the headers as done
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
122
  res.flushHeaders = () => (res as any).headPromiseResolve();
114
123
 
115
124
  // Only allow statusCode to be modified if not sent
@@ -127,6 +136,7 @@ function getWrappedStreams(request: Request, ctx: any) {
127
136
  });
128
137
 
129
138
  // Make sure the writer is eventually closed
139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
140
  ctx.waitUntil((res as any).hasStreamed.finally(() => resBodyWriter.close().catch(() => {})));
131
141
 
132
142
  return {
@@ -138,6 +148,7 @@ function getWrappedStreams(request: Request, ctx: any) {
138
148
  res.setHeader("content-encoding", "identity");
139
149
  return new Response(NON_BODY_RESPONSES.has(res.statusCode) ? null : readable, {
140
150
  status: res.statusCode,
151
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
141
152
  headers: (res as any).headers,
142
153
  });
143
154
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@opennextjs/cloudflare",
3
3
  "description": "Cloudflare builder for next apps",
4
- "version": "0.0.0-e62af72",
4
+ "version": "0.0.3",
5
5
  "bin": "dist/cli/index.mjs",
6
6
  "main": "./dist/api/index.mjs",
7
7
  "types": "./dist/api/index.d.mts",
@@ -31,24 +31,34 @@
31
31
  },
32
32
  "homepage": "https://github.com/opennextjs/opennextjs-cloudflare",
33
33
  "devDependencies": {
34
- "@cloudflare/workers-types": "^4.20240919.0",
34
+ "@cloudflare/workers-types": "^4.20240925.0",
35
+ "@eslint/js": "^9.11.1",
36
+ "@tsconfig/strictest": "^2.0.5",
35
37
  "@types/node": "^22.2.0",
36
38
  "esbuild": "^0.23.0",
39
+ "eslint": "^9.11.1",
40
+ "eslint-plugin-unicorn": "^55.0.0",
37
41
  "glob": "^11.0.0",
42
+ "globals": "^15.9.0",
38
43
  "next": "14.2.11",
44
+ "package-manager-detector": "^0.2.0",
39
45
  "tsup": "^8.2.4",
40
46
  "typescript": "^5.5.4",
47
+ "typescript-eslint": "^8.7.0",
41
48
  "vitest": "^2.1.1"
42
49
  },
43
50
  "dependencies": {
44
51
  "ts-morph": "^23.0.0"
45
52
  },
46
53
  "peerDependencies": {
47
- "wrangler": "^3.78.6"
54
+ "wrangler": "^3.78.10"
48
55
  },
49
56
  "scripts": {
50
57
  "build": "tsup",
51
58
  "build:watch": "tsup --watch src",
59
+ "lint:check": "eslint",
60
+ "lint:fix": "eslint --fix",
61
+ "ts:check": "tsc --noEmit",
52
62
  "test": "vitest --run",
53
63
  "test:watch": "vitest"
54
64
  }
@@ -1,48 +0,0 @@
1
- import "./chunk-UJCSKKID.mjs";
2
-
3
- // src/cli/cache-handler.ts
4
- var CfWorkersKvCacheHandler = class _CfWorkersKvCacheHandler {
5
- constructor(ctx) {
6
- this.ctx = ctx;
7
- }
8
- static maybeKVNamespace = void 0;
9
- async get(key) {
10
- if (_CfWorkersKvCacheHandler.maybeKVNamespace === void 0) {
11
- return null;
12
- }
13
- console.log(`[Cf] Getting cache[${key}]`);
14
- try {
15
- return await _CfWorkersKvCacheHandler.maybeKVNamespace.get(key, "json") ?? null;
16
- } catch (e) {
17
- console.error(`Failed to get value for key = ${key}: ${e}`);
18
- return null;
19
- }
20
- }
21
- async set(key, entry, ctx) {
22
- if (_CfWorkersKvCacheHandler.maybeKVNamespace === void 0) {
23
- return;
24
- }
25
- console.log(`[Cf] Setting cache[${key}]`);
26
- try {
27
- const data = {
28
- lastModified: Date.now(),
29
- value: entry
30
- };
31
- await _CfWorkersKvCacheHandler.maybeKVNamespace.put(key, JSON.stringify(data));
32
- } catch (e) {
33
- console.error(`Failed to set value for key = ${key}: ${e}`);
34
- }
35
- }
36
- async revalidateTag(tags) {
37
- if (_CfWorkersKvCacheHandler.maybeKVNamespace === void 0) {
38
- return;
39
- }
40
- tags = [tags].flat();
41
- console.log(`[Cf] revalidateTag ${JSON.stringify(tags)}}`);
42
- }
43
- resetRequestCache() {
44
- }
45
- };
46
- export {
47
- CfWorkersKvCacheHandler as default
48
- };
@@ -1,30 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
8
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
- // If the importer is in node compatibility mode or this is not an ESM
20
- // file that has been converted to a CommonJS file using a Babel-
21
- // compatible transform (i.e. "__esModule" has not been set), then set
22
- // "default" to the CommonJS "module.exports" for node compatibility.
23
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
- mod
25
- ));
26
-
27
- export {
28
- __commonJS,
29
- __toESM
30
- };