@opennextjs/aws 4.1.12 → 4.1.13

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.
@@ -0,0 +1,49 @@
1
+ import { type CodePatcher } from "./codePatcher.js";
2
+ /**
3
+ * A Next.js package installed on disk.
4
+ */
5
+ export interface NextPackage {
6
+ /** Directory of the package, i.e. the directory of its `package.json`. */
7
+ dir: string;
8
+ /** Version of the package. */
9
+ version: string;
10
+ }
11
+ /**
12
+ * Compute the diff resulting of applying the `rule` to `src`.
13
+ *
14
+ * `diff` is an optional peer dependency of `@opennextjs/aws`: it must be installed to call this function.
15
+ *
16
+ * @param filename Filename used in the patch output
17
+ * @param src Content of the source code
18
+ * @param rule ASTgrep rule
19
+ * @returns diff in unified diff format
20
+ * @throws When the `diff` package is not installed
21
+ */
22
+ export declare function computePatchDiff(filename: string, src: string, rule: string): string;
23
+ /**
24
+ * Get the Next.js packages installed for some applications.
25
+ *
26
+ * Packages are deduplicated by version: a package manager can install the same version in multiple
27
+ * directories (i.e. pnpm when the peer dependencies differ).
28
+ *
29
+ * @param appDirs Directories of the applications (absolute or relative to the current working directory),
30
+ * `next` is resolved from their `package.json`
31
+ * @returns the path and version of the Next.js packages
32
+ * @throws When `next` can not be resolved from one of the applications
33
+ */
34
+ export declare function getInstalledNextPackages(appDirs: string[]): NextPackage[];
35
+ /**
36
+ * Get the files of a Next.js package that a code patcher applies to.
37
+ *
38
+ * It selects the files the same way `applyCodePatches` does at build time,
39
+ * i.e. using the `versions`, the `pathFilter` and the `contentFilter` of the patches.
40
+ *
41
+ * @param next A Next.js package, see `getInstalledNextPackages`
42
+ * @param codePatcher The code patcher
43
+ * @returns the files (path relative to the package) with their content and the patches to apply
44
+ */
45
+ export declare function getNextFilesToPatch(next: NextPackage, codePatcher: CodePatcher): {
46
+ name: string;
47
+ code: string;
48
+ patches: CodePatcher["patches"];
49
+ }[];
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Utilities to test code patches.
3
+ *
4
+ * They are used by the OpenNext adapters to test their patches against frozen snippets and against
5
+ * the files of the Next.js versions they are installed with.
6
+ * This module is not used at build time or at runtime.
7
+ */
8
+ import { readFileSync, readdirSync } from "node:fs";
9
+ import { createRequire } from "node:module";
10
+ import path from "node:path";
11
+ import { patchCode } from "./astCodePatcher.js";
12
+ import { isVersionInRange } from "./codePatcher.js";
13
+ const require = createRequire(import.meta.url);
14
+ /**
15
+ * Compute the diff resulting of applying the `rule` to `src`.
16
+ *
17
+ * `diff` is an optional peer dependency of `@opennextjs/aws`: it must be installed to call this function.
18
+ *
19
+ * @param filename Filename used in the patch output
20
+ * @param src Content of the source code
21
+ * @param rule ASTgrep rule
22
+ * @returns diff in unified diff format
23
+ * @throws When the `diff` package is not installed
24
+ */
25
+ export function computePatchDiff(filename, src, rule) {
26
+ // Loaded lazily so that the other utilities can be used without `diff`.
27
+ const { createPatch } = require("diff");
28
+ const dst = patchCode(src, rule);
29
+ return createPatch(filename, src, dst);
30
+ }
31
+ /**
32
+ * Get the Next.js packages installed for some applications.
33
+ *
34
+ * Packages are deduplicated by version: a package manager can install the same version in multiple
35
+ * directories (i.e. pnpm when the peer dependencies differ).
36
+ *
37
+ * @param appDirs Directories of the applications (absolute or relative to the current working directory),
38
+ * `next` is resolved from their `package.json`
39
+ * @returns the path and version of the Next.js packages
40
+ * @throws When `next` can not be resolved from one of the applications
41
+ */
42
+ export function getInstalledNextPackages(appDirs) {
43
+ const packages = new Map();
44
+ for (const appDir of appDirs) {
45
+ const appRequire = createRequire(path.join(path.resolve(appDir), "package.json"));
46
+ const dir = path.dirname(appRequire.resolve("next/package.json"));
47
+ const { version } = JSON.parse(readFileSync(path.join(dir, "package.json"), "utf-8"));
48
+ if (!packages.has(version)) {
49
+ packages.set(version, dir);
50
+ }
51
+ }
52
+ return [...packages].map(([version, dir]) => ({ dir, version }));
53
+ }
54
+ /**
55
+ * Get the files of a Next.js package that a code patcher applies to.
56
+ *
57
+ * It selects the files the same way `applyCodePatches` does at build time,
58
+ * i.e. using the `versions`, the `pathFilter` and the `contentFilter` of the patches.
59
+ *
60
+ * @param next A Next.js package, see `getInstalledNextPackages`
61
+ * @param codePatcher The code patcher
62
+ * @returns the files (path relative to the package) with their content and the patches to apply
63
+ */
64
+ export function getNextFilesToPatch(next, codePatcher) {
65
+ const patches = codePatcher.patches.filter(({ versions }) => isVersionInRange(next.version, versions));
66
+ return readdirSync(next.dir, { recursive: true }).flatMap((name) => {
67
+ const filePath = path.join(next.dir, name);
68
+ const matchingPath = patches.filter(({ pathFilter }) => filePath.match(pathFilter));
69
+ if (matchingPath.length === 0) {
70
+ return [];
71
+ }
72
+ const code = readFileSync(filePath, "utf-8");
73
+ const matchingContent = matchingPath.filter(({ contentFilter }) => !contentFilter || code.match(contentFilter));
74
+ return matchingContent.length === 0
75
+ ? []
76
+ : [{ name, code, patches: matchingContent }];
77
+ });
78
+ }
@@ -1,6 +1,7 @@
1
1
  import { Readable, Writable } from "node:stream";
