From 0520a370a8d4ed2f58c1f888a1857d092a45d350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Fri, 5 Jan 2024 10:45:19 +0000 Subject: [PATCH 1/4] fix: set Blobs context on the process --- src/commands/dev/dev.ts | 16 +++++++++------- src/commands/serve/serve.ts | 4 +++- src/lib/blobs/blobs.ts | 5 ++++- src/lib/functions/netlify-function.ts | 16 ---------------- src/lib/functions/registry.ts | 11 +---------- src/lib/functions/runtimes/js/index.ts | 9 +++++++++ src/lib/functions/server.ts | 17 ++--------------- 7 files changed, 28 insertions(+), 50 deletions(-) diff --git a/src/commands/dev/dev.ts b/src/commands/dev/dev.ts index 50f1da5a745..ce0de04f6b6 100644 --- a/src/commands/dev/dev.ts +++ b/src/commands/dev/dev.ts @@ -2,7 +2,7 @@ import process from 'process' import { OptionValues, Option } from 'commander' -import { getBlobsContext } from '../../lib/blobs/blobs.js' +import { BLOBS_CONTEXT_VARIABLE, getBlobsContext } from '../../lib/blobs/blobs.js' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js' import { startFunctionsServer } from '../../lib/functions/server.js' import { printBanner } from '../../utils/banner.js' @@ -105,6 +105,14 @@ export const dev = async (options: OptionValues, command: BaseCommand) => { env.NETLIFY_DEV = { sources: ['internal'], value: 'true' } + const blobsContext = await getBlobsContext({ + debug: options.debug, + projectRoot: command.workingDir, + siteID: site.id ?? 'unknown-site-id', + }) + + env[BLOBS_CONTEXT_VARIABLE] = { sources: ['internal'], value: blobsContext } + if (!options.offline && siteInfo.use_envelope) { env = await getEnvelopeEnv({ api, context: options.context, env, siteInfo }) log(`${NETLIFYDEVLOG} Injecting environment variable values for ${chalk.yellow('all scopes')}`) @@ -155,12 +163,6 @@ export const dev = async (options: OptionValues, command: BaseCommand) => { }, }) - const blobsContext = await getBlobsContext({ - debug: options.debug, - projectRoot: command.workingDir, - siteID: site.id ?? 'unknown-site-id', - }) - const functionsRegistry = await startFunctionsServer({ api, blobsContext, diff --git a/src/commands/serve/serve.ts b/src/commands/serve/serve.ts index 2c3a5c1095c..b22fe0eab39 100644 --- a/src/commands/serve/serve.ts +++ b/src/commands/serve/serve.ts @@ -2,7 +2,7 @@ import process from 'process' import { OptionValues } from 'commander' -import { getBlobsContext } from '../../lib/blobs/blobs.js' +import { BLOBS_CONTEXT_VARIABLE, getBlobsContext } from '../../lib/blobs/blobs.js' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js' import { startFunctionsServer } from '../../lib/functions/server.js' import { printBanner } from '../../utils/banner.js' @@ -100,6 +100,8 @@ export const serve = async (options: OptionValues, command: BaseCommand) => { siteID: site.id ?? 'unknown-site-id', }) + process.env[BLOBS_CONTEXT_VARIABLE] = blobsContext + const functionsRegistry = await startFunctionsServer({ api, blobsContext, diff --git a/src/lib/blobs/blobs.ts b/src/lib/blobs/blobs.ts index 94e9bdf8f1a..135f2137ae4 100644 --- a/src/lib/blobs/blobs.ts +++ b/src/lib/blobs/blobs.ts @@ -1,3 +1,4 @@ +import { Buffer } from 'buffer' import path from 'path' import { BlobsServer } from '@netlify/blobs' @@ -8,6 +9,8 @@ import { getPathInProject } from '../settings.js' let hasPrintedLocalBlobsNotice = false +export const BLOBS_CONTEXT_VARIABLE = 'NETLIFY_BLOBS_CONTEXT' + export interface BlobsContext { deployID: string edgeURL: string @@ -62,5 +65,5 @@ export const getBlobsContext = async ({ debug, projectRoot, siteID }: GetBlobsCo token, } - return context + return Buffer.from(JSON.stringify(context)).toString('base64') } diff --git a/src/lib/functions/netlify-function.ts b/src/lib/functions/netlify-function.ts index a202948156b..71070fed081 100644 --- a/src/lib/functions/netlify-function.ts +++ b/src/lib/functions/netlify-function.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer' import { basename, extname } from 'path' import { version as nodeVersion } from 'process' @@ -7,7 +6,6 @@ import semver from 'semver' import { error as errorExit } from '../../utils/command-helpers.js' import { BACKGROUND } from '../../utils/functions/get-functions.js' -import type { BlobsContext } from '../blobs/blobs.js' const TYPESCRIPT_EXTENSIONS = new Set(['.cts', '.mts', '.ts']) const V2_MIN_NODE_VERSION = '18.14.0' @@ -34,7 +32,6 @@ export default class NetlifyFunction { private readonly directory: string private readonly projectRoot: string - private readonly blobsContext: BlobsContext private readonly timeoutBackground: number private readonly timeoutSynchronous: number @@ -51,8 +48,6 @@ export default class NetlifyFunction { private readonly srcFiles = new Set() constructor({ - // @ts-expect-error TS(7031) FIXME: Binding element 'blobsContext' implicitly has an '... Remove this comment to see the full error message - blobsContext, // @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message config, // @ts-expect-error TS(7031) FIXME: Binding element 'directory' implicitly has an 'any... Remove this comment to see the full error message @@ -74,7 +69,6 @@ export default class NetlifyFunction { // @ts-expect-error TS(7031) FIXME: Binding element 'timeoutSynchronous' implicitly ha... Remove this comment to see the full error message timeoutSynchronous, }) { - this.blobsContext = blobsContext // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'NetlifyF... Remove this comment to see the full error message this.config = config this.directory = directory @@ -236,16 +230,6 @@ export default class NetlifyFunction { const timeout = this.isBackground ? this.timeoutBackground : this.timeoutSynchronous const environment = {} - if (this.blobsContext) { - const payload = JSON.stringify({ - url: this.blobsContext.edgeURL, - token: this.blobsContext.token, - }) - - // @ts-expect-error TS(2339) FIXME: Property 'blobs' does not exist on type '{}'. - event.blobs = Buffer.from(payload).toString('base64') - } - try { // @ts-expect-error TS(2339) FIXME: Property 'runtime' does not exist on type 'Netlify... Remove this comment to see the full error message const result = await this.runtime.invokeFunction({ diff --git a/src/lib/functions/registry.ts b/src/lib/functions/registry.ts index 840a4a65a43..cb26b951856 100644 --- a/src/lib/functions/registry.ts +++ b/src/lib/functions/registry.ts @@ -17,7 +17,6 @@ import { watchDebounced, } from '../../utils/command-helpers.js' import { INTERNAL_FUNCTIONS_FOLDER, SERVE_FUNCTIONS_FOLDER } from '../../utils/functions/functions.js' -import type { BlobsContext } from '../blobs/blobs.js' import { BACKGROUND_FUNCTIONS_WARNING } from '../log.js' import { getPathInProject } from '../settings.js' @@ -53,17 +52,11 @@ export class FunctionsRegistry { */ private hasCheckedTypesPackage = false - /** - * Context object for Netlify Blobs - */ - private blobsContext: BlobsContext - private projectRoot: string private isConnected: boolean private debug: boolean constructor({ - blobsContext, // @ts-expect-error TS(7031) FIXME: Binding element 'capabilities' implicitly has an '... Remove this comment to see the full error message capabilities, // @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message @@ -79,7 +72,7 @@ export class FunctionsRegistry { settings, // @ts-expect-error TS(7031) FIXME: Binding element 'timeouts' implicitly has an 'any'... Remove this comment to see the full error message timeouts, - }: { projectRoot: string; debug?: boolean; isConnected?: boolean; blobsContext: BlobsContext } & object) { + }: { projectRoot: string; debug?: boolean; isConnected?: boolean } & object) { // @ts-expect-error TS(2339) FIXME: Property 'capabilities' does not exist on type 'Fu... Remove this comment to see the full error message this.capabilities = capabilities // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message @@ -91,7 +84,6 @@ export class FunctionsRegistry { this.timeouts = timeouts // @ts-expect-error TS(2339) FIXME: Property 'settings' does not exist on type 'Functi... Remove this comment to see the full error message this.settings = settings - this.blobsContext = blobsContext /** * An object to be shared among all functions in the registry. It can be @@ -529,7 +521,6 @@ export class FunctionsRegistry { } const func = new NetlifyFunction({ - blobsContext: this.blobsContext, // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message config: this.config, directory: directories.find((directory) => mainFile.startsWith(directory)), diff --git a/src/lib/functions/runtimes/js/index.ts b/src/lib/functions/runtimes/js/index.ts index c35ea04b057..004afeadfdc 100644 --- a/src/lib/functions/runtimes/js/index.ts +++ b/src/lib/functions/runtimes/js/index.ts @@ -5,6 +5,8 @@ import { Worker } from 'worker_threads' import lambdaLocal from 'lambda-local' +import { BLOBS_CONTEXT_VARIABLE } from '../../../blobs/blobs.js' + import detectNetlifyLambdaBuilder from './builders/netlify-lambda.js' import detectZisiBuilder, { parseFunctionForMetadata } from './builders/zisi.js' import { SECONDS_TO_MILLISECONDS } from './constants.js' @@ -104,6 +106,13 @@ export const invokeFunctionDirectly = async ({ context, event, func, timeout }) const lambdaPath = func.buildData?.buildPath ?? func.mainFile const result = await lambdaLocal.execute({ clientContext: JSON.stringify(context), + environment: { + // We've set the Blobs context on the parent process, which means it will + // be available to the Lambda. This would be inconsistent with production + // where only V2 functions get the context injected. To fix it, unset the + // context variable before invoking the function. + [BLOBS_CONTEXT_VARIABLE]: undefined, + }, event, lambdaPath, timeoutMs: timeout * SECONDS_TO_MILLISECONDS, diff --git a/src/lib/functions/server.ts b/src/lib/functions/server.ts index e9637fabefc..23d3b62ce27 100644 --- a/src/lib/functions/server.ts +++ b/src/lib/functions/server.ts @@ -265,7 +265,6 @@ const getFunctionsServer = (options) => { /** * * @param {object} options - * @param {import("../blobs/blobs.js").BlobsContext} options.blobsContext * @param {import('../../commands/base-command.js').default} options.command * @param {*} options.capabilities * @param {*} options.config @@ -280,19 +279,8 @@ const getFunctionsServer = (options) => { */ // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. export const startFunctionsServer = async (options) => { - const { - blobsContext, - capabilities, - command, - config, - debug, - loadDistFunctions, - settings, - site, - siteInfo, - siteUrl, - timeouts, - } = options + const { capabilities, command, config, debug, loadDistFunctions, settings, site, siteInfo, siteUrl, timeouts } = + options const internalFunctionsDir = await getInternalFunctionsDir({ base: site.root }) const functionsDirectories: string[] = [] let manifest @@ -339,7 +327,6 @@ export const startFunctionsServer = async (options) => { } const functionsRegistry = new FunctionsRegistry({ - blobsContext, // @ts-expect-error TS(7031) FIXME capabilities, config, From 724569bcddcf572c7cdfebbebb975d2bb00a3fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Sat, 6 Jan 2024 10:51:53 +0000 Subject: [PATCH 2/4] fix: keep context for Lambda compat mode --- src/commands/dev/dev.ts | 4 ++-- src/commands/serve/serve.ts | 4 ++-- src/lib/blobs/blobs.ts | 8 +++++++- src/lib/functions/netlify-function.ts | 16 ++++++++++++++++ src/lib/functions/registry.ts | 11 ++++++++++- src/lib/functions/server.ts | 17 +++++++++++++++-- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/commands/dev/dev.ts b/src/commands/dev/dev.ts index ce0de04f6b6..b2ae872e4b1 100644 --- a/src/commands/dev/dev.ts +++ b/src/commands/dev/dev.ts @@ -2,7 +2,7 @@ import process from 'process' import { OptionValues, Option } from 'commander' -import { BLOBS_CONTEXT_VARIABLE, getBlobsContext } from '../../lib/blobs/blobs.js' +import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContext } from '../../lib/blobs/blobs.js' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js' import { startFunctionsServer } from '../../lib/functions/server.js' import { printBanner } from '../../utils/banner.js' @@ -111,7 +111,7 @@ export const dev = async (options: OptionValues, command: BaseCommand) => { siteID: site.id ?? 'unknown-site-id', }) - env[BLOBS_CONTEXT_VARIABLE] = { sources: ['internal'], value: blobsContext } + env[BLOBS_CONTEXT_VARIABLE] = { sources: ['internal'], value: encodeBlobsContext(blobsContext) } if (!options.offline && siteInfo.use_envelope) { env = await getEnvelopeEnv({ api, context: options.context, env, siteInfo }) diff --git a/src/commands/serve/serve.ts b/src/commands/serve/serve.ts index b22fe0eab39..c474b342db4 100644 --- a/src/commands/serve/serve.ts +++ b/src/commands/serve/serve.ts @@ -2,7 +2,7 @@ import process from 'process' import { OptionValues } from 'commander' -import { BLOBS_CONTEXT_VARIABLE, getBlobsContext } from '../../lib/blobs/blobs.js' +import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContext } from '../../lib/blobs/blobs.js' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js' import { startFunctionsServer } from '../../lib/functions/server.js' import { printBanner } from '../../utils/banner.js' @@ -100,7 +100,7 @@ export const serve = async (options: OptionValues, command: BaseCommand) => { siteID: site.id ?? 'unknown-site-id', }) - process.env[BLOBS_CONTEXT_VARIABLE] = blobsContext + process.env[BLOBS_CONTEXT_VARIABLE] = encodeBlobsContext(blobsContext) const functionsRegistry = await startFunctionsServer({ api, diff --git a/src/lib/blobs/blobs.ts b/src/lib/blobs/blobs.ts index 135f2137ae4..54168eeff4f 100644 --- a/src/lib/blobs/blobs.ts +++ b/src/lib/blobs/blobs.ts @@ -65,5 +65,11 @@ export const getBlobsContext = async ({ debug, projectRoot, siteID }: GetBlobsCo token, } - return Buffer.from(JSON.stringify(context)).toString('base64') + return context } + +/** + * Returns a Base-64, JSON-encoded representation of the Blobs context. This is + * the format that the `@netlify/blobs` package expects to find the context in. + */ +export const encodeBlobsContext = (context: BlobsContext) => Buffer.from(JSON.stringify(context)).toString('base64') diff --git a/src/lib/functions/netlify-function.ts b/src/lib/functions/netlify-function.ts index 71070fed081..a202948156b 100644 --- a/src/lib/functions/netlify-function.ts +++ b/src/lib/functions/netlify-function.ts @@ -1,3 +1,4 @@ +import { Buffer } from 'buffer' import { basename, extname } from 'path' import { version as nodeVersion } from 'process' @@ -6,6 +7,7 @@ import semver from 'semver' import { error as errorExit } from '../../utils/command-helpers.js' import { BACKGROUND } from '../../utils/functions/get-functions.js' +import type { BlobsContext } from '../blobs/blobs.js' const TYPESCRIPT_EXTENSIONS = new Set(['.cts', '.mts', '.ts']) const V2_MIN_NODE_VERSION = '18.14.0' @@ -32,6 +34,7 @@ export default class NetlifyFunction { private readonly directory: string private readonly projectRoot: string + private readonly blobsContext: BlobsContext private readonly timeoutBackground: number private readonly timeoutSynchronous: number @@ -48,6 +51,8 @@ export default class NetlifyFunction { private readonly srcFiles = new Set() constructor({ + // @ts-expect-error TS(7031) FIXME: Binding element 'blobsContext' implicitly has an '... Remove this comment to see the full error message + blobsContext, // @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message config, // @ts-expect-error TS(7031) FIXME: Binding element 'directory' implicitly has an 'any... Remove this comment to see the full error message @@ -69,6 +74,7 @@ export default class NetlifyFunction { // @ts-expect-error TS(7031) FIXME: Binding element 'timeoutSynchronous' implicitly ha... Remove this comment to see the full error message timeoutSynchronous, }) { + this.blobsContext = blobsContext // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'NetlifyF... Remove this comment to see the full error message this.config = config this.directory = directory @@ -230,6 +236,16 @@ export default class NetlifyFunction { const timeout = this.isBackground ? this.timeoutBackground : this.timeoutSynchronous const environment = {} + if (this.blobsContext) { + const payload = JSON.stringify({ + url: this.blobsContext.edgeURL, + token: this.blobsContext.token, + }) + + // @ts-expect-error TS(2339) FIXME: Property 'blobs' does not exist on type '{}'. + event.blobs = Buffer.from(payload).toString('base64') + } + try { // @ts-expect-error TS(2339) FIXME: Property 'runtime' does not exist on type 'Netlify... Remove this comment to see the full error message const result = await this.runtime.invokeFunction({ diff --git a/src/lib/functions/registry.ts b/src/lib/functions/registry.ts index cb26b951856..840a4a65a43 100644 --- a/src/lib/functions/registry.ts +++ b/src/lib/functions/registry.ts @@ -17,6 +17,7 @@ import { watchDebounced, } from '../../utils/command-helpers.js' import { INTERNAL_FUNCTIONS_FOLDER, SERVE_FUNCTIONS_FOLDER } from '../../utils/functions/functions.js' +import type { BlobsContext } from '../blobs/blobs.js' import { BACKGROUND_FUNCTIONS_WARNING } from '../log.js' import { getPathInProject } from '../settings.js' @@ -52,11 +53,17 @@ export class FunctionsRegistry { */ private hasCheckedTypesPackage = false + /** + * Context object for Netlify Blobs + */ + private blobsContext: BlobsContext + private projectRoot: string private isConnected: boolean private debug: boolean constructor({ + blobsContext, // @ts-expect-error TS(7031) FIXME: Binding element 'capabilities' implicitly has an '... Remove this comment to see the full error message capabilities, // @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message @@ -72,7 +79,7 @@ export class FunctionsRegistry { settings, // @ts-expect-error TS(7031) FIXME: Binding element 'timeouts' implicitly has an 'any'... Remove this comment to see the full error message timeouts, - }: { projectRoot: string; debug?: boolean; isConnected?: boolean } & object) { + }: { projectRoot: string; debug?: boolean; isConnected?: boolean; blobsContext: BlobsContext } & object) { // @ts-expect-error TS(2339) FIXME: Property 'capabilities' does not exist on type 'Fu... Remove this comment to see the full error message this.capabilities = capabilities // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message @@ -84,6 +91,7 @@ export class FunctionsRegistry { this.timeouts = timeouts // @ts-expect-error TS(2339) FIXME: Property 'settings' does not exist on type 'Functi... Remove this comment to see the full error message this.settings = settings + this.blobsContext = blobsContext /** * An object to be shared among all functions in the registry. It can be @@ -521,6 +529,7 @@ export class FunctionsRegistry { } const func = new NetlifyFunction({ + blobsContext: this.blobsContext, // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message config: this.config, directory: directories.find((directory) => mainFile.startsWith(directory)), diff --git a/src/lib/functions/server.ts b/src/lib/functions/server.ts index 23d3b62ce27..e9637fabefc 100644 --- a/src/lib/functions/server.ts +++ b/src/lib/functions/server.ts @@ -265,6 +265,7 @@ const getFunctionsServer = (options) => { /** * * @param {object} options + * @param {import("../blobs/blobs.js").BlobsContext} options.blobsContext * @param {import('../../commands/base-command.js').default} options.command * @param {*} options.capabilities * @param {*} options.config @@ -279,8 +280,19 @@ const getFunctionsServer = (options) => { */ // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. export const startFunctionsServer = async (options) => { - const { capabilities, command, config, debug, loadDistFunctions, settings, site, siteInfo, siteUrl, timeouts } = - options + const { + blobsContext, + capabilities, + command, + config, + debug, + loadDistFunctions, + settings, + site, + siteInfo, + siteUrl, + timeouts, + } = options const internalFunctionsDir = await getInternalFunctionsDir({ base: site.root }) const functionsDirectories: string[] = [] let manifest @@ -327,6 +339,7 @@ export const startFunctionsServer = async (options) => { } const functionsRegistry = new FunctionsRegistry({ + blobsContext, // @ts-expect-error TS(7031) FIXME capabilities, config, From ddadb62408b0a5f35a18f2a79ef4ae4b243652ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Mon, 8 Jan 2024 10:07:29 +0000 Subject: [PATCH 3/4] chore: add test --- .../integration/commands/dev/dev.config.test.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/integration/commands/dev/dev.config.test.js b/tests/integration/commands/dev/dev.config.test.js index 768f6938e9c..8a6f24dc7f1 100644 --- a/tests/integration/commands/dev/dev.config.test.js +++ b/tests/integration/commands/dev/dev.config.test.js @@ -1,4 +1,4 @@ -// Handlers are meant to be async outside tests +import { Buffer } from 'buffer' import { version } from 'process' import FormData from 'form-data' @@ -142,7 +142,7 @@ describe.concurrent('commands/dev/config', () => { }) }) - test('should provide CLI version in env var', async (t) => { + test('should provide environment variables to framework server', async (t) => { await withSiteBuilder('site-with-netlify-version-env-var', async (builder) => { await builder .withContentFile({ @@ -151,6 +151,7 @@ describe.concurrent('commands/dev/config', () => { http.createServer((req, res) => { res.write(JSON.stringify({ + NETLIFY_BLOBS_CONTEXT: process.env.NETLIFY_BLOBS_CONTEXT, NETLIFY_CLI_VERSION: process.env.NETLIFY_CLI_VERSION, })) res.end() @@ -171,7 +172,17 @@ describe.concurrent('commands/dev/config', () => { await withDevServer({ cwd: builder.directory }, async (server) => { const resp = await fetch(server.url) - const { NETLIFY_CLI_VERSION } = await resp.json() + const { NETLIFY_BLOBS_CONTEXT, NETLIFY_CLI_VERSION } = await resp.json() + + t.expect(NETLIFY_BLOBS_CONTEXT).toBeTypeOf('string') + + const { deployID, edgeURL, siteID, token } = JSON.parse(Buffer.from(NETLIFY_BLOBS_CONTEXT, 'base64').toString()) + + t.expect(deployID).toBe('0') + t.expect(edgeURL.startsWith('http://localhost:')).toBeTruthy() + t.expect(siteID).toBeTypeOf('string') + t.expect(token).toBeTypeOf('string') + t.expect(NETLIFY_CLI_VERSION).toMatch(/\d+\.\d+\.\d+/) }) }) From 177b81157d3c11324f2abef61818f4c68a84a728 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 11 Jan 2024 14:20:44 +0100 Subject: [PATCH 4/4] chore: add comment --- src/lib/functions/runtimes/js/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/functions/runtimes/js/index.ts b/src/lib/functions/runtimes/js/index.ts index 004afeadfdc..fd79efb6480 100644 --- a/src/lib/functions/runtimes/js/index.ts +++ b/src/lib/functions/runtimes/js/index.ts @@ -111,6 +111,7 @@ export const invokeFunctionDirectly = async ({ context, event, func, timeout }) // be available to the Lambda. This would be inconsistent with production // where only V2 functions get the context injected. To fix it, unset the // context variable before invoking the function. + // This has the side-effect of also removing the variable from `process.env`. [BLOBS_CONTEXT_VARIABLE]: undefined, }, event,