ƒun

repository·main·Indexed 21 days ago

https://github.com/vercel/fun

A local development runtime for serverless functions that mimics the AWS Lambda execution environment. It allows developers to invoke Lambda functions locally using `createFunction`, supporting various runtimes for Node.js, Python, Go, and custom executables. The library provides tools for managing function lifecycles, handling Lambda-style errors via `LambdaError`, and configuring execution parameters such as memory size, timeouts, and environment variables.

Tokens
3.4K
Snippets
10
Records
14
Agent score
77%

What's inside @vercel/fun

  1. Understand the ƒun execution environment limitations

    main

    While ƒun closely resembles the AWS Lambda environment, be aware of these differences:

    • User Identity: Processes run as your current local user, not the sbx_user1051 user used in AWS.
    • Sandboxing: Processes are not sandboxed or chrooted. Do not use hard-coded paths like /var/task, /var/runtime, or /opt. Instead, use the environment variables LAMBDA_TASK_ROOT and LAMBDA_RUNTIME_DIR to locate files.
    • Process Freezing: Processes are frozen/unfrozen using SIGSTOP and SIGCONT signals rather than the cgroup freezer.
    • Native Binaries: For runtimes like Go, binaries must be compiled for your local operating system (e.g., macOS) to run locally.
  2. Invoke Lambda functions locally with createFunction

    main

    Use createFunction from @vercel/fun to start a local serverless execution environment that mimics AWS Lambda. You can specify the function's source code (via Directory or ZipFile), the entry point Handler, the Runtime, environment variables, and MemorySize.

    Once created, the returned function instance can be invoked by passing a payload. To clean up processes and shut down the API server, call fn.destroy().

    import { createFunction } from '@vercel/fun';
    
    async function main() {
    	// Starts up the necessary server to be able to invoke the function
    	const fn = await createFunction({
    		Code: {
    			// `ZipFile` works, or an already unzipped directory may be specified
    			Directory: __dirname + '/example'
    		},
    		Handler: 'index.handler',
    		Runtime: 'nodejs8.10',
    		Environment: {
    			Variables: {
    				HELLO: 'world'
    			}
    		},
    		MemorySize: 512
    	});
    
    	// Invoke the function with a custom payload
    	const res = await fn({ hello: 'world' });
    
    	console.log(res);
    
    	// Clean up processes and shut down the API server
    	await fn.destroy();
    }
    
    main().catch(console.error);
  3. Configure createFunction options

    main

    When calling createFunction, you can provide an options object with the following keys:

    • Code: An object containing either Directory (path to an unzipped directory) or ZipFile (a zip file).
    • Handler: The entry point for the function (e.g., 'index.handler').
    • Runtime: The Lambda runtime identifier (e.g., 'nodejs8.10', 'python3.7').
    • Environment: An object containing Variables to set environment variables for the function.
    • MemorySize: The amount of memory allocated to the function.
  4. Supported Runtimes in ƒun

    main

    ƒun supports a wide range of runtimes. Use the corresponding string identifier in the Runtime option of createFunction:

    Node.js

    • nodejs: Uses the system node binary
    • nodejs6.10: Uses a downloaded Node v6.10.0 binary
    • nodejs8.10: Uses a downloaded Node v8.10.0 binary
    • nodejs10.x: Uses a downloaded Node v10.15.3 binary
    • nodejs12.x: Uses a downloaded Node v12.22.7 binary
    • nodejs14.x: Uses a downloaded Node v14.18.1 binary

    Python

    • python: Uses the system python binary
    • python2.7: Uses a downloaded Python v2.7.12 binary
    • python3: Uses the system python3 binary (or fallback to python)
    • python3.6: Uses a downloaded Python v3.6.8 binary
    • python3.7: Uses a downloaded Python v3.7.2 binary

    Other

    • go1.x: For Go functions (binary must be compiled for your platform)
    • provided: For custom runtimes
    • executable: For executables powered by Fluid compute
  5. Handle environment variable validation errors

    main

    When calling createFunction, if you attempt to set environment variables that are reserved by AWS Lambda, the library throws a ValidationError. This error contains a reserved property which is an array of the offending variable names.

    Reserved variables include: _HANDLER, LAMBDA_TASK_ROOT, LAMBDA_RUNTIME_DIR, AWS_EXECUTION_ENV, AWS_DEFAULT_REGION, AWS_REGION, AWS_LAMBDA_LOG_GROUP_NAME, AWS_LAMBDA_LOG_STREAM_NAME, AWS_LAMBDA_FUNCTION_NAME, AWS_LAMBDA_FUNCTION_MEMORY_SIZE, AWS_LAMBDA_FUNCTION_VERSION, AWS_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, and TZ.

    try {
      await createFunction(params);
    } catch (err) {
      if (err instanceof ValidationError) {
        console.error('Forbidden env vars:', err.reserved);
      }
    }
  6. Create a Lambda function with createFunction()

    main

    Use createFunction(params: LambdaParams) to initialize a new Lambda instance. This function selects the appropriate provider (defaulting to 'native') and runtime based on the provided parameters. It also handles environment variable validation, ensuring no reserved AWS Lambda environment variables are included.

    Key behaviors:

    • Runtime Initialization: Automatically calls initializeRuntime for the specified runtime.
    • Environment Validation: Throws a ValidationError if any keys in params.Environment.Variables match the reserved AWS list (e.g., _HANDLER, AWS_REGION, TZ).
    • Code Extraction: If params.Code.ZipFile is provided, the function is automatically unzipped to a temporary directory.
    • Returned Object: Returns a Lambda function that can be called directly with a payload, or used via its attached properties like .invoke() and .destroy().
    import { createFunction } from '@vercel/fun';
    
    const fn = await createFunction({
      FunctionName: 'my-function',
      Runtime: 'nodejs18.x', // Example runtime
      Provider: 'native',
      Code: { ZipFile: buffer },
      Environment: {
        Variables: {
          MY_VAR: 'hello'
        }
      }
    });
    
    // You can call the function directly
    const result = await fn({ key: 'value' });
  7. Clean the global fun cache directory

    main

    Use cleanCacheDir() to delete the entire funCacheDir. This is useful for clearing out cached runtimes or artifacts stored by the library.

    import { cleanCacheDir } from '@vercel/fun';
    
    await cleanCacheDir();
  8. Cleanup resources with destroy()

    main

    The destroy(fn: Lambda) function performs cleanup for a specific Lambda instance. It executes two main tasks:

    1. Calls the underlying provider's destroy() method.
    2. If the function was created from a ZipFile, it recursively deletes the temporary directory where the code was extracted (fn.extractedDir).
    import { destroy } from '@vercel/fun';
    
    await destroy(fn);
  9. Handle Lambda execution failures with LambdaError

    main

    When dealing with failures during Lambda runtime initialization or execution, you can use the LambdaError class to wrap error details. This class allows you to reconstruct an error from a payload containing an error message, an error type, and a stack trace (either as a single string or an array of strings).

    Constructing a LambdaError with a payload ensures that the name and stack properties are correctly set to match the original runtime error, which is useful for consistent error reporting and troubleshooting.

    import { LambdaError } from './errors';
    
    const error = new LambdaError({
      errorMessage: 'Database connection failed',
      errorType: 'RuntimeError',
      stackTrace: ['Error: connection timeout at line 10', 'at main.ts:5:1']
    });
    
    console.log(error.name);    // 'RuntimeError'
    console.log(error.message); // 'Database connection failed'
    console.log(error.stack);   // 'RuntimeError: Database connection failed\nError: connection timeout at line 10\nat main.ts:5:1'
  10. Invoke a Lambda function with invoke()

    main

    The invoke(fn: Lambda, params: InvokeParams) function allows you to trigger a specific Lambda instance using custom invocation parameters. This is useful when you need to control the InvocationType (e.g., 'RequestResponse' vs 'Event') or pass specific Payload configurations that differ from the standard direct call.

    import { invoke } from '@vercel/fun';
    
    const result = await invoke(fn, {
      InvocationType: 'RequestResponse',
      Payload: JSON.stringify({ key: 'value' })
    });
  11. Configure LambdaParams for function deployment

    main

    The LambdaParams interface defines the configuration for a Lambda function. Use this to specify the code source, runtime environment, and resource constraints.

    Key Configuration Options:

    • Code: Must provide either a ZipFile (as a Buffer or string) or a Directory path.
    • Runtime: Specifies the execution environment (e.g., nodejs, python3.7, go1.x, provided).
    • MemorySize: The amount of memory in MB. Must be a multiple of 64 MB. Increasing memory also increases CPU allocation. Default is 128 MB.
    • Timeout: Execution time limit in seconds. Default is 3 seconds; maximum is 900 seconds.
    • Provider: Choose between native or docker.
    • Environment: An object containing Variables for environment variables.
    • AccessKeyId & SecretAccessKey: AWS credentials used for authentication via the AWS SDK.
    const params: LambdaParams = {
      FunctionName: 'my-function',
      Code: { Directory: './dist' },
      Handler: 'index.handler',
      Runtime: 'nodejs12.x',
      MemorySize: 512,
      Timeout: 30,
      Environment: { Variables: { NODE_ENV: 'production' } }
    };
  12. Understand the InvokeResult response format

    main

    The InvokeResult object is returned after an invocation. It follows the AWS Lambda API response structure.

    Fields:

    • StatusCode: The HTTP status code of the request.
    • FunctionError: If present, indicates whether the error was 'Handled' or 'Unhandled' by the function.
    • LogResult: The execution log string.
    • Payload: The data returned by the function (as Buffer, Blob, or string).
    • ExecutedVersion: The version of the function that was executed.