@@ -20,6 +20,8 @@ const SERVER_HANDLER_NAME = '___netlify-server-handler'
2020 * @property {string } [url] TThe relative path that should be requested. Defaults to '/'
2121 * @property {Record<string, string> } [headers] The headers used for the invocation
2222 * @property {Record<string, unknown> } [flags] Feature flags that should be set during the invocation
23+ *
24+ * @typedef {Pick<FunctionInvocationOptions, 'env'> } LoadFunctionOptions
2325 */
2426
2527/**
@@ -109,76 +111,87 @@ const DEFAULT_FLAGS = {}
109111
110112/**
111113 * @param {FixtureTestContext } ctx
112- * @param {FunctionInvocationOptions } options
114+ * @param {LoadFunctionOptions } options
113115 */
114- export async function loadAndInvokeFunctionImpl (
115- ctx ,
116- { headers, httpMethod, flags, url, env } = { } ,
117- ) {
116+ export async function loadFunction ( ctx , { env } = { } ) {
118117 const restoreEnvironment = temporarilySetEnv ( ctx , env )
119118
120119 const { handler } = await import (
121120 'file:///' + join ( ctx . functionDist , SERVER_HANDLER_NAME , '___netlify-entry-point.mjs' )
122121 )
123122
124- let resolveInvocation , rejectInvocation
125- const invocationPromise = new Promise ( ( resolve , reject ) => {
126- resolveInvocation = resolve
127- rejectInvocation = reject
128- } )
123+ /**
124+ * @param {FunctionInvocationOptions } options
125+ */
126+ async function invokeFunction ( { headers, httpMethod, flags, url, env : invokeEnv } = { } ) {
127+ const restoreEnvironment = temporarilySetEnv ( ctx , {
128+ ...env ,
129+ ...invokeEnv ,
130+ } )
129131
130- const response = await execute ( {
131- event : {
132- headers : {
133- // 'x-nf-debug-logging': 1,
134- ...( headers || { } ) ,
132+ let resolveInvocation , rejectInvocation
133+ const invocationPromise = new Promise ( ( resolve , reject ) => {
134+ resolveInvocation = resolve
135+ rejectInvocation = reject
136+ } )
137+
138+ const response = await execute ( {
139+ event : {
140+ headers : {
141+ // 'x-nf-debug-logging': 1,
142+ ...( headers || { } ) ,
143+ } ,
144+ httpMethod : httpMethod || 'GET' ,
145+ rawUrl : new URL ( url || '/' , 'https://example.netlify' ) . href ,
146+ flags : flags ?? DEFAULT_FLAGS ,
135147 } ,
136- httpMethod : httpMethod || 'GET' ,
137- rawUrl : new URL ( url || '/' , 'https://example.netlify' ) . href ,
138- flags : flags ?? DEFAULT_FLAGS ,
139- } ,
140- lambdaFunc : { handler } ,
141- timeoutMs : 4_000 ,
142- onInvocationEnd : ( error ) => {
143- // lambda-local resolve promise return from execute when response is closed
144- // but we should wait for tracked background work to finish
145- // before resolving the promise to allow background work to finish
146- if ( error ) {
147- rejectInvocation ( error )
148- } else {
149- resolveInvocation ( )
150- }
151- } ,
152- } )
148+ lambdaFunc : { handler } ,
149+ timeoutMs : 4_000 ,
150+ onInvocationEnd : ( error ) => {
151+ // lambda-local resolve promise return from execute when response is closed
152+ // but we should wait for tracked background work to finish
153+ // before resolving the promise to allow background work to finish
154+ if ( error ) {
155+ rejectInvocation ( error )
156+ } else {
157+ resolveInvocation ( )
158+ }
159+ } ,
160+ } )
153161
154- await invocationPromise
162+ await invocationPromise
155163
156- if ( ! response ) {
157- throw new Error ( 'No response from lambda-local' )
158- }
164+ if ( ! response ) {
165+ throw new Error ( 'No response from lambda-local' )
166+ }
159167
160- const responseHeaders = Object . entries ( response . multiValueHeaders || { } ) . reduce (
161- ( prev , [ key , value ] ) => ( {
162- ...prev ,
163- [ key ] : value . length === 1 ? `${ value } ` : value . join ( ', ' ) ,
164- } ) ,
165- response . headers || { } ,
166- )
168+ const responseHeaders = Object . entries ( response . multiValueHeaders || { } ) . reduce (
169+ ( prev , [ key , value ] ) => ( {
170+ ...prev ,
171+ [ key ] : value . length === 1 ? `${ value } ` : value . join ( ', ' ) ,
172+ } ) ,
173+ response . headers || { } ,
174+ )
167175
168- const bodyBuffer = await streamToBuffer ( response . body )
176+ const bodyBuffer = await streamToBuffer ( response . body )
169177
170- restoreEnvironment ( )
178+ restoreEnvironment ( )
171179
172- return {
173- statusCode : response . statusCode ,
174- bodyBuffer,
175- body : bodyBuffer . toString ( 'utf-8' ) ,
176- headers : responseHeaders ,
177- isBase64Encoded : response . isBase64Encoded ,
180+ return {
181+ statusCode : response . statusCode ,
182+ bodyBuffer,
183+ body : bodyBuffer . toString ( 'utf-8' ) ,
184+ headers : responseHeaders ,
185+ isBase64Encoded : response . isBase64Encoded ,
186+ }
178187 }
188+
189+ restoreEnvironment ( )
190+
191+ return invokeFunction
179192}
180193
181194/**
182- * @typedef {typeof loadAndInvokeFunctionImpl } InvokeFunction
195+ * @typedef {Awaited<ReturnType< typeof loadFunction>> } InvokeFunction
183196 * @typedef {Promise<Awaited<ReturnType<InvokeFunction>>> } InvokeFunctionResult
184197 */
0 commit comments