@opennextjs/cloudflare 0.3.9 → 0.3.10

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.
@@ -2,7 +2,10 @@ import fs from "node:fs";
2
2
  import { readFile, writeFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { Lang, parse } from "@ast-grep/napi";
6
+ import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
5
7
  import { build } from "esbuild";
8
+ import { patchOptionalDependencies } from "./patches/ast/optional-deps.js";
6
9
  import * as patches from "./patches/index.js";
7
10
  import { normalizePath, patchCodeWithValidations } from "./utils/index.js";
8
11
  /** The dist directory of the Cloudflare adapter package */
@@ -31,7 +34,7 @@ export async function bundleServer(config, openNextOptions) {
31
34
  target: "esnext",
32
35
  minify: false,
33
36
  plugins: [createFixRequiresESBuildPlugin(config)],
34
- external: ["./middleware/handler.mjs"],
37
+ external: ["./middleware/handler.mjs", "caniuse-lite"],
35
38
  alias: {
36
39
  // Note: we apply an empty shim to next/dist/compiled/ws because it generates two `eval`s:
37
40
  // eval("require")("bufferutil");
@@ -149,14 +152,16 @@ async function updateWorkerBundledCode(workerOutputFile, config, openNextOptions
149
152
  (code) => code.replace('require.resolve("./cache.cjs")', '"unused"'),
150
153
  ],
151
154
  ]);
152
- await writeFile(workerOutputFile, patchedCode);
155
+ const bundle = parse(Lang.TypeScript, patchedCode).root();
156
+ const edits = patchOptionalDependencies(bundle);
157
+ await writeFile(workerOutputFile, bundle.commitEdits(edits));
153
158
  }
