From d108e92bfc00c3e45650d75dca19785bd1dc6973 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Tue, 27 Jun 2023 17:29:02 +0200 Subject: [PATCH 01/13] feat: add revalidateTag handling --- packages/open-next/package.json | 1 + packages/open-next/src/adapters/cache.ts | 191 ++++++- packages/open-next/src/build.ts | 90 +++- pnpm-lock.yaml | 643 ++++++++++++++--------- 4 files changed, 655 insertions(+), 270 deletions(-) diff --git a/packages/open-next/package.json b/packages/open-next/package.json index a0c92c5f..dcbd8d03 100644 --- a/packages/open-next/package.json +++ b/packages/open-next/package.json @@ -34,6 +34,7 @@ "README.md" ], "dependencies": { + "@aws-sdk/client-dynamodb": "^3.398.0", "@aws-sdk/client-lambda": "^3.398.0", "@aws-sdk/client-s3": "^3.398.0", "@aws-sdk/client-sqs": "^3.398.0", diff --git a/packages/open-next/src/adapters/cache.ts b/packages/open-next/src/adapters/cache.ts index ed0cc7ee..d3acad41 100644 --- a/packages/open-next/src/adapters/cache.ts +++ b/packages/open-next/src/adapters/cache.ts @@ -1,5 +1,10 @@ import path from "node:path"; +import { + BatchWriteItemCommand, + DynamoDBClient, + QueryCommand, +} from "@aws-sdk/client-dynamodb"; import { DeleteObjectsCommand, GetObjectCommand, @@ -8,6 +13,8 @@ import { PutObjectCommandInput, S3Client, } from "@aws-sdk/client-s3"; +//@ts-ignore +import { getDerivedTags } from "next/dist/server/lib/incremental-cache/utils"; import { awsLogger, debug, error } from "./logger.js"; import { loadBuildId } from "./util.js"; @@ -17,7 +24,9 @@ interface CachedFetchValue { data: { headers: { [k: string]: string }; body: string; + url: string; status?: number; + tags?: string[]; }; revalidate: number; } @@ -51,6 +60,8 @@ interface IncrementalCachedPageValue { // the string value html: string; pageData: Object; + status?: number; + headers?: Record; } type IncrementalCacheValue = @@ -88,11 +99,16 @@ type Extension = | "redirect"; // Expected environment variables -const { CACHE_BUCKET_NAME, CACHE_BUCKET_KEY_PREFIX, CACHE_BUCKET_REGION } = - process.env; +const { + CACHE_BUCKET_NAME, + CACHE_BUCKET_KEY_PREFIX, + CACHE_BUCKET_REGION, + CACHE_DYNAMO_TABLE, +} = process.env; export default class S3Cache { private client: S3Client; + private dynamoClient: DynamoDBClient; private buildId: string; constructor(_ctx: CacheHandlerContext) { @@ -100,12 +116,16 @@ export default class S3Cache { region: CACHE_BUCKET_REGION, logger: awsLogger, }); + this.dynamoClient = new DynamoDBClient({ + region: CACHE_BUCKET_REGION, + logger: awsLogger, + }); this.buildId = loadBuildId( path.dirname(_ctx.serverDistDir ?? ".next/server"), ); } - async get(key: string, fetchCache?: boolean) { + public async get(key: string, fetchCache?: boolean) { return fetchCache ? this.getFetchCache(key) : this.getIncrementalCache(key); } @@ -113,8 +133,13 @@ export default class S3Cache { debug("get fetch cache", { key }); try { const { Body, LastModified } = await this.getS3Object(key, "fetch"); + const lastModified = await this.getHasRevalidatedTags( + key, + LastModified?.getTime(), + ); + return { - lastModified: LastModified?.getTime(), + lastModified, value: JSON.parse((await Body?.transformToString()) ?? "{}"), } as CacheHandlerValue; } catch (e) { @@ -160,19 +185,27 @@ export default class S3Cache { if (!isJson && !isRsc) return null; try { - const [{ Body, LastModified }, { Body: PageBody }] = await Promise.all([ - this.getS3Object(key, "html"), - this.getS3Object(key, isJson ? "json" : "rsc"), - ]); - + const [{ Body, LastModified }, { Body: PageBody }, { Body: MetaBody }] = + await Promise.all([ + this.getS3Object(key, "html"), + this.getS3Object(key, isJson ? "json" : "rsc"), + this.getS3Object(key, "meta"), + ]); + const lastModified = await this.getHasRevalidatedTags( + key, + LastModified?.getTime(), + ); + const meta = JSON.parse((await MetaBody?.transformToString()) ?? "{}"); return { - lastModified: LastModified?.getTime(), + lastModified, value: { kind: "PAGE", html: (await Body?.transformToString()) ?? "", pageData: isJson ? JSON.parse((await PageBody?.transformToString()) ?? "{}") : await PageBody?.transformToString(), + status: meta.status, + headers: meta.headers, }, } as CacheHandlerValue; } catch (e) { @@ -200,7 +233,7 @@ export default class S3Cache { return null; } - async set(key: string, data?: IncrementalCacheValue | null): Promise { + async set(key: string, data?: IncrementalCacheValue): Promise { if (data?.kind === "ROUTE") { const { body, status, headers } = data; await Promise.all([ @@ -227,8 +260,144 @@ export default class S3Cache { } else if (data === null || data === undefined) { await this.deleteS3Objects(key); } + // Write getDerivedTags to dynamodb + // If we use an in house version of getDerivedTags in build we should use it here instead of next's one + const derivedTags: string[] = + data?.kind === "FETCH" + ? getDerivedTags(data.data.tags ?? []) + : data?.kind === "PAGE" + ? getDerivedTags(data.headers?.["x-next-cache-tags"]?.split(",") ?? []) + : []; + debug("derivedTags", derivedTags); + if (derivedTags.length > 0) { + // Maybe we should not override the tag revalidateAt if it is already set + // With our current implementation it should not matter, every time we update the cache + // it is because of a revalidation and every ISR is considered as on demand revalidation + // so effectively skipping the fetch cache + await this.batchWriteDynamoItem( + derivedTags.map((tag) => ({ + path: key, + tag: tag, + })), + ); + } + } + + public async revalidateTag(tag: string) { + debug("revalidateTag", tag); + // Find all keys with the given tag + const paths = await this.getByTag(tag); + debug("Items", paths); + // Update all keys with the given tag with revalidatedAt set to now + await this.batchWriteDynamoItem( + paths?.map((path) => ({ + path: path, + tag: tag, + })) ?? [], + ); + } + + // DynamoDB handling + + //TODO: Figure out a better name for this function since it returns the lastModified + private async getHasRevalidatedTags(key: string, lastModified?: number) { + try { + const result = await this.dynamoClient.send( + new QueryCommand({ + TableName: CACHE_DYNAMO_TABLE, + IndexName: "revalidate", + KeyConditionExpression: + "#key = :key AND #revalidatedAt > :lastModified", + ExpressionAttributeNames: { + "#key": "path", + "#revalidatedAt": "revalidatedAt", + }, + ExpressionAttributeValues: { + ":key": { S: this.buildDynamoKey(key) }, + ":lastModified": { N: String(lastModified ?? 0) }, + }, + }), + ); + const revalidatedTags = result.Items ?? []; + debug("revalidatedTags", revalidatedTags); + // If we have revalidated tags we return -1 to force revalidation + return revalidatedTags.length > 0 ? -1 : lastModified ?? Date.now(); + } catch (e) { + error("Failed to get revalidated tags", e); + return lastModified ?? Date.now(); + } + } + + private async getByTag(tag: string) { + try { + const { Items } = await this.dynamoClient.send( + new QueryCommand({ + TableName: CACHE_DYNAMO_TABLE, + KeyConditionExpression: "#tag = :tag", + ExpressionAttributeNames: { + "#tag": "tag", + }, + ExpressionAttributeValues: { + ":tag": { S: this.buildDynamoKey(tag) }, + }, + }), + ); + return ( + // We need to remove the buildId from the path + Items?.map( + ({ path: { S: key } }) => key?.replace(`${this.buildId}/`, "") ?? "", + ) ?? [] + ); + } catch (e) { + error("Failed to get by tag", e); + return []; + } } + private async batchWriteDynamoItem(req: { path: string; tag: string }[]) { + await Promise.all( + this.chunkArray(req, 25).map((Items) => { + return this.dynamoClient.send( + new BatchWriteItemCommand({ + RequestItems: { + [CACHE_DYNAMO_TABLE ?? ""]: Items.map((Item) => ({ + PutRequest: { + Item: { + ...this.buildDynamoObject(Item.path, Item.tag), + }, + }, + })), + }, + }), + ); + }), + ); + } + + private buildDynamoKey(key: string) { + // FIXME: We should probably use something else than path.join here + // this could transform some fetch cache key into a valid path + return path.posix.join(this.buildId, key); + } + + private buildDynamoObject(path: string, tags: string) { + return { + path: { S: this.buildDynamoKey(path) }, + tag: { S: this.buildDynamoKey(tags) }, + revalidatedAt: { N: `${Date.now()}` }, + }; + } + + private chunkArray(array: T[], chunkSize: number) { + const chunks = []; + for (let i = 0; i < array.length; i += chunkSize) { + chunks.push(array.slice(i, i + chunkSize)); + } + return chunks; + } + + // S3 handling + private buildS3Key(key: string, extension: Extension) { return path.posix.join( CACHE_BUCKET_KEY_PREFIX ?? "", diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 7e6bef5e..bcbcf5ce 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -393,6 +393,14 @@ function createCacheAssets(monorepoRoot: string) { (file.endsWith(".html") && htmlPages.has(file)), ); + // Generate dynamodb data + // We need to traverse the cache to find every .meta file + const metaFiles: { + tag: { S: string }; + path: { S: string }; + revalidatedAt: { N: string }; + }[] = []; + // Copy fetch-cache to cache folder const fetchCachePath = path.join( appBuildOutputPath, @@ -402,6 +410,63 @@ function createCacheAssets(monorepoRoot: string) { const fetchOutputPath = path.join(outputDir, "cache", "__fetch", buildId); fs.mkdirSync(fetchOutputPath, { recursive: true }); fs.cpSync(fetchCachePath, fetchOutputPath, { recursive: true }); + + // Compute dynamodb cache data + // Traverse files inside cache to find all meta files and cache tags associated with them + traverseFiles( + outputPath, + (file) => file.endsWith(".meta"), + (filePath) => { + const fileContent = fs.readFileSync(filePath, "utf8"); + const fileData = JSON.parse(fileContent); + if (fileData.headers?.["x-next-cache-tags"]) { + fileData.headers["x-next-cache-tags"] + .split(",") + .forEach((tag: string) => { + // TODO: We should split the tag using getDerivedTags from next.js or maybe use an in house implementation + metaFiles.push({ + tag: { S: path.posix.join(buildId, tag.trim()) }, + path: { + S: path.posix.join( + buildId, + path.relative(outputPath, filePath).replace(".meta", "") + ), + }, + revalidatedAt: { N: `${Date.now()}` }, + }); + }); + } + } + ); + + const tagsManifestPath = path.join(fetchCachePath, "tags-manifest.json"); + if (fs.existsSync(tagsManifestPath)) { + // We also need to add cache tags from tags-manifest.json + const tagsManifestFile = fs.readFileSync(tagsManifestPath, "utf8"); + const tagsManifest = JSON.parse(tagsManifestFile) as { + version: number; + items: { + [tag: string]: { + keys: string[]; + }; + }; + }; + Object.entries(tagsManifest.items).forEach(([tag, tagObject]) => { + tagObject.keys.forEach((key: string) => { + metaFiles.push({ + tag: { S: path.posix.join(buildId, tag) }, + path: { S: path.posix.join(buildId, key) }, + revalidatedAt: { N: `${Date.now()}` }, + }); + }); + }); + } + + // TODO: check if metafiles doesn't contain duplicates + fs.writeFileSync( + path.join(fetchOutputPath, "dynamodb-cache.json"), + JSON.stringify(metaFiles) + ); } } @@ -600,6 +665,8 @@ function addCacheHandler(outputPath: string) { esbuildSync({ external: ["next", "styled-jsx", "react"], entryPoints: [path.join(__dirname, "adapters", "cache.js")], + // We don't need to bundle next + external: ["next"], outfile: path.join(outputPath, "cache.cjs"), target: ["node18"], format: "cjs", @@ -673,17 +740,36 @@ function removeFiles( root: string, conditionFn: (file: string) => boolean, searchingDir: string = "", +) { + traverseFiles( + root, + conditionFn, + (filePath) => fs.rmSync(filePath, { force: true }), + searchingDir + ); +} + +function traverseFiles( + root: string, + conditionFn: (file: string) => boolean, + callbackFn: (filePath: string) => void, + searchingDir: string = "" ) { fs.readdirSync(path.join(root, searchingDir)).forEach((file) => { const filePath = path.join(root, searchingDir, file); if (fs.statSync(filePath).isDirectory()) { - removeFiles(root, conditionFn, path.join(searchingDir, file)); + traverseFiles( + root, + conditionFn, + callbackFn, + path.join(searchingDir, file) + ); return; } if (conditionFn(path.join(searchingDir, file))) { - fs.rmSync(filePath, { force: true }); + callbackFn(filePath); } }); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91beb61b..e4b64dc0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -237,15 +237,18 @@ importers: packages/open-next: dependencies: + '@aws-sdk/client-dynamodb': + specifier: ^3.398.0 + version: 3.398.0 '@aws-sdk/client-lambda': specifier: ^3.398.0 - version: 3.405.0 + version: 3.398.0 '@aws-sdk/client-s3': specifier: ^3.398.0 - version: 3.405.0(@aws-sdk/signature-v4-crt@3.398.0) + version: 3.400.0(@aws-sdk/signature-v4-crt@3.398.0) '@aws-sdk/client-sqs': specifier: ^3.398.0 - version: 3.405.0 + version: 3.398.0 '@esbuild-plugins/node-resolve': specifier: 0.2.2 version: 0.2.2(esbuild@0.18.20) @@ -273,7 +276,7 @@ importers: version: 8.10.119 '@types/node': specifier: ^18.16.1 - version: 18.17.13 + version: 18.17.12 typescript: specifier: ^4.9.3 version: 4.9.3 @@ -291,7 +294,7 @@ importers: version: 2.0.0 ts-node: specifier: 10.9.1 - version: 10.9.1(@types/node@20.5.0)(typescript@4.9.3) + version: 10.9.1(@types/node@18.17.12)(typescript@4.9.3) packages/tests-unit: dependencies: @@ -456,6 +459,9 @@ packages: /@aws-cdk/cloud-assembly-schema@2.84.0: resolution: {integrity: sha512-TLQMexYkev8T1WSevwCibW4Dc9bvm89MUOdv1rJykCg4Vskmmw9WkWBRxW8S4nLgRAsQ0Uw8503sg5FIGjQ7rQ==} engines: {node: '>= 14.15.0'} + dependencies: + jsonschema: 1.4.1 + semver: 7.5.4 dev: true bundledDependencies: - jsonschema @@ -464,6 +470,9 @@ packages: /@aws-cdk/cloud-assembly-schema@2.91.0: resolution: {integrity: sha512-H7pbe7VMnX2siipaT6rVDWjp0p9clrKc+8C+FG+6woqQIuQBuBZxZGVVSNtR0hdtAj7UWFX/CHGS4ihFtJnmIQ==} engines: {node: '>= 14.15.0'} + dependencies: + jsonschema: 1.4.1 + semver: 7.5.4 dev: true bundledDependencies: - jsonschema @@ -500,6 +509,7 @@ packages: '@aws-cdk/cloud-assembly-schema': 2.84.0 dependencies: '@aws-cdk/cloud-assembly-schema': 2.84.0 + semver: 7.5.4 dev: true bundledDependencies: - semver @@ -511,6 +521,7 @@ packages: '@aws-cdk/cloud-assembly-schema': 2.91.0 dependencies: '@aws-cdk/cloud-assembly-schema': 2.91.0 + semver: 7.5.4 dev: true bundledDependencies: - semver @@ -593,14 +604,14 @@ packages: tslib: 1.14.1 dev: true - /@aws-sdk/client-cloudformation@3.405.0: - resolution: {integrity: sha512-7tmE/r0FESVR8N6G6bRsVnAoUxmzv8c6C2oe4I6K9bQT9wHDv/DuFHNSkP28ReIwdr9iA7mzzTUQ6JyeqW/UuA==} + /@aws-sdk/client-cloudformation@3.398.0: + resolution: {integrity: sha512-NQAjm0FYmmMT9jn7y2kYpa5MtANwe2c+65IJATXCJC9YqmDxDveZce6YmOpZ3Qflf7Z1J2A7rYAwo0qO35/Zcg==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -609,7 +620,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -619,7 +630,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -628,8 +639,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 '@smithy/util-waiter': 2.0.5 @@ -640,14 +651,14 @@ packages: - aws-crt dev: true - /@aws-sdk/client-cognito-identity@3.405.0: - resolution: {integrity: sha512-kvmNAREFQbhaZoEMQzBOYTaN7cFIOLgk2DZYYlHh2ErUYXSbvbVOBUriMRW9hRDtKLooe3ZFBLO3sWKvQE/AfA==} + /@aws-sdk/client-cognito-identity@3.398.0: + resolution: {integrity: sha512-Pr/S1f8R2FsJ8DwBC6g0CSdtZNNV5dMHhlIi+t8YAmCJvP4KT+UhzFjbvQRINlBRLFuGUuP7p5vRcGVELD3+wA==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -656,7 +667,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -666,7 +677,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -675,8 +686,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 @@ -684,14 +695,15 @@ packages: - aws-crt dev: true - /@aws-sdk/client-ecs@3.405.0: - resolution: {integrity: sha512-Yhp5ujk5V4iaX8mCkUnco4M3ltnJeLZoB5yY/7C8uCAn91rM+Z2UTHO24zYqO/NIh0PErqkR40K8MwEkI7QqAw==} + /@aws-sdk/client-dynamodb@3.398.0: + resolution: {integrity: sha512-INYklo7u16T0Gia983MqfLdx4feZ96xqowH23+1XSYe4VSersCSfdBM+yeChQ5naTCW0GqFybC9+BytZX5/klw==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 + '@aws-sdk/middleware-endpoint-discovery': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -700,7 +712,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -710,7 +722,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -719,8 +731,54 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 + '@smithy/util-retry': 2.0.0 + '@smithy/util-utf8': 2.0.0 + '@smithy/util-waiter': 2.0.5 + tslib: 2.6.2 + uuid: 8.3.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/client-ecs@3.398.0: + resolution: {integrity: sha512-bjLdxYs9fV6u5qZI5HssZrcrM2pD8JOxqo4ApHTo1ldhwtKiSsrsJv2nJ721bRT0iByDrtgI72EKfGMBysE+lA==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 + '@aws-sdk/middleware-host-header': 3.398.0 + '@aws-sdk/middleware-logger': 3.398.0 + '@aws-sdk/middleware-recursion-detection': 3.398.0 + '@aws-sdk/middleware-signing': 3.398.0 + '@aws-sdk/middleware-user-agent': 3.398.0 + '@aws-sdk/types': 3.398.0 + '@aws-sdk/util-endpoints': 3.398.0 + '@aws-sdk/util-user-agent-browser': 3.398.0 + '@aws-sdk/util-user-agent-node': 3.398.0 + '@smithy/config-resolver': 2.0.5 + '@smithy/fetch-http-handler': 2.0.5 + '@smithy/hash-node': 2.0.5 + '@smithy/invalid-dependency': 2.0.5 + '@smithy/middleware-content-length': 2.0.5 + '@smithy/middleware-endpoint': 2.0.5 + '@smithy/middleware-retry': 2.0.5 + '@smithy/middleware-serde': 2.0.5 + '@smithy/middleware-stack': 2.0.0 + '@smithy/node-config-provider': 2.0.5 + '@smithy/node-http-handler': 2.0.5 + '@smithy/protocol-http': 2.0.5 + '@smithy/smithy-client': 2.0.5 + '@smithy/types': 2.2.2 + '@smithy/url-parser': 2.0.5 + '@smithy/util-base64': 2.0.0 + '@smithy/util-body-length-browser': 2.0.0 + '@smithy/util-body-length-node': 2.1.0 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 '@smithy/util-waiter': 2.0.5 @@ -729,14 +787,14 @@ packages: - aws-crt dev: true - /@aws-sdk/client-eventbridge@3.405.0(@aws-sdk/signature-v4-crt@3.398.0): - resolution: {integrity: sha512-WCWXwFiWDwKFYehfOTmmrXZ2UTx+yPma0935eGGoOLzZ6Vn/IGedPiZOq8We+oqEHm2QFTb/n5gnp1WjnunMGg==} + /@aws-sdk/client-eventbridge@3.398.0(@aws-sdk/signature-v4-crt@3.398.0): + resolution: {integrity: sha512-EmaRYvjdj+OaIjLmOlWjfAqG4hQuhEieJucRXNvdf1FShktDzN23kOHchvzBzn6e+EG5sOWhZx2ID/8YDRAPew==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -746,7 +804,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -756,7 +814,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -765,8 +823,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 @@ -775,14 +833,14 @@ packages: - aws-crt dev: true - /@aws-sdk/client-iam@3.405.0: - resolution: {integrity: sha512-q2sIj1r6yZ6mhZEkSBVpwiwi0dTmDAeSSRBdwq/O8ekpuB4LNRaMuHba4qUEN4Xq9Gaykky7rzArJ5/+iUxVLg==} + /@aws-sdk/client-iam@3.398.0: + resolution: {integrity: sha512-wQEVjrS1f00NxZNCnAzGhn1HLmFlqkMjgCNRskRF2Qz/ppgSsdgUEc/D5msusWKNo+p9e2ixHKB8eATX03kUXQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -791,7 +849,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -801,7 +859,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -810,8 +868,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 '@smithy/util-waiter': 2.0.5 @@ -821,14 +879,14 @@ packages: - aws-crt dev: true - /@aws-sdk/client-iot-data-plane@3.405.0: - resolution: {integrity: sha512-D3KBFk2jEv/OyPUt4j5RGbW0MRmXcnj1nSCMosyY5ft/OVF1cDlpokaSrskjHeVAyUSWyVkcZAFEt7YHw/38IQ==} + /@aws-sdk/client-iot-data-plane@3.398.0: + resolution: {integrity: sha512-aURiQAnz/KVYdXDGN40ND67BiqdIMFpDypXGB7jOqBi+Ih3dO+htQaOPQUmkrB/5/mT1cnVgQvi4PNOiwfK1VQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -837,7 +895,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -847,7 +905,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -856,8 +914,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-stream': 2.0.5 '@smithy/util-utf8': 2.0.0 @@ -866,14 +924,14 @@ packages: - aws-crt dev: true - /@aws-sdk/client-iot@3.405.0: - resolution: {integrity: sha512-dtdRv2+TGvtmrnMbDDLUV3351QZp1fh66xN8Zk9clnDyLMQHjDTgs8RAozG5kM86/oJqlQWTUTo8XJZFcDPG/g==} + /@aws-sdk/client-iot@3.398.0: + resolution: {integrity: sha512-HWBEeRb4yq/6j9kldwFd+Hr31c1DI/a/vw9Kjb2OZwUOjWxcuEWaka4R2OfJ0PzjaKFnfey+2pqMB8WlLEMTxg==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -882,7 +940,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -892,7 +950,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -901,8 +959,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 @@ -911,14 +969,14 @@ packages: - aws-crt dev: true - /@aws-sdk/client-lambda@3.405.0: - resolution: {integrity: sha512-q43LQCllmfIMbA8low6lNIJdD3HxfN08RpB4vIWQhzwHxXrj0GV15pxPQa4SQdzSF6OfKIoW58Z2M/IPYvlQhg==} + /@aws-sdk/client-lambda@3.398.0: + resolution: {integrity: sha512-f++i62vpdh/kUFBx2hWnAJRpb1IOGSqP6+2OP4c7WCpYrrGKleZCRPEZdsDTYnEG1ws987XYfDtal4CVVVL+nw==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -927,7 +985,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/eventstream-serde-browser': 2.0.5 '@smithy/eventstream-serde-config-resolver': 2.0.5 @@ -940,7 +998,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -949,8 +1007,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-stream': 2.0.5 '@smithy/util-utf8': 2.0.0 @@ -959,14 +1017,14 @@ packages: transitivePeerDependencies: - aws-crt - /@aws-sdk/client-rds-data@3.405.0: - resolution: {integrity: sha512-PWfpBqmOzk3dAvweghRU57HhxI65ExFm5sKJk/dsRY4xv2pZif4yFKkGv7BTf0LNXZo0ynuZivfVQYLdjnCFVw==} + /@aws-sdk/client-rds-data@3.398.0: + resolution: {integrity: sha512-RfjHG2vHg5fqjPN1fNQa/hZ/yyEUkkI+THOQh1fW0e4sL4zPJtYG8j5Sc8IynPQFOQXUOppS0lyY+x4FqnYCWQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -975,7 +1033,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -985,7 +1043,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -994,8 +1052,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 @@ -1003,16 +1061,16 @@ packages: - aws-crt dev: true - /@aws-sdk/client-s3@3.405.0(@aws-sdk/signature-v4-crt@3.398.0): - resolution: {integrity: sha512-+LK6OCbKplR51zBZAtK/+RxaPsXcEklsA1+mmUA3M1h4KHl6GMiK5r/D9dlKht5DRntmmjCn3SI99QbfckqKXg==} + /@aws-sdk/client-s3@3.400.0(@aws-sdk/signature-v4-crt@3.398.0): + resolution: {integrity: sha512-lnv0pb79Czl8fCMs/z7yM56LvoKTri1I4jX/V33trHMFKPQDoy8i24wxG8+TZl3MUmnUyoQS7tlukh7IFkii1Q==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha1-browser': 3.0.0 '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 - '@aws-sdk/middleware-bucket-endpoint': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 + '@aws-sdk/middleware-bucket-endpoint': 3.398.0 '@aws-sdk/middleware-expect-continue': 3.398.0 '@aws-sdk/middleware-flexible-checksums': 3.400.0 '@aws-sdk/middleware-host-header': 3.398.0 @@ -1027,7 +1085,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@aws-sdk/xml-builder': 3.310.0 '@smithy/config-resolver': 2.0.5 '@smithy/eventstream-serde-browser': 2.0.5 @@ -1044,7 +1102,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -1053,8 +1111,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-stream': 2.0.5 '@smithy/util-utf8': 2.0.0 @@ -1065,14 +1123,14 @@ packages: - '@aws-sdk/signature-v4-crt' - aws-crt - /@aws-sdk/client-sqs@3.405.0: - resolution: {integrity: sha512-mZ3nKrAK8OntS765pH2kslCpaxtuGIc5TdKcgaFi17p4FD5zP5uzEK1UmUl52Y7YVa1Qpixyzbnzy/lp0J8V/g==} + /@aws-sdk/client-sqs@3.398.0: + resolution: {integrity: sha512-y5+QxwQEYbbrHWuJgGL4BnlgfQO/Jp3cLpd0p/idLccAfWia2TKO15rn6sBvMcpC7/nTPjtii3jPeUn6HkAGHQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -1082,7 +1140,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -1093,7 +1151,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -1102,8 +1160,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 fast-xml-parser: 4.2.5 @@ -1112,14 +1170,14 @@ packages: - aws-crt dev: false - /@aws-sdk/client-ssm@3.405.0: - resolution: {integrity: sha512-e47vcxHBveuPth/MRUOleR2iehV3xftP204nRzDkB5DSnQ28qdXvxWau1lLbTFRX2PzzJZPe5aI7+PZE/s+nwg==} + /@aws-sdk/client-ssm@3.398.0: + resolution: {integrity: sha512-TlcY4wJzGinllmPtmZi7M8lUaXeUWHkpU1N5CFi8/Ef1A2o7Af9tG+1UgY7dFeoPv2pZsYp5Ettw/hRV+dt7fQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -1128,7 +1186,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -1138,7 +1196,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -1147,8 +1205,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 '@smithy/util-waiter': 2.0.5 @@ -1158,8 +1216,8 @@ packages: - aws-crt dev: true - /@aws-sdk/client-sso@3.405.0: - resolution: {integrity: sha512-z1ssydU07bDhe0tNXQwVO+rWh/iSfK48JI8s8vgpBNwH+NejMzIJ9r3AkjCiJ+LSAwlBZItUsNWwR0veIfgBiw==} + /@aws-sdk/client-sso@3.398.0: + resolution: {integrity: sha512-CygL0jhfibw4kmWXG/3sfZMFNjcXo66XUuPC4BqZBk8Rj5vFoxp1vZeMkDLzTIk97Nvo5J5Bh+QnXKhub6AckQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 @@ -1171,7 +1229,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -1181,7 +1239,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -1190,21 +1248,21 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 transitivePeerDependencies: - aws-crt - /@aws-sdk/client-sts@3.405.0: - resolution: {integrity: sha512-asVEpda3zu5QUO5ZNNjbLBS0718IhxxyUDVrNmVTKZoOhK1pMNouGZf+l49v0Lb5cOPbUds8cxsNaInj2MvIKw==} + /@aws-sdk/client-sts@3.398.0: + resolution: {integrity: sha512-/3Pa9wLMvBZipKraq3AtbmTfXW6q9kyvhwOno64f1Fz7kFb8ijQFMGoATS70B2pGEZTlxkUqJFWDiisT6Q6dFg==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/credential-provider-node': 3.405.0 + '@aws-sdk/credential-provider-node': 3.398.0 '@aws-sdk/middleware-host-header': 3.398.0 '@aws-sdk/middleware-logger': 3.398.0 '@aws-sdk/middleware-recursion-detection': 3.398.0 @@ -1214,7 +1272,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -1224,7 +1282,7 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/smithy-client': 2.0.5 @@ -1233,8 +1291,8 @@ packages: '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 fast-xml-parser: 4.2.5 @@ -1251,13 +1309,13 @@ packages: tslib: 2.6.2 dev: true - /@aws-sdk/credential-provider-cognito-identity@3.405.0: - resolution: {integrity: sha512-tmu8r0kB3qHHIitQAwiziWzxoaGCv/vCh00EcabuW3x3UsKQUF71ZLuNcMOv5wqTsQw0Fmv3dKy2tzVmRm3Z5g==} + /@aws-sdk/credential-provider-cognito-identity@3.398.0: + resolution: {integrity: sha512-MFUhy1YayHg5ypRTk4OTfDumQRP+OJBagaGv14kA8DzhKH1sNrU4HV7A7y2J4SvkN5hG/KnLJqxpakCtB2/O2g==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-cognito-identity': 3.405.0 + '@aws-sdk/client-cognito-identity': 3.398.0 '@aws-sdk/types': 3.398.0 - '@smithy/property-provider': 2.0.6 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 transitivePeerDependencies: @@ -1269,64 +1327,64 @@ packages: engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/types': 3.398.0 - '@smithy/property-provider': 2.0.6 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 - /@aws-sdk/credential-provider-ini@3.405.0: - resolution: {integrity: sha512-b4TqVsM4WQM96GDVs+TYOhU2/0SnUWzz6NH55qY1y2xyF8/pZEhc0XXdpvZtQQBLGdROhXCbxhBVye8GmTpgcg==} + /@aws-sdk/credential-provider-ini@3.398.0: + resolution: {integrity: sha512-AsK1lStK3nB9Cn6S6ODb1ktGh7SRejsNVQVKX3t5d3tgOaX+aX1Iwy8FzM/ZEN8uCloeRifUGIY9uQFygg5mSw==} engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/credential-provider-env': 3.398.0 - '@aws-sdk/credential-provider-process': 3.405.0 - '@aws-sdk/credential-provider-sso': 3.405.0 + '@aws-sdk/credential-provider-process': 3.398.0 + '@aws-sdk/credential-provider-sso': 3.398.0 '@aws-sdk/credential-provider-web-identity': 3.398.0 '@aws-sdk/types': 3.398.0 - '@smithy/credential-provider-imds': 2.0.7 - '@smithy/property-provider': 2.0.6 - '@smithy/shared-ini-file-loader': 2.0.6 + '@smithy/credential-provider-imds': 2.0.5 + '@smithy/property-provider': 2.0.5 + '@smithy/shared-ini-file-loader': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 transitivePeerDependencies: - aws-crt - /@aws-sdk/credential-provider-node@3.405.0: - resolution: {integrity: sha512-AMmRP09nwYsft0MXDlHIxMQe7IloWW8As0lbZmPrG7Y7mK5RDmCIwD2yMDz77Zqlv09FsYt+9+cOK2fTNhim+Q==} + /@aws-sdk/credential-provider-node@3.398.0: + resolution: {integrity: sha512-odmI/DSKfuWUYeDnGTCEHBbC8/MwnF6yEq874zl6+owoVv0ZsYP8qBHfiJkYqrwg7wQ7Pi40sSAPC1rhesGwzg==} engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/credential-provider-env': 3.398.0 - '@aws-sdk/credential-provider-ini': 3.405.0 - '@aws-sdk/credential-provider-process': 3.405.0 - '@aws-sdk/credential-provider-sso': 3.405.0 + '@aws-sdk/credential-provider-ini': 3.398.0 + '@aws-sdk/credential-provider-process': 3.398.0 + '@aws-sdk/credential-provider-sso': 3.398.0 '@aws-sdk/credential-provider-web-identity': 3.398.0 '@aws-sdk/types': 3.398.0 - '@smithy/credential-provider-imds': 2.0.7 - '@smithy/property-provider': 2.0.6 - '@smithy/shared-ini-file-loader': 2.0.6 + '@smithy/credential-provider-imds': 2.0.5 + '@smithy/property-provider': 2.0.5 + '@smithy/shared-ini-file-loader': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 transitivePeerDependencies: - aws-crt - /@aws-sdk/credential-provider-process@3.405.0: - resolution: {integrity: sha512-EqAMcUVeZAICYHHL8x5Fi5CYPgCo9UCE7ScWmU5Sa2wAFY4XLyQ1mMxX3lKGYx9lBxWk3dqnhmvlcqdzN7AjyQ==} + /@aws-sdk/credential-provider-process@3.398.0: + resolution: {integrity: sha512-WrkBL1W7TXN508PA9wRXPFtzmGpVSW98gDaHEaa8GolAPHMPa5t2QcC/z/cFpglzrcVv8SA277zu9Z8tELdZhg==} engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/types': 3.398.0 - '@smithy/property-provider': 2.0.6 - '@smithy/shared-ini-file-loader': 2.0.6 + '@smithy/property-provider': 2.0.5 + '@smithy/shared-ini-file-loader': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 - /@aws-sdk/credential-provider-sso@3.405.0: - resolution: {integrity: sha512-fXqSgQHz7qcmIWMVguwSMSjqFkVfN2+XiNgiskcmeYiCS7mIGAgUnKABZc9Ds2+YW9ATYiY0BOD5aWxc8TX5fA==} + /@aws-sdk/credential-provider-sso@3.398.0: + resolution: {integrity: sha512-2Dl35587xbnzR/GGZqA2MnFs8+kS4wbHQO9BioU0okA+8NRueohNMdrdQmQDdSNK4BfIpFspiZmFkXFNyEAfgw==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-sso': 3.405.0 - '@aws-sdk/token-providers': 3.405.0 + '@aws-sdk/client-sso': 3.398.0 + '@aws-sdk/token-providers': 3.398.0 '@aws-sdk/types': 3.398.0 - '@smithy/property-provider': 2.0.6 - '@smithy/shared-ini-file-loader': 2.0.6 + '@smithy/property-provider': 2.0.5 + '@smithy/shared-ini-file-loader': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 transitivePeerDependencies: @@ -1337,35 +1395,43 @@ packages: engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/types': 3.398.0 - '@smithy/property-provider': 2.0.6 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 - /@aws-sdk/credential-providers@3.405.0: - resolution: {integrity: sha512-332QZ2Wrr5gfFUGPLwITcjhxnBD4y94fxKg7qerSBq7fjjIkl/OjnchZf5ReePrjpglxs6hgLdGrPYIYPC4Hhw==} + /@aws-sdk/credential-providers@3.398.0: + resolution: {integrity: sha512-355vXmImn2e85mIWSYDVb101AF2lIVHKNCaH6sV1U/8i0ZOXh2cJYNdkRYrxNt1ezDB0k97lSKvuDx7RDvJyRg==} engines: {node: '>=14.0.0'} dependencies: - '@aws-sdk/client-cognito-identity': 3.405.0 - '@aws-sdk/client-sso': 3.405.0 - '@aws-sdk/client-sts': 3.405.0 - '@aws-sdk/credential-provider-cognito-identity': 3.405.0 + '@aws-sdk/client-cognito-identity': 3.398.0 + '@aws-sdk/client-sso': 3.398.0 + '@aws-sdk/client-sts': 3.398.0 + '@aws-sdk/credential-provider-cognito-identity': 3.398.0 '@aws-sdk/credential-provider-env': 3.398.0 - '@aws-sdk/credential-provider-ini': 3.405.0 - '@aws-sdk/credential-provider-node': 3.405.0 - '@aws-sdk/credential-provider-process': 3.405.0 - '@aws-sdk/credential-provider-sso': 3.405.0 + '@aws-sdk/credential-provider-ini': 3.398.0 + '@aws-sdk/credential-provider-node': 3.398.0 + '@aws-sdk/credential-provider-process': 3.398.0 + '@aws-sdk/credential-provider-sso': 3.398.0 '@aws-sdk/credential-provider-web-identity': 3.398.0 '@aws-sdk/types': 3.398.0 - '@smithy/credential-provider-imds': 2.0.7 - '@smithy/property-provider': 2.0.6 + '@smithy/credential-provider-imds': 2.0.5 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 transitivePeerDependencies: - aws-crt dev: true - /@aws-sdk/middleware-bucket-endpoint@3.405.0: - resolution: {integrity: sha512-wKmHZi44NkbaGXXbMwassUm06/wDtSYucPbM4paU2cMbBUOnwFpndHWlrRYCNmj5Ty5A2HjdkGlhgla8nifHzQ==} + /@aws-sdk/endpoint-cache@3.310.0: + resolution: {integrity: sha512-y3wipforet41EDTI0vnzxILqwAGll1KfI5qcdX9pXF/WF1f+3frcOtPiWtQEZQpy4czRogKm3BHo70QBYAZxlQ==} + engines: {node: '>=14.0.0'} + dependencies: + mnemonist: 0.38.3 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-bucket-endpoint@3.398.0: + resolution: {integrity: sha512-+iDHiRofK/vIY94RWAXkSnR4rBPzc2dPHmLp+FDKywq1y708H9W7TOT37dpn+KSFeO4k2FfddFjzWBHsaeakCA==} engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/types': 3.398.0 @@ -1375,6 +1441,17 @@ packages: '@smithy/util-config-provider': 2.0.0 tslib: 2.6.2 + /@aws-sdk/middleware-endpoint-discovery@3.398.0: + resolution: {integrity: sha512-Gf5HPhgCbTwPkoYlp50DnQRATljaTW3S9og7E+PrIIXdsTPGeZrlVFausreFhTXy3UOVP/3iGG3ajBQl84yNtw==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/endpoint-cache': 3.310.0 + '@aws-sdk/types': 3.398.0 + '@smithy/protocol-http': 2.0.5 + '@smithy/types': 2.2.2 + tslib: 2.6.2 + dev: false + /@aws-sdk/middleware-expect-continue@3.398.0: resolution: {integrity: sha512-d6he+Qqwh1yqml9duXSv5iKJ2lS0PVrF2UEsVew2GFxfUif0E/davTZJjvWtnelbuIGcTP+wDKVVjLwBN2sN/g==} engines: {node: '>=14.0.0'} @@ -1476,7 +1553,7 @@ packages: engines: {node: '>=14.0.0'} dependencies: '@aws-sdk/types': 3.398.0 - '@smithy/property-provider': 2.0.6 + '@smithy/property-provider': 2.0.5 '@smithy/protocol-http': 2.0.5 '@smithy/signature-v4': 2.0.5 '@smithy/types': 2.2.2 @@ -1541,8 +1618,8 @@ packages: tslib: 2.6.2 dev: true - /@aws-sdk/token-providers@3.405.0: - resolution: {integrity: sha512-rVzC7ptf7TlV84M9w+Ds9isio1EY7bs1MRFv/6lmYstsyTri+DaZG10TwXSGfzIMwB0yVh11niCxO9wSjQ36zg==} + /@aws-sdk/token-providers@3.398.0: + resolution: {integrity: sha512-nrYgjzavGCKJL/48Vt0EL+OlIc5UZLfNGpgyUW9cv3XZwl+kXV0QB+HH0rHZZLfpbBgZ2RBIJR9uD5ieu/6hpQ==} engines: {node: '>=14.0.0'} dependencies: '@aws-crypto/sha256-browser': 3.0.0 @@ -1554,7 +1631,7 @@ packages: '@aws-sdk/types': 3.398.0 '@aws-sdk/util-endpoints': 3.398.0 '@aws-sdk/util-user-agent-browser': 3.398.0 - '@aws-sdk/util-user-agent-node': 3.405.0 + '@aws-sdk/util-user-agent-node': 3.398.0 '@smithy/config-resolver': 2.0.5 '@smithy/fetch-http-handler': 2.0.5 '@smithy/hash-node': 2.0.5 @@ -1564,19 +1641,19 @@ packages: '@smithy/middleware-retry': 2.0.5 '@smithy/middleware-serde': 2.0.5 '@smithy/middleware-stack': 2.0.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/node-http-handler': 2.0.5 - '@smithy/property-provider': 2.0.6 + '@smithy/property-provider': 2.0.5 '@smithy/protocol-http': 2.0.5 - '@smithy/shared-ini-file-loader': 2.0.6 + '@smithy/shared-ini-file-loader': 2.0.5 '@smithy/smithy-client': 2.0.5 '@smithy/types': 2.2.2 '@smithy/url-parser': 2.0.5 '@smithy/util-base64': 2.0.0 '@smithy/util-body-length-browser': 2.0.0 '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.6 - '@smithy/util-defaults-mode-node': 2.0.7 + '@smithy/util-defaults-mode-browser': 2.0.5 + '@smithy/util-defaults-mode-node': 2.0.5 '@smithy/util-retry': 2.0.0 '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 @@ -1617,8 +1694,8 @@ packages: bowser: 2.11.0 tslib: 2.6.2 - /@aws-sdk/util-user-agent-node@3.405.0: - resolution: {integrity: sha512-6Ssld7aalKCnW6lSGfiiWpqwo2L+AmYq2oV3P9yYAo9ZL+Q78dXquabwj3uq3plJ4l2xE4Gfcf2FJ/1PZpqDvQ==} + /@aws-sdk/util-user-agent-node@3.398.0: + resolution: {integrity: sha512-RTVQofdj961ej4//fEkppFf4KXqKGMTCqJYghx3G0C/MYXbg7MGl7LjfNGtJcboRE8pfHHQ/TUWBDA7RIAPPlQ==} engines: {node: '>=14.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1627,7 +1704,7 @@ packages: optional: true dependencies: '@aws-sdk/types': 3.398.0 - '@smithy/node-config-provider': 2.0.7 + '@smithy/node-config-provider': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 @@ -1833,6 +1910,10 @@ packages: '@babel/helper-validator-identifier': 7.22.5 to-fast-properties: 2.0.0 + /@balena/dockerignore@1.0.2: + resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} + dev: true + /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true @@ -3281,12 +3362,12 @@ packages: '@smithy/util-middleware': 2.0.0 tslib: 2.6.2 - /@smithy/credential-provider-imds@2.0.7: - resolution: {integrity: sha512-XivkZj/pipzpQPxgleE1odwJQ6oDsVViB4VUO/HRDI4EdEfZjud44USupOUOa/xOjS39/75DYB4zgTbyV+totw==} + /@smithy/credential-provider-imds@2.0.5: + resolution: {integrity: sha512-KFcf/e0meFkQNyteJ65f1G19sgUEY1e5zL7hyAEUPz2SEfBmC9B37WyRq87G3MEEsvmAWwCRu7nFFYUKtR3svQ==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/node-config-provider': 2.0.7 - '@smithy/property-provider': 2.0.6 + '@smithy/node-config-provider': 2.0.5 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 '@smithy/url-parser': 2.0.5 tslib: 2.6.2 @@ -3463,12 +3544,12 @@ packages: dependencies: tslib: 2.6.2 - /@smithy/node-config-provider@2.0.7: - resolution: {integrity: sha512-GuLxhnf0aVQsfQp4ZWaM1TRCIndpQjAswyFcmDFRNf4yFqpxpLPDeV540+O0Z21Hmu3deoQm/dCPXbVn90PYzg==} + /@smithy/node-config-provider@2.0.5: + resolution: {integrity: sha512-LRtjV9WkhONe2lVy+ipB/l1GX60ybzBmFyeRUoLUXWKdnZ3o81jsnbKzMK8hKq8eFSWPk+Lmyx6ZzCQabGeLxg==} engines: {node: '>=14.0.0'} dependencies: - '@smithy/property-provider': 2.0.6 - '@smithy/shared-ini-file-loader': 2.0.6 + '@smithy/property-provider': 2.0.5 + '@smithy/shared-ini-file-loader': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 @@ -3493,8 +3574,8 @@ packages: '@smithy/types': 2.2.2 tslib: 2.6.2 - /@smithy/property-provider@2.0.6: - resolution: {integrity: sha512-CVem6ZkkWxbTnhjDLyLESY0oLA6IUZYtdqrCpGQKUXaFBOuc/izjm7fIFGBxEbjZ1EGcH9hHxrjqX36RWULNRg==} + /@smithy/property-provider@2.0.5: + resolution: {integrity: sha512-cAFSUhX6aiHcmpWfrCLKvwBtgN1F6A0N8qY/8yeSi0LRLmhGqsY1/YTxFE185MCVzYbqBGXVr9TBv4RUcIV4rA==} engines: {node: '>=14.0.0'} dependencies: '@smithy/types': 2.2.2 @@ -3548,8 +3629,8 @@ packages: resolution: {integrity: sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==} engines: {node: '>=14.0.0'} - /@smithy/shared-ini-file-loader@2.0.6: - resolution: {integrity: sha512-NO6dHqho6APbVR0DxPtYoL4KXBqUeSM3Slsd103MOgL50YbzzsQmMLtDMZ87W8MlvvCN0tuiq+OrAO/rM7hTQg==} + /@smithy/shared-ini-file-loader@2.0.5: + resolution: {integrity: sha512-Mvtk6FwMtfbKRC4YuSsIqRYp9WTxsSUJVVo2djgyhcacKGMqicHDWSAmgy3sDrKv+G/G6xTZCPwm6pJARtdxVg==} engines: {node: '>=14.0.0'} dependencies: '@smithy/types': 2.2.2 @@ -3661,23 +3742,23 @@ packages: dependencies: tslib: 2.6.2 - /@smithy/util-defaults-mode-browser@2.0.6: - resolution: {integrity: sha512-h8xyKTZIIom62DN4xbPUmL+RL1deZcK1qJGmCr4c2yXjOrs5/iZ1VtQQcl+xP78620ga/565AikZE1sktdg2yA==} + /@smithy/util-defaults-mode-browser@2.0.5: + resolution: {integrity: sha512-yciP6TPttLsj731aHTvekgyuCGXQrEAJibEwEWAh3kzaDsfGAVCuZSBlyvC2Dl3TZmHKCOQwHV8mIE7KQCTPuQ==} engines: {node: '>= 10.0.0'} dependencies: - '@smithy/property-provider': 2.0.6 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 bowser: 2.11.0 tslib: 2.6.2 - /@smithy/util-defaults-mode-node@2.0.7: - resolution: {integrity: sha512-2C1YfmYJj9bpM/cRAgQppYNzPd8gDEXZ5XIVDuEQg3TmmIiinZaFf/HsHYo9NK/PMy5oawJVdIuR7SVriIo1AQ==} + /@smithy/util-defaults-mode-node@2.0.5: + resolution: {integrity: sha512-M07t99rWasXt+IaDZDyP3BkcoEm/mgIE1RIMASrE49LKSNxaVN7PVcgGc77+4uu2kzBAyqJKy79pgtezuknyjQ==} engines: {node: '>= 10.0.0'} dependencies: '@smithy/config-resolver': 2.0.5 - '@smithy/credential-provider-imds': 2.0.7 - '@smithy/node-config-provider': 2.0.7 - '@smithy/property-provider': 2.0.6 + '@smithy/credential-provider-imds': 2.0.5 + '@smithy/node-config-provider': 2.0.5 + '@smithy/property-provider': 2.0.5 '@smithy/types': 2.2.2 tslib: 2.6.2 @@ -3891,9 +3972,8 @@ packages: resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} dev: false - /@types/node@18.17.13: - resolution: {integrity: sha512-SlLPDDe6YQl1JnQQy4hgsuJeo5q5c1TBU4be4jeBLXsqpjoDbfb0HesSfhMwnaxfSJ4txtfzJzW5/x/43fkkfQ==} - dev: true + /@types/node@18.17.12: + resolution: {integrity: sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ==} /@types/node@20.5.0: resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} @@ -3959,7 +4039,7 @@ packages: /@types/ws@8.5.5: resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} dependencies: - '@types/node': 20.5.0 + '@types/node': 18.17.12 /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} @@ -4533,7 +4613,7 @@ packages: dependencies: browserslist: 4.21.10 caniuse-lite: 1.0.30001525 - fraction.js: 4.3.6 + fraction.js: 4.3.4 normalize-range: 0.1.2 picocolors: 1.0.0 postcss: 8.4.27 @@ -4553,7 +4633,17 @@ packages: '@aws-cdk/asset-awscli-v1': 2.2.200 '@aws-cdk/asset-kubectl-v20': 2.1.2 '@aws-cdk/asset-node-proxy-agent-v5': 2.0.166 + '@balena/dockerignore': 1.0.2 + case: 1.6.3 constructs: 10.1.156 + fs-extra: 11.1.1 + ignore: 5.2.4 + jsonschema: 1.4.1 + minimatch: 3.1.2 + punycode: 2.3.0 + semver: 7.5.4 + table: 6.8.1 + yaml: 1.10.2 dev: true bundledDependencies: - '@balena/dockerignore' @@ -4576,7 +4666,17 @@ packages: '@aws-cdk/asset-awscli-v1': 2.2.200 '@aws-cdk/asset-kubectl-v20': 2.1.2 '@aws-cdk/asset-node-proxy-agent-v5': 2.0.166 + '@balena/dockerignore': 1.0.2 + case: 1.6.3 constructs: 10.2.69 + fs-extra: 11.1.1 + ignore: 5.2.4 + jsonschema: 1.4.1 + minimatch: 3.1.2 + punycode: 2.3.0 + semver: 7.5.4 + table: 6.8.1 + yaml: 1.10.2 dev: true bundledDependencies: - '@balena/dockerignore' @@ -4621,8 +4721,8 @@ packages: - utf-8-validate dev: true - /aws-sdk@2.1450.0: - resolution: {integrity: sha512-EfZLImJ0XNuIdlx5McHX0rJbOiQHz+vEjnpGV08gXSzaq2cN3vSjE+L2Dju7KmaIh85FTYvLOf2REUuCLDpSRg==} + /aws-sdk@2.1448.0: + resolution: {integrity: sha512-15r8YKdAAXLgtPfQTAzD/qNxxgndF1SMEw6F+mXvLxZrLkG4BHnzOW2g2sQc3C2qG5yqCb3K6R+OrjbvGOAmdQ==} engines: {node: '>= 10.0.0'} dependencies: buffer: 4.9.2 @@ -4772,7 +4872,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001525 - electron-to-chromium: 1.4.508 + electron-to-chromium: 1.4.506 node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.10) @@ -4787,7 +4887,7 @@ packages: resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} dependencies: base64-js: 1.5.1 - ieee754: 1.1.13 + ieee754: 1.2.1 isarray: 1.0.0 dev: true @@ -4874,6 +4974,11 @@ packages: /caniuse-lite@1.0.30001525: resolution: {integrity: sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==} + /case@1.6.3: + resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} + engines: {node: '>= 0.8.0'} + dev: true + /ccount@1.1.0: resolution: {integrity: sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==} dev: false @@ -4886,7 +4991,7 @@ packages: '@aws-cdk/cloud-assembly-schema': 2.84.0 '@aws-cdk/cx-api': 2.84.0(@aws-cdk/cloud-assembly-schema@2.84.0) archiver: 5.3.2 - aws-sdk: 2.1450.0 + aws-sdk: 2.1448.0 glob: 7.2.3 mime: 2.6.0 yargs: 16.2.0 @@ -4900,7 +5005,7 @@ packages: '@aws-cdk/cloud-assembly-schema': 2.91.0 '@aws-cdk/cx-api': 2.91.0(@aws-cdk/cloud-assembly-schema@2.91.0) archiver: 5.3.2 - aws-sdk: 2.1450.0 + aws-sdk: 2.1448.0 glob: 7.2.3 mime: 2.6.0 yargs: 16.2.0 @@ -5104,7 +5209,7 @@ packages: resolution: {integrity: sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==} dependencies: leven: 2.1.0 - minimist: 1.2.6 + minimist: 1.2.8 /compress-commons@4.1.1: resolution: {integrity: sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==} @@ -5532,8 +5637,8 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: true - /electron-to-chromium@1.4.508: - resolution: {integrity: sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==} + /electron-to-chromium@1.4.506: + resolution: {integrity: sha512-xxGct4GPAKSRlrLBtJxJFYy74W11zX6PO9GyHgl/U+2s3Dp0ZEwAklDfNHXOWcvH7zWMpsmgbR0ggEuaYAVvHA==} /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -6429,8 +6534,8 @@ packages: engines: {node: '>= 0.6'} dev: true - /fraction.js@4.3.6: - resolution: {integrity: sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==} + /fraction.js@4.3.4: + resolution: {integrity: sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==} /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} @@ -6445,6 +6550,15 @@ packages: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: true + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -6924,7 +7038,7 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - /ink-spinner@5.0.0(ink@4.4.0)(react@18.2.0): + /ink-spinner@5.0.0(ink@4.3.1)(react@18.2.0): resolution: {integrity: sha512-EYEasbEjkqLGyPOUc8hBJZNuC5GvXGMLu0w5gdTNskPc7Izc5vO3tdQEYnzvshucyGCBXc86ig0ujXPMWaQCdA==} engines: {node: '>=14.16'} peerDependencies: @@ -6932,12 +7046,12 @@ packages: react: '>=18.0.0' dependencies: cli-spinners: 2.9.0 - ink: 4.4.0(react@18.2.0) + ink: 4.3.1(react@18.2.0) react: 18.2.0 dev: true - /ink@4.4.0(react@18.2.0): - resolution: {integrity: sha512-WEUkpgW6b/0yu30xYKNTxkpF90SzoTCzo0o96XEWZXQG+RmmadYC0nWgzmK0jy9pcsIDs1dqUBa+ihcJu1kfKQ==} + /ink@4.3.1(react@18.2.0): + resolution: {integrity: sha512-XlH5AiZRLIC4cF+eMgZLsB/feHCDT7lUtHXK4pe8ULGrC6mNosrYidzJr8CRY0P+hK7UmZ1rLO+ufdox53+NQg==} engines: {node: '>=14.16'} peerDependencies: '@types/react': '>=18.0.0' @@ -7423,8 +7537,8 @@ packages: engines: {node: '>= 0.6.0'} dev: true - /joi@17.10.1: - resolution: {integrity: sha512-vIiDxQKmRidUVp8KngT8MZSOcmRVm2zV7jbMjNYWuHcJWI0bUck3nRTGQjhpPlQenIQIBC5Vp9AhcnHbWQqafw==} + /joi@17.10.0: + resolution: {integrity: sha512-hrazgRSlhzacZ69LdcKfhi3Vu13z2yFfoAzmEov3yFIJlatTdVGUW6vle1zjH8qkzdCn/qGw8rapjqsObbYXAg==} dependencies: '@hapi/hoek': 9.3.0 '@hapi/topo': 5.1.0 @@ -7558,6 +7672,10 @@ packages: graceful-fs: 4.2.11 dev: true + /jsonschema@1.4.1: + resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} + dev: true + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -7629,23 +7747,23 @@ packages: minimist: 1.2.8 dev: true - /kysely-data-api@0.2.1(@aws-sdk/client-rds-data@3.405.0)(kysely@0.23.5): + /kysely-data-api@0.2.1(@aws-sdk/client-rds-data@3.398.0)(kysely@0.23.5): resolution: {integrity: sha512-KmASvF1gmjVqyU9WOUXhCQlv29ofR+xc2DhjaIomz1+Bjd/VtR2/3g4ZuXwG1L4lWGKxMuo5iOvK3XyPbB4LdQ==} peerDependencies: '@aws-sdk/client-rds-data': 3.x kysely: 0.x dependencies: - '@aws-sdk/client-rds-data': 3.405.0 + '@aws-sdk/client-rds-data': 3.398.0 kysely: 0.23.5 dev: true - /kysely-data-api@0.2.1(@aws-sdk/client-rds-data@3.405.0)(kysely@0.25.0): + /kysely-data-api@0.2.1(@aws-sdk/client-rds-data@3.398.0)(kysely@0.25.0): resolution: {integrity: sha512-KmASvF1gmjVqyU9WOUXhCQlv29ofR+xc2DhjaIomz1+Bjd/VtR2/3g4ZuXwG1L4lWGKxMuo5iOvK3XyPbB4LdQ==} peerDependencies: '@aws-sdk/client-rds-data': 3.x kysely: 0.x dependencies: - '@aws-sdk/client-rds-data': 3.405.0 + '@aws-sdk/client-rds-data': 3.398.0 kysely: 0.25.0 dev: true @@ -8064,6 +8182,7 @@ packages: /minimist@1.2.6: resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -8098,6 +8217,12 @@ packages: ufo: 1.3.0 dev: true + /mnemonist@0.38.3: + resolution: {integrity: sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==} + dependencies: + obliterator: 1.6.1 + dev: false + /mnemonist@0.39.5: resolution: {integrity: sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==} dependencies: @@ -8124,7 +8249,7 @@ packages: duplexify: 4.1.2 help-me: 3.0.0 inherits: 2.0.4 - minimist: 1.2.6 + minimist: 1.2.8 mqtt-packet: 6.10.0 pump: 3.0.0 readable-stream: 3.6.2 @@ -8445,6 +8570,10 @@ packages: es-abstract: 1.22.1 dev: true + /obliterator@1.6.1: + resolution: {integrity: sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==} + dev: false + /obliterator@2.0.4: resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} dev: true @@ -9178,8 +9307,8 @@ packages: - supports-color dev: false - /remeda@1.26.0: - resolution: {integrity: sha512-v+Qbi2krvXknCvG60gviLUSBJQPxXUVBAvi64m3Awoua3X+ygAmPYPrbFgqwPpiM1tBHNBVrHPBKtza7if+HyQ==} + /remeda@1.25.2: + resolution: {integrity: sha512-rWYb4nTgOrgWfOJb7q2JFa/925M6XXf+wJ2n4T1ItviVPjyzqpSW+Qt6t9N/Qbciw9McNCqsgV4/gzJGfwhB5w==} dev: true /repeat-string@1.6.1: @@ -9591,18 +9720,18 @@ packages: '@aws-cdk/cloud-assembly-schema': 2.84.0 '@aws-cdk/cloudformation-diff': 2.84.0 '@aws-cdk/cx-api': 2.84.0(@aws-cdk/cloud-assembly-schema@2.84.0) - '@aws-sdk/client-cloudformation': 3.405.0 - '@aws-sdk/client-eventbridge': 3.405.0(@aws-sdk/signature-v4-crt@3.398.0) - '@aws-sdk/client-iam': 3.405.0 - '@aws-sdk/client-iot': 3.405.0 - '@aws-sdk/client-iot-data-plane': 3.405.0 - '@aws-sdk/client-lambda': 3.405.0 - '@aws-sdk/client-rds-data': 3.405.0 - '@aws-sdk/client-s3': 3.405.0(@aws-sdk/signature-v4-crt@3.398.0) - '@aws-sdk/client-ssm': 3.405.0 - '@aws-sdk/client-sts': 3.405.0 + '@aws-sdk/client-cloudformation': 3.398.0 + '@aws-sdk/client-eventbridge': 3.398.0(@aws-sdk/signature-v4-crt@3.398.0) + '@aws-sdk/client-iam': 3.398.0 + '@aws-sdk/client-iot': 3.398.0 + '@aws-sdk/client-iot-data-plane': 3.398.0 + '@aws-sdk/client-lambda': 3.398.0 + '@aws-sdk/client-rds-data': 3.398.0 + '@aws-sdk/client-s3': 3.400.0(@aws-sdk/signature-v4-crt@3.398.0) + '@aws-sdk/client-ssm': 3.398.0 + '@aws-sdk/client-sts': 3.398.0 '@aws-sdk/config-resolver': 3.374.0 - '@aws-sdk/credential-providers': 3.405.0 + '@aws-sdk/credential-providers': 3.398.0 '@aws-sdk/middleware-retry': 3.374.0 '@aws-sdk/middleware-signing': 3.398.0 '@aws-sdk/signature-v4-crt': 3.398.0 @@ -9614,7 +9743,7 @@ packages: adm-zip: 0.5.10 aws-cdk-lib: 2.84.0(constructs@10.1.156) aws-iot-device-sdk: 2.2.12 - aws-sdk: 2.1450.0 + aws-sdk: 2.1448.0 builtin-modules: 3.2.0 cdk-assets: 2.84.0 chalk: 5.3.0 @@ -9634,16 +9763,16 @@ packages: graphql: 16.8.0 graphql-yoga: 3.9.1(graphql@16.8.0) immer: 9.0.21 - ink: 4.4.0(react@18.2.0) - ink-spinner: 5.0.0(ink@4.4.0)(react@18.2.0) + ink: 4.3.1(react@18.2.0) + ink-spinner: 5.0.0(ink@4.3.1)(react@18.2.0) kysely: 0.23.5 kysely-codegen: 0.10.1(kysely@0.23.5) - kysely-data-api: 0.2.1(@aws-sdk/client-rds-data@3.405.0)(kysely@0.23.5) + kysely-data-api: 0.2.1(@aws-sdk/client-rds-data@3.398.0)(kysely@0.23.5) minimatch: 6.2.0 openid-client: 5.4.3 ora: 6.3.1 react: 18.2.0 - remeda: 1.26.0 + remeda: 1.25.2 sst-aws-cdk: 2.84.0 tree-kill: 1.2.2 undici: 5.23.0 @@ -9680,19 +9809,19 @@ packages: '@aws-cdk/cloudformation-diff': 2.91.0 '@aws-cdk/cx-api': 2.91.0(@aws-cdk/cloud-assembly-schema@2.91.0) '@aws-crypto/sha256-js': 5.0.0 - '@aws-sdk/client-cloudformation': 3.405.0 - '@aws-sdk/client-ecs': 3.405.0 - '@aws-sdk/client-eventbridge': 3.405.0(@aws-sdk/signature-v4-crt@3.398.0) - '@aws-sdk/client-iam': 3.405.0 - '@aws-sdk/client-iot': 3.405.0 - '@aws-sdk/client-iot-data-plane': 3.405.0 - '@aws-sdk/client-lambda': 3.405.0 - '@aws-sdk/client-rds-data': 3.405.0 - '@aws-sdk/client-s3': 3.405.0(@aws-sdk/signature-v4-crt@3.398.0) - '@aws-sdk/client-ssm': 3.405.0 - '@aws-sdk/client-sts': 3.405.0 + '@aws-sdk/client-cloudformation': 3.398.0 + '@aws-sdk/client-ecs': 3.398.0 + '@aws-sdk/client-eventbridge': 3.398.0(@aws-sdk/signature-v4-crt@3.398.0) + '@aws-sdk/client-iam': 3.398.0 + '@aws-sdk/client-iot': 3.398.0 + '@aws-sdk/client-iot-data-plane': 3.398.0 + '@aws-sdk/client-lambda': 3.398.0 + '@aws-sdk/client-rds-data': 3.398.0 + '@aws-sdk/client-s3': 3.400.0(@aws-sdk/signature-v4-crt@3.398.0) + '@aws-sdk/client-ssm': 3.398.0 + '@aws-sdk/client-sts': 3.398.0 '@aws-sdk/config-resolver': 3.374.0 - '@aws-sdk/credential-providers': 3.405.0 + '@aws-sdk/credential-providers': 3.398.0 '@aws-sdk/middleware-retry': 3.374.0 '@aws-sdk/middleware-signing': 3.398.0 '@aws-sdk/signature-v4-crt': 3.398.0 @@ -9705,7 +9834,7 @@ packages: adm-zip: 0.5.10 aws-cdk-lib: 2.91.0(constructs@10.2.69) aws-iot-device-sdk: 2.2.12 - aws-sdk: 2.1450.0 + aws-sdk: 2.1448.0 builtin-modules: 3.2.0 cdk-assets: 2.91.0 chalk: 5.3.0 @@ -9725,16 +9854,16 @@ packages: graphql: 16.8.0 graphql-yoga: 3.9.1(graphql@16.8.0) immer: 9.0.21 - ink: 4.4.0(react@18.2.0) - ink-spinner: 5.0.0(ink@4.4.0)(react@18.2.0) + ink: 4.3.1(react@18.2.0) + ink-spinner: 5.0.0(ink@4.3.1)(react@18.2.0) kysely: 0.25.0 kysely-codegen: 0.10.1(kysely@0.25.0) - kysely-data-api: 0.2.1(@aws-sdk/client-rds-data@3.405.0)(kysely@0.25.0) + kysely-data-api: 0.2.1(@aws-sdk/client-rds-data@3.398.0)(kysely@0.25.0) minimatch: 6.2.0 openid-client: 5.4.3 ora: 6.3.1 react: 18.2.0 - remeda: 1.26.0 + remeda: 1.25.2 sst-aws-cdk: 2.91.0 tree-kill: 1.2.2 undici: 5.23.0 @@ -10210,7 +10339,7 @@ packages: /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - /ts-node@10.9.1(@types/node@20.5.0)(typescript@4.9.3): + /ts-node@10.9.1(@types/node@18.17.12)(typescript@4.9.3): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -10229,7 +10358,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.5.0 + '@types/node': 18.17.12 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -10810,7 +10939,7 @@ packages: hasBin: true dependencies: axios: 0.27.2(debug@4.3.4) - joi: 17.10.1 + joi: 17.10.0 lodash: 4.17.21 minimist: 1.2.8 rxjs: 7.8.1 From d5cc5724a8121c00310f89e2662dd3ee2408ec33 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Mon, 14 Aug 2023 09:51:32 +0200 Subject: [PATCH 02/13] fix: do not override tags on page set --- packages/open-next/src/adapters/cache.ts | 36 ++++++++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/open-next/src/adapters/cache.ts b/packages/open-next/src/adapters/cache.ts index d3acad41..973aed2b 100644 --- a/packages/open-next/src/adapters/cache.ts +++ b/packages/open-next/src/adapters/cache.ts @@ -269,13 +269,13 @@ export default class S3Cache { ? getDerivedTags(data.headers?.["x-next-cache-tags"]?.split(",") ?? []) : []; debug("derivedTags", derivedTags); - if (derivedTags.length > 0) { - // Maybe we should not override the tag revalidateAt if it is already set - // With our current implementation it should not matter, every time we update the cache - // it is because of a revalidation and every ISR is considered as on demand revalidation - // so effectively skipping the fetch cache + // Get all tags stored in dynamodb for the given key + // If any of the derived tags are not stored in dynamodb for the given key, write them + const storedTags = await this.getTagsByPath(key); + const tagsToWrite = derivedTags.filter((tag) => !storedTags.includes(tag)); + if (tagsToWrite.length > 0) { await this.batchWriteDynamoItem( - derivedTags.map((tag) => ({ + tagsToWrite.map((tag) => ({ path: key, tag: tag, })), @@ -299,6 +299,30 @@ export default class S3Cache { // DynamoDB handling + private async getTagsByPath(path: string) { + try { + const result = await this.dynamoClient.send( + new QueryCommand({ + TableName: CACHE_DYNAMO_TABLE, + IndexName: "revalidate", + KeyConditionExpression: "#key = :key", + ExpressionAttributeNames: { + "#key": "path", + }, + ExpressionAttributeValues: { + ":key": { S: this.buildDynamoKey(path) }, + }, + }) + ); + const tags = result.Items?.map((item) => item.tag.S ?? "") ?? []; + debug("tags for path", path, tags); + return tags; + } catch (e) { + error("Failed to get tags by path", e); + return []; + } + } + //TODO: Figure out a better name for this function since it returns the lastModified private async getHasRevalidatedTags(key: string, lastModified?: number) { try { From befea76148b3c37d6bbd86875f0d582c8941c5cb Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Mon, 14 Aug 2023 10:07:34 +0200 Subject: [PATCH 03/13] fix: force revalidation for stale tags and write meta for page --- packages/open-next/src/adapters/cache.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/open-next/src/adapters/cache.ts b/packages/open-next/src/adapters/cache.ts index 973aed2b..f381230f 100644 --- a/packages/open-next/src/adapters/cache.ts +++ b/packages/open-next/src/adapters/cache.ts @@ -1,5 +1,3 @@ -import path from "node:path"; - import { BatchWriteItemCommand, DynamoDBClient, @@ -11,10 +9,12 @@ import { ListObjectsV2Command, PutObjectCommand, PutObjectCommandInput, + PutObjectCommandOutput, S3Client, } from "@aws-sdk/client-s3"; //@ts-ignore import { getDerivedTags } from "next/dist/server/lib/incremental-cache/utils"; +import path from "path"; import { awsLogger, debug, error } from "./logger.js"; import { loadBuildId } from "./util.js"; @@ -137,6 +137,10 @@ export default class S3Cache { key, LastModified?.getTime(), ); + if (lastModified === -1) { + // If some tags are stale we need to force revalidation + return null; + } return { lastModified, @@ -195,6 +199,10 @@ export default class S3Cache { key, LastModified?.getTime(), ); + if (lastModified === -1) { + // If some tags are stale we need to force revalidation + return null; + } const meta = JSON.parse((await MetaBody?.transformToString()) ?? "{}"); return { lastModified, @@ -243,6 +251,15 @@ export default class S3Cache { } else if (data?.kind === "PAGE") { const { html, pageData } = data; const isAppPath = typeof pageData === "string"; + let metaPromise: Promise = + Promise.resolve(); + if (data.status || data.headers) { + metaPromise = this.putS3Object( + key, + "meta", + JSON.stringify({ status: data.status, headers: data.headers }), + ); + } await Promise.all([ this.putS3Object(key, "html", html), this.putS3Object( @@ -250,6 +267,7 @@ export default class S3Cache { isAppPath ? "rsc" : "json", isAppPath ? pageData : JSON.stringify(pageData), ), + metaPromise, ]); } else if (data?.kind === "FETCH") { await this.putS3Object(key, "fetch", JSON.stringify(data)); @@ -312,7 +330,7 @@ export default class S3Cache { ExpressionAttributeValues: { ":key": { S: this.buildDynamoKey(path) }, }, - }) + }), ); const tags = result.Items?.map((item) => item.tag.S ?? "") ?? []; debug("tags for path", path, tags); From 6a7364423791b76d1f7609dc772817a9f3297cb3 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Mon, 14 Aug 2023 11:35:17 +0200 Subject: [PATCH 04/13] fix: patch fetch function --- packages/open-next/src/adapters/revalidate.ts | 1 + .../open-next/src/adapters/server-adapter.ts | 4 ++++ packages/open-next/src/build.ts | 20 +++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/packages/open-next/src/adapters/revalidate.ts b/packages/open-next/src/adapters/revalidate.ts index ceb9a002..3d07b697 100644 --- a/packages/open-next/src/adapters/revalidate.ts +++ b/packages/open-next/src/adapters/revalidate.ts @@ -37,6 +37,7 @@ export const handler = async (event: SQSEvent) => { method: "HEAD", headers: { "x-prerender-revalidate": prerenderManifest.preview.previewModeId, + "x-isr": "1", }, }, (res) => resolve(res), diff --git a/packages/open-next/src/adapters/server-adapter.ts b/packages/open-next/src/adapters/server-adapter.ts index a2c2e9ef..feb21a11 100644 --- a/packages/open-next/src/adapters/server-adapter.ts +++ b/packages/open-next/src/adapters/server-adapter.ts @@ -59,6 +59,10 @@ export async function handler( // Parse Lambda event and create Next.js request const internalEvent = convertFrom(event); + process.env.OPEN_NEXT_ISR = internalEvent.headers["x-isr"] + ? "true" + : undefined; + // WORKAROUND: Set `x-forwarded-host` header (AWS specific) — https://github.com/serverless-stack/open-next#workaround-set-x-forwarded-host-header-aws-specific if (internalEvent.headers["x-forwarded-host"]) { internalEvent.headers.host = internalEvent.headers["x-forwarded-host"]; diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index bcbcf5ce..dcfecb4d 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -554,6 +554,7 @@ async function createServerBundle(monorepoRoot: string) { injectMiddlewareGeolocation(outputPath, packagePath); removeCachedPages(outputPath, packagePath); addCacheHandler(outputPath); + patchFetch(outputPath); } function addMonorepoEntrypoint(outputPath: string, packagePath: string) { @@ -673,6 +674,25 @@ function addCacheHandler(outputPath: string) { }); } +function patchFetch(outputPath: string) { + //TODO: handle monorepo case + const toOverridePath = path.join( + outputPath, + "node_modules", + "next", + "dist", + "server", + "lib", + "patch-fetch.js" + ); + const content = fs.readFileSync(toOverridePath, "utf-8"); + const patchedContent = content.replace( + "staticGenerationStore.isOnDemandRevalidate", + "(staticGenerationStore.isOnDemandRevalidate && !(process.env.OPEN_NEXT_ISR === 'true'))" + ); + fs.writeFileSync(toOverridePath, patchedContent); +} + /********************/ /* Helper Functions */ /********************/ From 1cf8bc6c800b3485a79216d46c7ef4deb0adcc58 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Fri, 8 Sep 2023 14:44:32 +0200 Subject: [PATCH 05/13] fix for 13.4.20 --- packages/open-next/src/adapters/cache.ts | 15 +++++++++++---- packages/open-next/src/build.ts | 18 ++++++++---------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/open-next/src/adapters/cache.ts b/packages/open-next/src/adapters/cache.ts index f381230f..c28d4c52 100644 --- a/packages/open-next/src/adapters/cache.ts +++ b/packages/open-next/src/adapters/cache.ts @@ -12,13 +12,16 @@ import { PutObjectCommandOutput, S3Client, } from "@aws-sdk/client-s3"; -//@ts-ignore -import { getDerivedTags } from "next/dist/server/lib/incremental-cache/utils"; +// //@ts-ignore +// import { getDerivedTags } from "next/dist/server/lib/incremental-cache/utils"; import path from "path"; import { awsLogger, debug, error } from "./logger.js"; import { loadBuildId } from "./util.js"; +// TODO: Remove this, temporary only to run some tests +const getDerivedTags = (tags: string[]) => tags; + interface CachedFetchValue { kind: "FETCH"; data: { @@ -125,8 +128,12 @@ export default class S3Cache { ); } - public async get(key: string, fetchCache?: boolean) { - return fetchCache ? this.getFetchCache(key) : this.getIncrementalCache(key); + public async get(key: string, options?: boolean | { fetchCache?: boolean }) { + const isFetchCache = + typeof options === "object" ? options.fetchCache : options; + return isFetchCache + ? this.getFetchCache(key) + : this.getIncrementalCache(key); } async getFetchCache(key: string) { diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index dcfecb4d..2a4ae7d5 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -429,14 +429,14 @@ function createCacheAssets(monorepoRoot: string) { path: { S: path.posix.join( buildId, - path.relative(outputPath, filePath).replace(".meta", "") + path.relative(outputPath, filePath).replace(".meta", ""), ), }, revalidatedAt: { N: `${Date.now()}` }, }); }); } - } + }, ); const tagsManifestPath = path.join(fetchCachePath, "tags-manifest.json"); @@ -465,7 +465,7 @@ function createCacheAssets(monorepoRoot: string) { // TODO: check if metafiles doesn't contain duplicates fs.writeFileSync( path.join(fetchOutputPath, "dynamodb-cache.json"), - JSON.stringify(metaFiles) + JSON.stringify(metaFiles), ); } } @@ -666,8 +666,6 @@ function addCacheHandler(outputPath: string) { esbuildSync({ external: ["next", "styled-jsx", "react"], entryPoints: [path.join(__dirname, "adapters", "cache.js")], - // We don't need to bundle next - external: ["next"], outfile: path.join(outputPath, "cache.cjs"), target: ["node18"], format: "cjs", @@ -683,12 +681,12 @@ function patchFetch(outputPath: string) { "dist", "server", "lib", - "patch-fetch.js" + "patch-fetch.js", ); const content = fs.readFileSync(toOverridePath, "utf-8"); const patchedContent = content.replace( "staticGenerationStore.isOnDemandRevalidate", - "(staticGenerationStore.isOnDemandRevalidate && !(process.env.OPEN_NEXT_ISR === 'true'))" + "(staticGenerationStore.isOnDemandRevalidate && !(process.env.OPEN_NEXT_ISR === 'true'))", ); fs.writeFileSync(toOverridePath, patchedContent); } @@ -765,7 +763,7 @@ function removeFiles( root, conditionFn, (filePath) => fs.rmSync(filePath, { force: true }), - searchingDir + searchingDir, ); } @@ -773,7 +771,7 @@ function traverseFiles( root: string, conditionFn: (file: string) => boolean, callbackFn: (filePath: string) => void, - searchingDir: string = "" + searchingDir: string = "", ) { fs.readdirSync(path.join(root, searchingDir)).forEach((file) => { const filePath = path.join(root, searchingDir, file); @@ -783,7 +781,7 @@ function traverseFiles( root, conditionFn, callbackFn, - path.join(searchingDir, file) + path.join(searchingDir, file), ); return; } From 46147b53f174a5123526194cca367dc6fb21eff9 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Fri, 8 Sep 2023 15:16:13 +0200 Subject: [PATCH 06/13] add docs to help retrieve paths --- README.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e9d13e4e..5e90b643 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,35 @@ await invalidateCFPaths(["/page/a", "/page/b", "/page/c"]); await invalidateCFPaths(["/page/*"]); ``` -Please note that on-demand revalidation via the [`next/cache` module](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#using-on-demand-revalidation) (`revalidatePath` and `revalidateTag`) is not yet supported. +For on-demand revalidation via the [`next/cache` module](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#using-on-demand-revalidation), if you want to retrieve the associated paths for a given tag, you can use this function: + +```ts +function getByTag(tag: string) { + try { + const { Items } = await this.dynamoClient.send( + new QueryCommand({ + TableName: process.env.CACHE_DYNAMO_TABLE, + KeyConditionExpression: "#tag = :tag", + ExpressionAttributeNames: { + "#tag": "tag", + }, + ExpressionAttributeValues: { + ":tag": { S: `${process.env.NEXT_BUILD_ID}/${tag}` }, + }, + }), + ); + return ( + // We need to remove the buildId from the path + Items?.map( + ({ path: { S: key } }) => key?.replace(`${process.env.NEXT_BUILD_ID}/`, "") ?? "", + ) ?? [] + ); + } catch (e) { + error("Failed to get by tag", e); + return []; + } +} +``` ## How warming works From 2917c1aaeb5ee41802bb8b0485f9b81092893370 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Tue, 12 Sep 2023 09:16:38 +0200 Subject: [PATCH 07/13] custom provider to populate dynamodb --- .../open-next/src/adapters/dynamo-provider.ts | 75 +++++++++++++++++++ packages/open-next/src/build.ts | 11 ++- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 packages/open-next/src/adapters/dynamo-provider.ts diff --git a/packages/open-next/src/adapters/dynamo-provider.ts b/packages/open-next/src/adapters/dynamo-provider.ts new file mode 100644 index 00000000..9d0c1a55 --- /dev/null +++ b/packages/open-next/src/adapters/dynamo-provider.ts @@ -0,0 +1,75 @@ +import { + BatchWriteItemCommand, + DynamoDBClient, +} from "@aws-sdk/client-dynamodb"; +import { CdkCustomResourceEvent, CdkCustomResourceResponse } from "aws-lambda"; +import { readFileSync } from "fs"; + +const client = new DynamoDBClient({}); + +type DataType = { + tag: { + S: string; + }; + path: { + S: string; + }; + revalidatedAt: { + N: string; + }; +}; + +export async function handler( + event: CdkCustomResourceEvent, +): Promise { + switch (event.RequestType) { + case "Create": + case "Update": + return insert(); + case "Delete": + return remove(); + } +} + +async function insert(): Promise { + const file = readFileSync(`dynamodb-cache.json`, "utf8"); + + const data: DataType[] = JSON.parse(file); + + // Chunk array into batches of 25 + const chunked = data.reduce((acc, curr, i) => { + const index = Math.floor(i / 25); + acc[index] = [...(acc[index] || []), curr]; + return acc; + }, [] as DataType[][]); + + const TableName = process.env.CACHE_DYNAMO_TABLE!; + + const promises = chunked.map((chunk) => { + const params = { + RequestItems: { + [TableName]: chunk.map((item) => ({ + PutRequest: { + Item: item, + }, + })), + }, + }; + return client.send(new BatchWriteItemCommand(params)); + }); + + await Promise.all(promises); + + return { + PhysicalResourceId: "dynamodb-cache", + Data: {}, + }; +} + +async function remove(): Promise { + // Do we want to actually delete anything here? + return { + PhysicalResourceId: "dynamodb-cache", + Data: {}, + }; +} diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 2a4ae7d5..9975ac28 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -462,9 +462,18 @@ function createCacheAssets(monorepoRoot: string) { }); } + const providerPath = path.join(outputDir, "dynamodb-provider"); + + esbuildSync({ + external: ["@aws-sdk/client-dynamodb"], + entryPoints: [path.join(__dirname, "adapters", "dynamo-provider.js")], + outfile: path.join(providerPath, "index.mjs"), + target: ["node18"], + }); + // TODO: check if metafiles doesn't contain duplicates fs.writeFileSync( - path.join(fetchOutputPath, "dynamodb-cache.json"), + path.join(providerPath, "dynamodb-cache.json"), JSON.stringify(metaFiles), ); } From 1710c8c1c12f3eeb24aab35d9312b6b6c5173f84 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Tue, 12 Sep 2023 12:57:35 +0200 Subject: [PATCH 08/13] fix for esm loader --- .../adapters/plugins/13.4.20/serverHandler.ts | 17 ++++++++ .../src/adapters/plugins/13.4.20/util.ts | 41 +++++++++++++++++++ packages/open-next/src/build.ts | 15 ++++++- 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 packages/open-next/src/adapters/plugins/13.4.20/serverHandler.ts create mode 100644 packages/open-next/src/adapters/plugins/13.4.20/util.ts diff --git a/packages/open-next/src/adapters/plugins/13.4.20/serverHandler.ts b/packages/open-next/src/adapters/plugins/13.4.20/serverHandler.ts new file mode 100644 index 00000000..9810dbf8 --- /dev/null +++ b/packages/open-next/src/adapters/plugins/13.4.20/serverHandler.ts @@ -0,0 +1,17 @@ +/*eslint-disable simple-import-sort/imports */ +import type { Options, PluginHandler } from "../../next-types.js"; +import type { IncomingMessage } from "../../request.js"; +import type { ServerResponse } from "../../response.js"; +//#override imports +import { requestHandler } from "./util.js"; +//#endOverride + +//#override handler +export const handler: PluginHandler = async ( + req: IncomingMessage, + res: ServerResponse, + _: Options, +) => { + return requestHandler(req, res); +}; +//#endOverride diff --git a/packages/open-next/src/adapters/plugins/13.4.20/util.ts b/packages/open-next/src/adapters/plugins/13.4.20/util.ts new file mode 100644 index 00000000..342547de --- /dev/null +++ b/packages/open-next/src/adapters/plugins/13.4.20/util.ts @@ -0,0 +1,41 @@ +import path from "node:path"; + +import { loadConfig } from "../../util.js"; + +const NEXT_DIR = path.join(__dirname, ".next"); + +const config = loadConfig(NEXT_DIR); +//#override requestHandler + +process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify({ + ...config, + // Next.js compression should be disabled because of a bug in the bundled + // `compression` package — https://github.com/vercel/next.js/issues/11669 + compress: false, + // By default, Next.js uses local disk to store ISR cache. We will use + // our own cache handler to store the cache on S3. + skipMiddlewareUrlNormalize: true, + experimental: { + ...config.experimental, + // This uses the request.headers.host as the URL + // https://github.com/vercel/next.js/blob/canary/packages/next/src/server/next-server.ts#L1749-L1754 + trustHostHeader: true, + incrementalCacheHandlerPath: `${process.env.LAMBDA_TASK_ROOT}/cache.cjs`, + }, +}); +process.env.__NEXT_PRIVATE_PREBUNDLED_REACT = true + ? config.experimental && config.experimental.serverActions + ? "experimental" + : "next" + : ""; + +require("next"); +const { getRequestHandlers } = require("next/dist/server/lib/start-server"); + +const handlers = await getRequestHandlers({ + customServer: false, + dev: false, + dir: __dirname, +}); +export const requestHandler = handlers[0]; +//#endOverride diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 9975ac28..7e2b3e4e 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -516,7 +516,7 @@ async function createServerBundle(monorepoRoot: string) { // note: bundle in OpenNext package b/c the adapter relies on the // "serverless-http" package which is not a dependency in user's // Next.js app. - const plugins = + let plugins = compareSemver(options.nextVersion, "13.4.13") >= 0 ? [ openNextPlugin({ @@ -534,6 +534,19 @@ async function createServerBundle(monorepoRoot: string) { ] : undefined; + if (compareSemver(options.nextVersion, "13.4.20") >= 0) { + plugins = [ + openNextPlugin({ + target: /plugins\/serverHandler\.js/g, + replacements: ["./13.4.20/serverHandler.js"], + }), + openNextPlugin({ + target: /plugins\/util\.js/g, + replacements: ["./13.4.20/util.js"], + }), + ]; + } + if (plugins) { console.log( `Applying plugins:: [${plugins From 9da69110a85b8aae263841d79cd8b5f8faea31d8 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Mon, 18 Sep 2023 19:25:42 +0200 Subject: [PATCH 09/13] fix for next bundled 13.5 --- .../adapters/plugins/{13.4.20 => 13.5}/serverHandler.ts | 0 .../src/adapters/plugins/{13.4.20 => 13.5}/util.ts | 7 ++++++- packages/open-next/src/adapters/plugins/util.ts | 2 ++ packages/open-next/src/build.ts | 6 +++--- 4 files changed, 11 insertions(+), 4 deletions(-) rename packages/open-next/src/adapters/plugins/{13.4.20 => 13.5}/serverHandler.ts (100%) rename packages/open-next/src/adapters/plugins/{13.4.20 => 13.5}/util.ts (90%) diff --git a/packages/open-next/src/adapters/plugins/13.4.20/serverHandler.ts b/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts similarity index 100% rename from packages/open-next/src/adapters/plugins/13.4.20/serverHandler.ts rename to packages/open-next/src/adapters/plugins/13.5/serverHandler.ts diff --git a/packages/open-next/src/adapters/plugins/13.4.20/util.ts b/packages/open-next/src/adapters/plugins/13.5/util.ts similarity index 90% rename from packages/open-next/src/adapters/plugins/13.4.20/util.ts rename to packages/open-next/src/adapters/plugins/13.5/util.ts index 342547de..e3925898 100644 --- a/packages/open-next/src/adapters/plugins/13.4.20/util.ts +++ b/packages/open-next/src/adapters/plugins/13.5/util.ts @@ -1,12 +1,17 @@ import path from "node:path"; +import { debug } from "../../logger.js"; import { loadConfig } from "../../util.js"; const NEXT_DIR = path.join(__dirname, ".next"); const config = loadConfig(NEXT_DIR); -//#override requestHandler +//#override requireHooks +debug("No need to override require hooks with next 13.4.20+"); +//#endOverride + +//#override requestHandler process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify({ ...config, // Next.js compression should be disabled because of a bug in the bundled diff --git a/packages/open-next/src/adapters/plugins/util.ts b/packages/open-next/src/adapters/plugins/util.ts index 31305b37..c2543479 100644 --- a/packages/open-next/src/adapters/plugins/util.ts +++ b/packages/open-next/src/adapters/plugins/util.ts @@ -30,8 +30,10 @@ const config = loadConfig(NEXT_DIR); // Step 3: Apply the override after Next.js server is imported since the // override that Next.js does is done at import time +//#override requireHooks overrideNextjsRequireHooks(config); applyNextjsRequireHooksOverride(); +//#endOverride //#override requestHandler // @ts-ignore diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 7e2b3e4e..13460b3c 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -534,15 +534,15 @@ async function createServerBundle(monorepoRoot: string) { ] : undefined; - if (compareSemver(options.nextVersion, "13.4.20") >= 0) { + if (compareSemver(options.nextVersion, "13.5.1") >= 0) { plugins = [ openNextPlugin({ target: /plugins\/serverHandler\.js/g, - replacements: ["./13.4.20/serverHandler.js"], + replacements: ["./13.5/serverHandler.js"], }), openNextPlugin({ target: /plugins\/util\.js/g, - replacements: ["./13.4.20/util.js"], + replacements: ["./13.5/util.js"], }), ]; } From e8294b387d944bed1e8002f73ba222a97c59f94f Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Tue, 26 Sep 2023 20:02:25 +0200 Subject: [PATCH 10/13] revert serverHandler to use custom routing --- .../adapters/plugins/13.5/serverHandler.ts | 12 +++++- .../src/adapters/plugins/13.5/util.ts | 42 ++----------------- packages/open-next/src/build.ts | 8 ++++ 3 files changed, 21 insertions(+), 41 deletions(-) diff --git a/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts b/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts index 9810dbf8..83a66dc4 100644 --- a/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts +++ b/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts @@ -3,15 +3,23 @@ import type { Options, PluginHandler } from "../../next-types.js"; import type { IncomingMessage } from "../../request.js"; import type { ServerResponse } from "../../response.js"; //#override imports +//@ts-ignore import { requestHandler } from "./util.js"; +//@ts-ignore +import { proxyRequest } from "./routing/util.js"; //#endOverride //#override handler export const handler: PluginHandler = async ( req: IncomingMessage, res: ServerResponse, - _: Options, + options: Options, ) => { - return requestHandler(req, res); + if (options.isExternalRewrite) { + return proxyRequest(req, res); + } else { + // Next Server + return requestHandler(req, res); + } }; //#endOverride diff --git a/packages/open-next/src/adapters/plugins/13.5/util.ts b/packages/open-next/src/adapters/plugins/13.5/util.ts index e3925898..4ef61fde 100644 --- a/packages/open-next/src/adapters/plugins/13.5/util.ts +++ b/packages/open-next/src/adapters/plugins/13.5/util.ts @@ -1,46 +1,10 @@ -import path from "node:path"; +// import path from "node:path"; import { debug } from "../../logger.js"; -import { loadConfig } from "../../util.js"; +// import { loadConfig } from "../../util.js"; -const NEXT_DIR = path.join(__dirname, ".next"); - -const config = loadConfig(NEXT_DIR); +// const NEXT_DIR = path.join(__dirname, ".next"); //#override requireHooks debug("No need to override require hooks with next 13.4.20+"); //#endOverride - -//#override requestHandler -process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify({ - ...config, - // Next.js compression should be disabled because of a bug in the bundled - // `compression` package — https://github.com/vercel/next.js/issues/11669 - compress: false, - // By default, Next.js uses local disk to store ISR cache. We will use - // our own cache handler to store the cache on S3. - skipMiddlewareUrlNormalize: true, - experimental: { - ...config.experimental, - // This uses the request.headers.host as the URL - // https://github.com/vercel/next.js/blob/canary/packages/next/src/server/next-server.ts#L1749-L1754 - trustHostHeader: true, - incrementalCacheHandlerPath: `${process.env.LAMBDA_TASK_ROOT}/cache.cjs`, - }, -}); -process.env.__NEXT_PRIVATE_PREBUNDLED_REACT = true - ? config.experimental && config.experimental.serverActions - ? "experimental" - : "next" - : ""; - -require("next"); -const { getRequestHandlers } = require("next/dist/server/lib/start-server"); - -const handlers = await getRequestHandlers({ - customServer: false, - dev: false, - dir: __dirname, -}); -export const requestHandler = handlers[0]; -//#endOverride diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 13460b3c..f86aa111 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -544,6 +544,14 @@ async function createServerBundle(monorepoRoot: string) { target: /plugins\/util\.js/g, replacements: ["./13.5/util.js"], }), + openNextPlugin({ + target: /plugins\/util\.js/g, + replacements: ["./util.replacement.js"], + }), + openNextPlugin({ + target: /plugins\/routing\/default\.js/g, + replacements: ["./default.replacement.js"], + }), ]; } From 90f76a711dbc528e5f011d498e9d35fe2622c5bc Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Tue, 26 Sep 2023 20:03:27 +0200 Subject: [PATCH 11/13] remove patchFetch as it no longer works --- packages/open-next/src/build.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index f86aa111..2caf3a96 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -584,7 +584,6 @@ async function createServerBundle(monorepoRoot: string) { injectMiddlewareGeolocation(outputPath, packagePath); removeCachedPages(outputPath, packagePath); addCacheHandler(outputPath); - patchFetch(outputPath); } function addMonorepoEntrypoint(outputPath: string, packagePath: string) { @@ -702,25 +701,6 @@ function addCacheHandler(outputPath: string) { }); } -function patchFetch(outputPath: string) { - //TODO: handle monorepo case - const toOverridePath = path.join( - outputPath, - "node_modules", - "next", - "dist", - "server", - "lib", - "patch-fetch.js", - ); - const content = fs.readFileSync(toOverridePath, "utf-8"); - const patchedContent = content.replace( - "staticGenerationStore.isOnDemandRevalidate", - "(staticGenerationStore.isOnDemandRevalidate && !(process.env.OPEN_NEXT_ISR === 'true'))", - ); - fs.writeFileSync(toOverridePath, patchedContent); -} - /********************/ /* Helper Functions */ /********************/ From da56f0798de41b3111f248a0b5b66e436a54b880 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Tue, 26 Sep 2023 20:15:23 +0200 Subject: [PATCH 12/13] docs: add docs about fetch behaviour --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 5e90b643..435eef5c 100644 --- a/README.md +++ b/README.md @@ -411,6 +411,19 @@ This cost estimate is based on the `us-east-1` region pricing and does not consi ## Limitations and workarounds +#### WORKAROUND: Patch fetch behaviour for ISR. Only for next@13.5.1+ + +In order to make fetch work as expected with ISR, you need to patch the `fetch` function in your app. Just add this lines to your root layout component: + +```ts +const asyncStorage = require("next/dist/client/components/static-generation-async-storage.external"); +//@ts-ignore +const staticStore = (fetch as any).__nextGetStaticStore?.() || asyncStorage.staticGenerationAsyncStorage; +const store = staticStore.getStore(); +store.isOnDemandRevalidate = store.isOnDemandRevalidate && !(process.env.OPEN_NEXT_ISR === 'true'); +``` +Without this workaround, if you have 2 fetch calls in your page with different revalidate values, both will use the smallest value during ISR revalidation. + #### WORKAROUND: Create one cache behavior per top-level file and folder in `public/` (AWS specific) As mentioned in the [Asset files](#asset-files) section, files in your app's `public/` folder are static and are uploaded to the S3 bucket. And requests for these files are handled by the S3 bucket, like so: From c77e4dca72c19db05094910d6f1d4158b93e32ae Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Wed, 27 Sep 2023 16:11:54 +0200 Subject: [PATCH 13/13] get fetch cache tags directly from cache file --- packages/open-next/src/build.ts | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 2caf3a96..2babe0e9 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -439,28 +439,26 @@ function createCacheAssets(monorepoRoot: string) { }, ); - const tagsManifestPath = path.join(fetchCachePath, "tags-manifest.json"); - if (fs.existsSync(tagsManifestPath)) { - // We also need to add cache tags from tags-manifest.json - const tagsManifestFile = fs.readFileSync(tagsManifestPath, "utf8"); - const tagsManifest = JSON.parse(tagsManifestFile) as { - version: number; - items: { - [tag: string]: { - keys: string[]; - }; - }; - }; - Object.entries(tagsManifest.items).forEach(([tag, tagObject]) => { - tagObject.keys.forEach((key: string) => { + traverseFiles( + fetchCachePath, + () => true, + (filepath) => { + const fileContent = fs.readFileSync(filepath, "utf8"); + const fileData = JSON.parse(fileContent); + fileData?.tags?.forEach((tag: string) => { metaFiles.push({ tag: { S: path.posix.join(buildId, tag) }, - path: { S: path.posix.join(buildId, key) }, + path: { + S: path.posix.join( + buildId, + path.relative(fetchCachePath, filepath), + ), + }, revalidatedAt: { N: `${Date.now()}` }, }); }); - }); - } + }, + ); const providerPath = path.join(outputDir, "dynamodb-provider");