diff --git a/.projen/deps.json b/.projen/deps.json index 6000d27f..b57839b5 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -16,10 +16,6 @@ "name": "@smithy/signature-v4", "type": "build" }, - { - "name": "@types/adm-zip", - "type": "build" - }, { "name": "@types/aws-lambda", "type": "build" diff --git a/.projen/tasks.json b/.projen/tasks.json index f998c20d..26badcbe 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -317,13 +317,13 @@ }, "steps": [ { - "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@aws-crypto/sha256-js,@aws-sdk/client-s3,@mrgrain/jsii-struct-builder,@smithy/signature-v4,@types/adm-zip,@types/aws-lambda,@types/jest,@types/micromatch,@types/mime-types,@types/node,@typescript-eslint/eslint-plugin,@typescript-eslint/parser,aws-lambda,esbuild,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,eslint,jest,jest-junit,jsii-diff,jsii-docgen,jsii-pacmak,jszip,micromatch,mime-types,prettier,projen,standard-version,ts-jest,ts-node,typescript,undici,aws-cdk-lib,constructs" + "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@aws-crypto/sha256-js,@aws-sdk/client-s3,@mrgrain/jsii-struct-builder,@smithy/signature-v4,@types/aws-lambda,@types/jest,@types/micromatch,@types/mime-types,@types/node,@typescript-eslint/eslint-plugin,@typescript-eslint/parser,aws-lambda,esbuild,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,eslint,jest,jest-junit,jsii-diff,jsii-docgen,jsii-pacmak,jszip,micromatch,mime-types,prettier,projen,standard-version,ts-jest,ts-node,typescript,undici,aws-cdk-lib,constructs" }, { "exec": "yarn install --check-files" }, { - "exec": "yarn upgrade @aws-crypto/sha256-js @aws-sdk/client-s3 @mrgrain/jsii-struct-builder @smithy/signature-v4 @types/adm-zip @types/aws-lambda @types/jest @types/micromatch @types/mime-types @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-lambda esbuild eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit jsii-diff jsii-docgen jsii-pacmak jszip micromatch mime-types prettier projen standard-version ts-jest ts-node typescript undici aws-cdk-lib constructs" + "exec": "yarn upgrade @aws-crypto/sha256-js @aws-sdk/client-s3 @mrgrain/jsii-struct-builder @smithy/signature-v4 @types/aws-lambda @types/jest @types/micromatch @types/mime-types @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-lambda esbuild eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit jsii-diff jsii-docgen jsii-pacmak jszip micromatch mime-types prettier projen standard-version ts-jest ts-node typescript undici aws-cdk-lib constructs" }, { "exec": "npx projen" diff --git a/.projenrc.ts b/.projenrc.ts index b9e27a8e..8ba7df20 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -57,11 +57,10 @@ const project = new awscdk.AwsCdkConstructLibrary({ '@aws-sdk/client-s3', '@mrgrain/jsii-struct-builder', '@smithy/signature-v4', - '@types/adm-zip', '@types/aws-lambda', '@types/micromatch', '@types/mime-types', - '@types/node@^18', + '@types/node@^20', 'aws-lambda', 'constructs', 'jszip', diff --git a/package.json b/package.json index 6ef1e032..f6593610 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@aws-sdk/client-s3": "^3.462.0", "@mrgrain/jsii-struct-builder": "^0.7.3", "@smithy/signature-v4": "^2.0.16", - "@types/adm-zip": "^0.5.5", "@types/aws-lambda": "^8.10.130", "@types/jest": "^27", "@types/micromatch": "^4.0.6", diff --git a/src/NextjsDistribution.ts b/src/NextjsDistribution.ts index c7c2a996..5e63755d 100644 --- a/src/NextjsDistribution.ts +++ b/src/NextjsDistribution.ts @@ -285,6 +285,7 @@ export class NextjsDistribution extends Construct { ...this.commonBehaviorOptions, origin, allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL, + // ALL_VIEWER_EXCEPT_HOST_HEADER needed Lambda Function URL; see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-all-viewer-except-host-header originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER, cachePolicy, edgeLambdas: this.edgeLambdas.length ? this.edgeLambdas : undefined, @@ -351,6 +352,7 @@ export class NextjsDistribution extends Construct { allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS, cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS, cachePolicy, + // ALL_VIEWER_EXCEPT_HOST_HEADER needed Lambda Function URL; see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-all-viewer-except-host-header originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER, edgeLambdas: this.edgeLambdas, responseHeadersPolicy, diff --git a/src/utils/create-archive.ts b/src/utils/create-archive.ts index 01564f9e..a2bde2ef 100644 --- a/src/utils/create-archive.ts +++ b/src/utils/create-archive.ts @@ -1,7 +1,7 @@ import { execSync } from 'node:child_process'; -import * as fs from 'node:fs'; -import * as os from 'node:os'; -import * as path from 'node:path'; +import { Dirent, cpSync, existsSync, mkdtempSync, readdirSync, renameSync, rmSync, unlinkSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; export interface CreateArchiveArgs { readonly directory: string; @@ -17,18 +17,24 @@ export interface CreateArchiveArgs { * for PNPM monorepos. See more here: https://github.com/aws/aws-cdk/issues/9251 */ export function createArchive({ directory, zipFileName, fileGlob = '.', quiet }: CreateArchiveArgs): string { - const zipOutDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-nextjs-archive-')); - const zipFilePath = path.join(zipOutDir, zipFileName); + const zipOutDir = mkdtempSync(join(tmpdir(), 'cdk-nextjs-archive-')); + const zipFilePath = join(zipOutDir, zipFileName); - // delete existing zip file - if (fs.existsSync(zipFilePath)) { - fs.unlinkSync(zipFilePath); + if (existsSync(zipFilePath)) { + // delete existing zip file + unlinkSync(zipFilePath); } - // run script to create zipfile, preserving symlinks for node_modules (e.g. pnpm structure) const isWindows = process.platform === 'win32'; + // needed for PNPM if (isWindows) { - // TODO: test on windows + const nodeModulesDir = join(directory, 'node_modules'); + const files = readdirSync(nodeModulesDir, { recursive: true, withFileTypes: true }); + if (files.some((f) => f.isSymbolicLink())) { + // Compress-Archive doesn't support resolving symlinks like `zip` command + // does with -y option. Therefore, we need to resolve symlinks then compress. + resolveSymlinks(files); + } execSync(`Compress-Archive -Path '${directory}\\*' -DestinationPath '${zipFilePath}' -CompressionLevel Optimal`, { stdio: 'inherit', shell: 'powershell.exe', @@ -40,7 +46,7 @@ export function createArchive({ directory, zipFileName, fileGlob = '.', quiet }: }); } // check output - if (!fs.existsSync(zipFilePath)) { + if (!existsSync(zipFilePath)) { throw new Error( `There was a problem generating the archive for ${directory}; the archive is missing in ${zipFilePath}.` ); @@ -48,3 +54,19 @@ export function createArchive({ directory, zipFileName, fileGlob = '.', quiet }: return zipFilePath; } + +/** + * Resolve symlinks + */ +function resolveSymlinks(files: Dirent[]) { + for (const file of files) { + if (file.isSymbolicLink()) { + const tmpDir = mkdtempSync(join(tmpdir(), `${file.name}-`)); + // cannot do `cpSync` to resolve symlinks in-place so must use temp dir + const path = join(file.path, file.name); + cpSync(path, tmpDir, { recursive: true, dereference: true, force: true }); + rmSync(path, { recursive: true }); + renameSync(tmpDir, path); + } + } +} diff --git a/yarn.lock b/yarn.lock index 4ca6ed95..baadeb0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1884,13 +1884,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/adm-zip@^0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@types/adm-zip/-/adm-zip-0.5.5.tgz#4588042726aa5f351d7ea88232e4a952f60e7c1a" - integrity sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw== - dependencies: - "@types/node" "*" - "@types/aws-lambda@^8.10.130": version "8.10.130" resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.130.tgz#d4a44201f0e47c8320a5868d845ad654f3b4adc2"