ServerlessUse

website·Indexed 29 days ago

https://serverlessuse.com/

A collection of composable functions for common serverless tasks, inspired by the Vue ecosystem. It provides utilities for managing Lambda execution scopes and API Gateway requests, including composables for handling query parameters, request/response headers, cookies, and body management via the @serverless-use/api package.

Tokens
8K
Snippets
50
Records
53
Agent score
48%

What's inside ServerlessUse

  1. Understand built-in response compression in @serverless-use/apigw

    The use handler in @serverless-use/apigw includes built-in compression. It automatically inspects request headers to determine if the response should be compressed, requiring no additional configuration for standard use cases.
  2. Understand Invocation vs Execution in ServerlessUse

    In the context of AWS Lambda and ServerlessUse, it is critical to distinguish between Invocation and Execution to manage state and caching correctly:

    • Invocation: The process of starting the lambda (Cold Start). Variables declared outside the execution scope (global scope) persist in memory as long as the lambda remains 'warm'. This allows for caching information across multiple requests but can lead to accidental data leakage between different users/requests if not handled carefully.
    • Execution: The lifetime of a single function run for a specific request. ServerlessUse manages this phase to ensure that composables are reset between requests, preventing memory leaks and ensuring that request-specific data (like query parameters or headers) does not bleed into subsequent executions.
  3. Share state globally using createSharedExecutionComposable

    The createSharedExecutionComposable utility wraps a composable function to ensure it is executed only once per execution scope. The result of the wrapped function is cached and returned for all subsequent calls within that scope, making it ideal for managing global state across different parts of the execution code.
    import { createSharedExecutionComposable } from '@serverless-use/core'
    
    type MyState = {
      name?: string
      image?: string
      profile?: string
    }
    
    export const useState = createSharedExecutionComposable(() => {
      // This function will only be run once per execution
      const state: MyState = {}
    
      // this result will be automatically cached for the execution scope
      // and returned anytime this composable is called
      return { state }
    })
  4. Manage HTTP response headers with useResponseHeaders

    The useResponseHeaders utility provides a mechanism to set and retrieve headers that will be included in the final API Gateway response. It returns an object containing set and get methods. This utility is designed to be used within a handler wrapped by the use function from @serverless-use/apigw.
    import { use, useResponseHeaders } from '@serverless-use/apigw'
    
    export const handler = use(async () => {
      const { set, get } = useResponseHeaders()
    
      // Set a header
      set('content-type', 'application/json')
    
      // Retrieve a header
      const contentType = get('content-type')
    
      return `Header is: ${contentType}`
    })
    
  5. Implement custom response compression with useCompression

    Use the useCompression utility when you need manual control over the compression process, such as specifying priority algorithms (e.g., Brotli) or custom compression parameters. To use useCompression manually, you must disable the built-in compression by passing { compression: false } as the second argument to the use handler.
    import { use, useCompression } from '@serverless-use/apigw'
    import zlib from 'zlib'
    
    export const handler = use(
      async () => {
        const { compress } = useCompression({
          priority: ['br'], // Set compression priority (e.g., Brotli)
          brotli: {
            params: {
              [zlib.constants.BROTLI_PARAM_QUALITY]: 2,
            },
          },
        })
    
        try {
          return compress({
            statusCode: 200,
            headers: {
              'Content-Type': 'text/html',
            },
            body: 'You must live your story.',
          })
        } catch (e) {
          return {
            statusCode: 400,
          }
        }
      },
      // Disable built-in compression to use custom logic
      { compression: false },
    )
    
  6. Manage response cookies with useResponseCookies

    The useResponseCookies utility allows developers to set and retrieve cookies that will be returned in the HTTP response. It is designed to work within the use wrapper from @serverless-use/apigw. Because AWS API Gateway response headers are typically JS objects (which normally prevent multiple headers of the same name), this utility handles the necessary logic to ensure multiple set-cookie headers can be sent successfully.
    import { use, useResponseCookies } from '@serverless-use/apigw'
    
    export const handler = use(async () => {
      const { get, set } = useResponseCookies()
    
      // Set a cookie
      set('name', 'Falkor')
    
      // Read a cookie
      const name = get('name')
    
      return {
        name,
        message: 'Example response',
      }
    })
    
  7. Wrap an API Gateway handler with use

    The use function is a wrapper for API Gateway handlers that manages execution scope and provides automatic result transformation. It allows you to return simplified values (like strings, booleans, or objects) which are automatically converted into valid API Gateway response objects.
    import { use } from '@serverless-use/apigw'
    
    export const handler = use(async () => {
      return {
        statusCode: 200,
        headers: {
          'Content-Type': 'text/html',
        },
        body: 'You must live your story.',
      }
    })
    
  8. Set the JSON response body using useResponseBody

    Use the body object returned by useResponseBody() to set the JSON response body. If the handler function also returns an object, the returned object will be merged with the body object. In the event of a merge conflict, the value returned by the handler takes priority over the value set in useResponseBody.
    import { use, useResponseBody } from '@serverless-use/apigw'
    
    export const handler = use(async () => {
      const { body } = useResponseBody()
      body.name = 'Atreyu'
    
      return {
        enemy: 'Gmork',
      }
    })
    // Result: { "name": "Atreyu", "enemy": "Gmork" }
  9. Register cleanup tasks using useExecution.onEnd

    Use the onEnd method provided by useExecution to register a callback function that will execute automatically when the execution scope is terminated via the end() method. This is useful for performing cleanup operations after the main logic has run.
    import { useExecution } from '@serverless-use/core'
    
    const { execute, end, onEnd } = useExecution()
    execute()
    
    onEnd(() => {
      // cleanup here will run when `end` is called 
    })
    
    // Run code here
    end()
  10. Manage Lambda execution scope with useExecution

    The useExecution utility allows developers to manually control the execution scope of a Lambda function. While this is typically managed automatically by the use function that wraps a handler, useExecution provides explicit control via execute() to start the scope and end() to terminate it.
    import { useExecution } from '@serverless-use/core'
    
    const { execute, end } = useExecution()
    execute()
    // Run code here
    end()
  11. Return HTML or Plain Text responses with useResponseBody

    The useResponseBody() utility provides html and text objects to set the response content as HTML or plain text. Assign the desired content to the .value property of these objects.
    import { use, useResponseBody } from '@serverless-use/apigw'
    
    // Returning HTML
    export const htmlHandler = use(async () => {
      const { html } = useResponseBody()
      html.value = '<h1>You must live your story.</h1>'
    })
    
    // Returning Plain Text
    export const textHandler = use(async () => {
      const { text } = useResponseBody()
      text.value = 'You must live your story.'
    })