154
159
  function createFixRequiresESBuildPlugin(config) {
155
160
  return {
156
161
  name: "replaceRelative",
157
162
  setup(build) {
158
163
  // Note: we (empty) shim require-hook modules as they generate problematic code that uses requires
159
- build.onResolve({ filter: /^\.(\/|\\)require-hook$/ }, () => ({
164
+ build.onResolve({ filter: getCrossPlatformPathRegex(String.raw `^\./require-hook$`, { escape: false }) }, () => ({
160
165
  path: path.join(config.paths.internal.templates, "shims", "empty.js"),
161
166
  }));
162
167
  },
@@ -13,6 +13,7 @@ import { minifyAll } from "@opennextjs/aws/minimize-js.js";
13
13
  import { openNextEdgePlugins } from "@opennextjs/aws/plugins/edge.js";
14
14
  import { openNextReplacementPlugin } from "@opennextjs/aws/plugins/replacement.js";
15
15
  import { openNextResolvePlugin } from "@opennextjs/aws/plugins/resolve.js";
16
+ import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js";
16
17
  import { normalizePath } from "../utils/index.js";
17
18
  export async function createServerBundle(options) {
18
19
  const { config } = options;
@@ -117,7 +118,7 @@ async function generateBundle(name, options, fnOptions) {
117
118
  const plugins = [
118
119
  openNextReplacementPlugin({
119
120
  name: `requestHandlerOverride ${name}`,
120
- target: /core(\/|\\)requestHandler\.js/g,
121
+ target: getCrossPlatformPathRegex("core/requestHandler.js"),
121
122
  deletes: [
122
123
  ...(disableNextPrebundledReact ? ["applyNextjsPrebundledReact"] : []),
123
124
  ...(disableRouting ? ["withRouting"] : []),
@@ -125,7 +126,7 @@ async function generateBundle(name, options, fnOptions) {
125
126
  }),
126
127
  openNextReplacementPlugin({
127
128
  name: `utilOverride ${name}`,
128
- target: /core(\/|\\)util\.js/g,
129
+ target: getCrossPlatformPathRegex("core/util.js"),
129
130
  deletes: [
130
131
  ...(disableNextPrebundledReact ? ["requireHooks"] : []),
131
132
  ...(isBefore13413 ? ["trustHostHeader"] : ["requestHandlerHost"]),
@@ -0,0 +1,10 @@
1
+ import { type SgNode } from "@ast-grep/napi";
2
+ /**
3
+ * Handle optional dependencies.
4
+ *
5
+ * A top level `require(optionalDep)` would throw when the dep is not installed.
6
+ *
7
+ * So we wrap `require(optionalDep)` in a try/catch (if not already present).
8
+ */
9
+ export declare const optionalDepRule = "\nrule:\n pattern: $$$LHS = require($$$REQ)\n has:\n pattern: $MOD\n kind: string_fragment\n stopBy: end\n regex: ^caniuse-lite(/|$)\n not:\n inside:\n kind: try_statement\n stopBy: end\n\nfix: |-\n try {\n $$$LHS = require($$$REQ);\n } catch {\n throw new Error('The optional dependency \"$MOD\" is not installed');\n }\n";
10
+ export declare function patchOptionalDependencies(root: SgNode): import("@ast-grep/napi").Edit[];
@@ -0,0 +1,31 @@
1
+ import { getRuleEdits } from "./util.js";
2
+ /**
3
+ * Handle optional dependencies.
4
+ *
5
+ * A top level `require(optionalDep)` would throw when the dep is not installed.
6
+ *
7
+ * So we wrap `require(optionalDep)` in a try/catch (if not already present).
8
+ */
9
+ export const optionalDepRule = `
10
+ rule:
11
+ pattern: $$$LHS = require($$$REQ)
12
+ has:
13
+ pattern: $MOD
14
+ kind: string_fragment
15
+ stopBy: end
16
+ regex: ^caniuse-lite(/|$)
17
+ not:
18
+ inside:
19
+ kind: try_statement
20
+ stopBy: end
21
+
22
+ fix: |-
23
+ try {
24
+ $$$LHS = require($$$REQ);
25
+ } catch {
26
+ throw new Error('The optional dependency "$MOD" is not installed');
27
+ }
28
+ `;
29
+ export function patchOptionalDependencies(root) {
30
+ return getRuleEdits(optionalDepRule, root);
31
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { optionalDepRule } from "./optional-deps.js";
3
+ import { patchCode } from "./util.js";
4
+ describe("optional dependecy", () => {
5
+ it('should wrap a top-level require("caniuse-lite") in a try-catch', () => {
6
+ const code = `t = require("caniuse-lite");`;
7
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
8
+ "try {
9
+ t = require("caniuse-lite");
10
+ } catch {
11
+ throw new Error('The optional dependency "caniuse-lite" is not installed');
12
+ };"
13
+ `);
14
+ });
15
+ it('should wrap a top-level require("caniuse-lite/data") in a try-catch', () => {
16
+ const code = `t = require("caniuse-lite/data");`;
17
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
18
+ "try {
19
+ t = require("caniuse-lite/data");
20
+ } catch {
21
+ throw new Error('The optional dependency "caniuse-lite/data" is not installed');
22
+ };"
23
+ `);
24
+ });
25
+ it('should wrap e.exports = require("caniuse-lite") in a try-catch', () => {
26
+ const code = 'e.exports = require("caniuse-lite");';
27
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
28
+ "try {
29
+ e.exports = require("caniuse-lite");
30
+ } catch {
31
+ throw new Error('The optional dependency "caniuse-lite" is not installed');
32
+ };"
33
+ `);
34
+ });
35
+ it('should wrap module.exports = require("caniuse-lite") in a try-catch', () => {
36
+ const code = 'module.exports = require("caniuse-lite");';
37
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
38
+ "try {
39
+ module.exports = require("caniuse-lite");
40
+ } catch {
41
+ throw new Error('The optional dependency "caniuse-lite" is not installed');
42
+ };"
43
+ `);
44
+ });
45
+ it('should wrap exports.foo = require("caniuse-lite") in a try-catch', () => {
46
+ const code = 'exports.foo = require("caniuse-lite");';
47
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
48
+ "try {
49
+ exports.foo = require("caniuse-lite");
50
+ } catch {
51
+ throw new Error('The optional dependency "caniuse-lite" is not installed');
52
+ };"
53
+ `);
54
+ });
55
+ it('should not wrap require("lodash") in a try-catch', () => {
56
+ const code = 't = require("lodash");';
57
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`"t = require("lodash");"`);
58
+ });
59
+ it('should not wrap require("other-module") if it does not match caniuse-lite regex', () => {
60
+ const code = 't = require("other-module");';
61
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`"t = require("other-module");"`);
62
+ });
63
+ it("should not wrap a require() call already inside a try-catch", () => {
64
+ const code = `
65
+ try {
66
+ const t = require("caniuse-lite");
67
+ } catch {}
68
+ `;
69
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
70
+ "try {
71
+ const t = require("caniuse-lite");
72
+ } catch {}
73
+ "
74
+ `);
75
+ });
76
+ it("should handle require with subpath and not wrap if already in try-catch", () => {
77
+ const code = `
78
+ try {
79
+ const t = require("caniuse-lite/path");
80
+ } catch {}
81
+ `;
82
+ expect(patchCode(code, optionalDepRule)).toMatchInlineSnapshot(`
83
+ "try {
84
+ const t = require("caniuse-lite/path");
85
+ } catch {}
86
+ "
87
+ `);
88
+ });
89
+ });
@@ -0,0 +1,39 @@
1
+ import { type Edit, Lang, type NapiConfig, type SgNode } from "@ast-grep/napi";
2
+ /**
3
+ * fix has the same meaning as in yaml rules
4
+ * see https://ast-grep.github.io/guide/rewrite-code.html#using-fix-in-yaml-rule
5
+ */
6
+ export type RuleConfig = NapiConfig & {
7
+ fix?: string;
8
+ };
9
+ /**
10
+ * Returns the `Edit`s for an ast-grep rule in yaml format
11
+ *
12
+ * The rule must have a `fix` to rewrite the matched node.
13
+ *
14
+ * Tip: use https://ast-grep.github.io/playground.html to create rules.
15
+ *
16
+ * @param rule The rule. Either a yaml string or an instance of `RuleConfig`
17
+ * @param root The root node
18
+ * @param once only apply once
19
+ * @returns A list of edits.
20
+ */
21
+ export declare function getRuleEdits(rule: string | RuleConfig, root: SgNode, { once }?: {
22
+ once?: boolean | undefined;
23
+ }): Edit[];
24
+ /**
25
+ * Patches the code from by applying the rule.
26
+ *
27
+ * This function is mainly for on off edits and tests,
28
+ * use `getRuleEdits` to apply multiple rules.
29
+ *
30
+ * @param code The source code
31
+ * @param rule The astgrep rule (yaml or NapiConfig)
32
+ * @param lang The language used by the source code
33
+ * @param lang Whether to apply the rule only once
34
+ * @returns The patched code
35
+ */
36
+ export declare function patchCode(code: string, rule: string | RuleConfig, { lang, once }?: {
37
+ lang?: Lang | undefined;
38
+ once?: boolean | undefined;
39
+ }): string;
@@ -0,0 +1,54 @@
1
+ import { Lang, parse } from "@ast-grep/napi";
2
+ import yaml from "yaml";
3
+ /**
4
+ * Returns the `Edit`s for an ast-grep rule in yaml format
5
+ *
6
+ * The rule must have a `fix` to rewrite the matched node.
7
+ *
8
+ * Tip: use https://ast-grep.github.io/playground.html to create rules.
9
+ *
10
+ * @param rule The rule. Either a yaml string or an instance of `RuleConfig`
11
+ * @param root The root node
12
+ * @param once only apply once
13
+ * @returns A list of edits.
14
+ */
15
+ export function getRuleEdits(rule, root, { once = false } = {}) {
16
+ const ruleConfig = typeof rule === "string" ? yaml.parse(rule) : rule;
17
+ if (ruleConfig.transform) {
18
+ throw new Error("transform is not supported");
19
+ }
20
+ if (!ruleConfig.fix) {
21
+ throw new Error("no fix to apply");
22
+ }
23
+ const fix = ruleConfig.fix;
24
+ const matches = once ? [root.find(ruleConfig)].filter((m) => m !== null) : root.findAll(ruleConfig);
25
+ const edits = [];
26
+ matches.forEach((match) => {
27
+ edits.push(match.replace(
28
+ // Replace known placeholders by their value
29
+ fix
30
+ .replace(/\$\$\$([A-Z0-9_]+)/g, (_m, name) => match
31
+ .getMultipleMatches(name)
32
+ .map((n) => n.text())
33
+ .join(""))
34
+ .replace(/\$([A-Z0-9_]+)/g, (m, name) => match.getMatch(name)?.text() ?? m)));
35
+ });
36
+ return edits;
37
+ }
38
+ /**
39
+ * Patches the code from by applying the rule.
40
+ *
41
+ * This function is mainly for on off edits and tests,
42
+ * use `getRuleEdits` to apply multiple rules.
43
+ *
44
+ * @param code The source code
45
+ * @param rule The astgrep rule (yaml or NapiConfig)
46
+ * @param lang The language used by the source code
47
+ * @param lang Whether to apply the rule only once
48
+ * @returns The patched code
49
+ */
50
+ export function patchCode(code, rule, { lang = Lang.TypeScript, once = false } = {}) {
51
+ const node = parse(lang, code).root();
52
+ const edits = getRuleEdits(rule, node, { once });
53
+ return node.commitEdits(edits);
54
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { patchCode } from "./util.js";
3
+ describe("patchCode", () => {
4
+ afterEach(() => {
5
+ vi.clearAllMocks();
6
+ });
7
+ it("should throw an error if rule has a transform", () => {
8
+ expect(() => patchCode(`console.log("hi")`, { rule: { pattern: "console.log($MSG)" }, transform: "not supported" })).toThrow(/not supported/);
9
+ });
10
+ it("should throw an error if rule has no fix", () => {
11
+ expect(() => patchCode(`console.log("hi")`, { rule: { pattern: "console.log($MSG)" } })).toThrow(/no fix/);
12
+ });
13
+ it("should accept yaml rules", () => {
14
+ const yamlRule = `
15
+ rule:
16
+ pattern: a
17
+ fix: b
18
+ `;
19
+ expect(patchCode(`a`, yamlRule)).toEqual("b");
20
+ });
21
+ it("should apply fix to a single match when once is true", () => {
22
+ expect(patchCode(`a+a`, { rule: { pattern: "a" }, fix: "b" }, { once: true })).toEqual("b+a");
23
+ });
24
+ it("should apply fix to all matches when once is false (default)", () => {
25
+ expect(patchCode(`a+a`, { rule: { pattern: "a" }, fix: "b" })).toEqual("b+b");
26
+ expect(patchCode(`a+a`, { rule: { pattern: "a" }, fix: "b" }, { once: false })).toEqual("b+b");
27
+ });
28
+ it("should handle no matches", () => {
29
+ expect(patchCode(`a`, { rule: { pattern: "b" }, fix: "c" })).toEqual("a");
30
+ });
31
+ it("should replace $PLACEHOLDER with match text", () => {
32
+ expect(patchCode(`console.log(message)`, { rule: { pattern: "console.log($MSG)" }, fix: "$MSG" })).toEqual("message");
33
+ });
34
+ it("should handle $PLACEHODLERS that are not found in matches", () => {
35
+ expect(patchCode(`console.log(message)`, { rule: { pattern: "console.log($MSG)" }, fix: "$WHAT$$$WHAT" })).toEqual("$WHAT");
36
+ });
37
+ it("should replace $$$PLACEHOLDER with match text", () => {
38
+ expect(patchCode(`console.log("hello" + world, "!")`, {
39
+ rule: { pattern: "console.log($$$ARGS)" },
40
+ fix: "$$$ARGS",
41
+ })).toEqual(`"hello" + world,"!"`);
42
+ });
43
+ });
@@ -9,7 +9,7 @@ import { normalizePath } from "../../utils/index.js";
9
9
  * there is a vm `runInNewContext` call which we also don't support (source: https://github.com/vercel/next.js/blob/b1e32c5d1f/packages/next/src/server/load-manifest.ts#L88)
10
10
  */
11
11
  export function inlineEvalManifest(code, config) {
12
- const manifestJss = globSync(normalizePath(join(config.paths.output.standaloneAppDotNext, "**", "*_client-reference-manifest.js"))).map((file) => normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, ""));
12
+ const manifestJss = globSync(normalizePath(join(config.paths.output.standaloneAppDotNext, "**/*_client-reference-manifest.js"))).map((file) => normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, ""));
13
13
  return code.replace(/function evalManifest\((.+?), .+?\) {/, `$&
14
14
  ${manifestJss
15
15
  .map((manifestJs) => `
@@ -15,7 +15,7 @@ export function patchLoadManifest(code, config) {
15
15
  // Same as patchBuildId, the next-server code loads the manifests with `readFileSync` and we want to avoid that
16
16
  // (source: https://github.com/vercel/next.js/blob/15aeb92e/packages/next/src/server/load-manifest.ts#L34-L56)
17
17
  // Note: we could/should probably just patch readFileSync here or something!
18
- const manifestJsons = globSync(normalizePath(join(config.paths.output.standaloneAppDotNext, "**", "*-manifest.json"))).map((file) => normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, ""));
18
+ const manifestJsons = globSync(normalizePath(join(config.paths.output.standaloneAppDotNext, "**/*-manifest.json"))).map((file) => normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, ""));
19
19
  return code.replace(/function loadManifest\((.+?), .+?\) {/, `$&
20
20
  ${manifestJsons
21
21
  .map((manifestJson) => `
@@ -12,7 +12,7 @@ export function patchWranglerDeps(config) {
12
12
  // [alias]
13
13
  // # critters is `require`d from `pages.runtime.prod.js` when running wrangler dev, so we need to stub it out
14
14
  // "critters" = "./.next/standalone/node_modules/cf/templates/shims/empty.ts"
15
- const pagesRuntimeFile = join(distPath, "compiled", "next-server", "pages.runtime.prod.js");
15
+ const pagesRuntimeFile = join(distPath, "compiled/next-server/pages.runtime.prod.js");
16
16
  const patchedPagesRuntime = readFileSync(pagesRuntimeFile, "utf-8").replace(`e.exports=require("critters")`, `e.exports={}`);
17
17
  writeFileSync(pagesRuntimeFile, patchedPagesRuntime);
18
18
  patchRequireReactDomServerEdge(config);
@@ -26,7 +26,7 @@ export function patchWranglerDeps(config) {
26
26
  // # try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31
27
27
  // # causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works)
28
28
  // #"@opentelemetry/api" = "./.next/standalone/node_modules/cf/templates/shims/throw.ts"
29
- const tracerFile = join(distPath, "server", "lib", "trace", "tracer.js");
29
+ const tracerFile = join(distPath, "server/lib/trace/tracer.js");
30
30
  const patchedTracer = readFileSync(tracerFile, "utf-8").replaceAll(/\w+\s*=\s*require\([^/]*opentelemetry.*\)/g, `throw new Error("@opentelemetry/api")`);
31
31
  writeFileSync(tracerFile, patchedTracer);
32
32
  }
@@ -45,7 +45,7 @@ export function patchWranglerDeps(config) {
45
45
  function getDistPath(config) {
46
46
  for (const root of [config.paths.output.standaloneApp, config.paths.output.standaloneRoot]) {
47
47
  try {
48
- const distPath = join(root, "node_modules", "next", "dist");
48
+ const distPath = join(root, "node_modules/next/dist");
49
49
  if (statSync(distPath).isDirectory())
50
50
  return distPath;
51
51
  }
@@ -73,7 +73,7 @@ function getDistPath(config) {
73
73
  function patchRequireReactDomServerEdge(config) {
74
74
  const distPath = getDistPath(config);
75
75
  // Patch .next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js
76
- const pagesRuntimeFile = join(distPath, "compiled", "next-server", "pages.runtime.prod.js");
76
+ const pagesRuntimeFile = join(distPath, "compiled/next-server/pages.runtime.prod.js");
77
77
  const code = readFileSync(pagesRuntimeFile, "utf-8");
78
78
  const file = tsParseFile(code);
79
79
  // we need to update this function: `e=>{"use strict";e.exports=require("react-dom/server.edge")}`
@@ -28,7 +28,7 @@ export async function createWranglerConfigIfNotExistent(projectOpts) {
28
28
  "(to avoid this check use the `--skipWranglerConfigCheck` flag or set a `SKIP_WRANGLER_CONFIG_CHECK` environment variable to `yes`)");
29
29
  return;
30
30
  }
31
- let wranglerConfig = readFileSync(join(getPackageTemplatesDirPath(), "defaults", "wrangler.json"), "utf8");
31
+ let wranglerConfig = readFileSync(join(getPackageTemplatesDirPath(), "defaults/wrangler.json"), "utf8");
32
32
  const appName = getAppNameFromPackageJson(projectOpts.sourceDir) ?? "app-name";
33
33
  if (appName) {
34
34
  wranglerConfig = wranglerConfig.replace('"app-name"', JSON.stringify(appName.replaceAll("_", "-")));
@@ -80,6 +80,6 @@ export async function createOpenNextConfigIfNotExistent(projectOpts) {
80
80
  if (!answer) {
81
81
  throw new Error("The `open-next.config.ts` file is required, aborting!");
82
82
  }
83
- cpSync(join(getPackageTemplatesDirPath(), "defaults", "open-next.config.ts"), openNextConfigPath);
83
+ cpSync(join(getPackageTemplatesDirPath(), "defaults/open-next.config.ts"), openNextConfigPath);
84
84
  }
85
85
  }
@@ -17,7 +17,7 @@ export function getConfig(projectOpts) {
17
17
  const standaloneAppServer = join(standaloneAppDotNext, "server");
18
18
  const nodeModules = join(standaloneApp, "node_modules");
19
19
  const internalPackage = join(nodeModules, ...PACKAGE_NAME.split("/"));
20
- const internalTemplates = join(internalPackage, "cli", "templates");
20
+ const internalTemplates = join(internalPackage, "cli/templates");
21
21
  return {
22
22
  build: {
23
23
  skipNextBuild: projectOpts.skipNextBuild,
@@ -72,7 +72,7 @@ function getNextjsApplicationPath(dotNextDir) {
72
72
  }
73
73
  function findServerParentPath(parentPath) {
74
74
  try {
75
- if (statSync(join(parentPath, ".next", "server")).isDirectory()) {
75
+ if (statSync(join(parentPath, ".next/server")).isDirectory()) {
76
76
  return parentPath;
77
77
  }
78
78
  }
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.3.9",
4
+ "version": "0.3.10",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "opennextjs-cloudflare": "dist/cli/index.js"
@@ -48,27 +48,29 @@
48
48
  "@types/mock-fs": "^4.13.4",
49
49
  "@types/node": "^22.2.0",
50
50
  "esbuild": "^0.23.0",
51
+ "eslint": "^9.11.1",
51
52
  "eslint-plugin-import": "^2.31.0",
52
53
  "eslint-plugin-simple-import-sort": "^12.1.1",
53
54
  "eslint-plugin-unicorn": "^55.0.0",
54
- "eslint": "^9.11.1",
55
55
  "globals": "^15.9.0",
56
56
  "mock-fs": "^5.4.1",
57
57
  "next": "14.2.11",
58
58
  "rimraf": "^6.0.1",
59
+ "typescript": "^5.7.3",
59
60
  "typescript-eslint": "^8.7.0",
60
- "typescript": "^5.5.4",
61
61
  "vitest": "^2.1.1"
62
62
  },
63
63
  "dependencies": {
64
+ "@ast-grep/napi": "^0.33.1",
64
65
  "@dotenvx/dotenvx": "1.31.0",
65
66
  "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@704",
67
+ "enquirer": "^2.4.1",
66
68
  "glob": "^11.0.0",
67
69
  "ts-morph": "^23.0.0",
68
- "enquirer": "^2.4.1"
70
+ "yaml": "^2.7.0"
69
71
  },
70
72
  "peerDependencies": {
71
- "wrangler": "^3.101.0"
73
+ "wrangler": "^3.103.0"
72
74
  },
73
75
  "scripts": {
74
76
  "clean": "rimraf dist",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "$schema": "node_modules/wrangler/config-schema.json",
2
3
  "main": ".open-next/worker.js",
3
4
  "name": "app-name",
4
5
  "compatibility_date": "2024-12-30",