2
2
  import zlib from "node:zlib";
3
3
  import { error } from "../../adapters/logger";
4
+ import { getBrotliQuality } from "../../utils/compression";
4
5
  import { formatWarmerResponse } from "./aws-lambda";
5
6
  const handler = async (handler, converter) => async (event) => {
6
7
  // Handle warmer event
@@ -70,10 +71,7 @@ function compressBody(body, encoding) {
70
71
  case "br":
71
72
  transform = zlib.createBrotliCompress({
72
73
  params: {
73
- // This is a compromise between speed and compression ratio.
74
- // The default one will most likely timeout an AWS Lambda with default configuration on large bodies (>6mb).
75
- // Therefore we set it to 6, which is a good compromise.
76
- [zlib.constants.BROTLI_PARAM_QUALITY]: Number(process.env.BROTLI_QUALITY) ?? 6,
74
+ [zlib.constants.BROTLI_PARAM_QUALITY]: getBrotliQuality(),
77
75
  },
78
76
  });
79
77
  break;
@@ -1,6 +1,7 @@
1
1
  import { Readable } from "node:stream";
2
2
  import zlib from "node:zlib";
3
3
  import { debug, error } from "../../adapters/logger";
4
+ import { getBrotliQuality } from "../../utils/compression";
4
5
  import { DetachedPromiseRunner } from "../../utils/promise";
5
6
  function formatWarmerResponse(event) {
6
7
  const result = new Promise((resolve) => {
@@ -34,6 +35,9 @@ const handler = async (handler, converter) => awslambda.streamifyResponse(async
34
35
  compressedStream = zlib.createBrotliCompress({
35
36
  flush: zlib.constants.BROTLI_OPERATION_FLUSH,
36
37
  finishFlush: zlib.constants.BROTLI_OPERATION_FINISH,
38
+ params: {
39
+ [zlib.constants.BROTLI_PARAM_QUALITY]: getBrotliQuality(),
40
+ },
37
41
  });
38
42
  compressedStream.pipe(responseStream);
39
43
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Brotli quality used by the compressing wrappers.
3
+ *
4
+ * It can be set with the `BROTLI_QUALITY` environment variable (0 to 11) and defaults to 6.
5
+ * Quality 10 and 11 cost an order of magnitude more CPU than 6 for a few percent smaller output,
6
+ * which delays every streamed response.
7
+ */
8
+ export declare function getBrotliQuality(): number;
@@ -0,0 +1,16 @@
1
+ import zlib from "node:zlib";
2
+ const DEFAULT_BROTLI_QUALITY = 6;
3
+ /**
4
+ * Brotli quality used by the compressing wrappers.
5
+ *
6
+ * It can be set with the `BROTLI_QUALITY` environment variable (0 to 11) and defaults to 6.
7
+ * Quality 10 and 11 cost an order of magnitude more CPU than 6 for a few percent smaller output,
8
+ * which delays every streamed response.
9
+ */
10
+ export function getBrotliQuality() {
11
+ const quality = Number.parseInt(process.env.BROTLI_QUALITY ?? "", 10);
12
+ return quality >= zlib.constants.BROTLI_MIN_QUALITY &&
13
+ quality <= zlib.constants.BROTLI_MAX_QUALITY
14
+ ? quality
15
+ : DEFAULT_BROTLI_QUALITY;
16
+ }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "access": "public"
4
4
  },
5
5
  "name": "@opennextjs/aws",
6
- "version": "4.1.12",
6
+ "version": "4.1.13",
7
7
  "bin": {
8
8
  "open-next": "./dist/index.js"
9
9
  },
@@ -56,13 +56,20 @@
56
56
  "@types/express": "5.0.6",
57
57
  "@types/node": "20.17.6",
58
58
  "concurrently": "^9.2.4",
59
+ "diff": "^9.0.0",
59
60
  "next": "16.4.1",
60
61
  "tsc-alias": "^1.9.7",
61
62
  "typescript": "5.9.3"
62
63
  },
63
64
  "peerDependencies": {
65
+ "diff": "^9.0.0",
64
66
  "next": ">=15.5.28 <16 || >=16.4.1"
65
67
  },
68
+ "peerDependenciesMeta": {
69
+ "diff": {
70
+ "optional": true
71
+ }
72
+ },
66
73
  "bugs": {
67
74
  "url": "https://github.com/opennextjs/opennextjs-aws/issues"
68
75
  },