npm package: @schematize/util-serverless
Description: Schematize Serverless Utilities Library
Author: Benjamin Bytheway
Latest version: 0.6.3

# @schematize/util-serverless

Utility functions for Schematize Serverless functions.  This package provides simple helpers for creating streaming handlers and managing response streams with automatic gzip compression.

## Features

- **Streaming Response Support**: Create streaming Serverless function handlers for large responses
- **Automatic Gzip Compression**: Built-in gzip compression for better performance
- **File Streaming**: Stream files directly to clients with proper headers
- **Response Management**: Simple API for writing headers, status codes, and cookies
- **Error Handling**: Automatic cleanup of streams on errors

## Dependencies

- `@schematize/util-common`: Common utility functions for MIME type mapping

## Installation

```bash
npm install @schematize/util-serverless
```

## Usage

```javascript
import { createStreamingHandler, streamResponse, streamFile } from '@schematize/util-serverless';

// Create a streaming Serverless function handler
export const handler = createStreamingHandler(async ({ event, streamResponse }) => {
  await streamResponse({
    statusCode: 200,
    headers: { 'content-type': 'application/json' },
    body: Buffer.from(JSON.stringify({ message: 'Hello World' }))
  });
});
```

## API Reference

### createStreamingHandler(fn)

Creates a streaming Serverless function handler that wraps your function with streaming capabilities.

#### Parameters

- `fn` (Function): Your handler function that receives streaming utilities

#### Returns

- `Function`: Serverless function streaming handler

#### Usage

```javascript
export const handler = createStreamingHandler(async ({ 
  event, 
  context, 
  streamResponse, 
  streamFile,
  writeHead,
  responseStream 
}) => {
  // Your handler logic here
});
```

#### Handler Function Parameters

The handler function receives an object with the following parameters:

- **`event`** (Object): The incoming event object containing request data, headers, body, etc.
- **`context`** (Object): The runtime context object with information about the function execution
- **`streamResponse`** (Function): Convenience function to stream a complete response with headers and body
- **`streamFile`** (Function): Convenience function to stream a file from the filesystem to the client
- **`writeHead`** (Function): Low-level function to write response headers, status code, and cookies
- **`responseStream`** (Stream): The raw response stream for fine-grained control over the response

### event

The event object contains the incoming request data.  For HTTP requests, it typically includes:

```javascript
{
  httpMethod: 'GET',
  path: '/api/users',
  headers: {
    'content-type': 'application/json',
    'authorization': 'Bearer token123'
  },
  queryStringParameters: {
    page: '1',
    limit: '10'
  },
  body: '{"name": "John Doe"}',
  isBase64Encoded: false
}
```

### context

The context object provides information about the function execution environment:

```javascript
{
  functionName: 'my-function',
  functionVersion: '$LATEST',
  memoryLimitInMB: '128',
  remainingTimeInMillis: 30000,
  // etc...
}
```

### streamResponse

Convenience function to send a complete response with headers and body.  Automatically handles gzip compression.

#### Parameters

- `responseStream` (Stream): The response stream
- `statusCode` (Number): HTTP status code
- `headers` (Object): Response headers
- `cookies` (Object): Response cookies
- `body` (Buffer): Response body
- `requestHeaders` (Object): the request headers
- `shouldGzipResponse` (Boolean): Whether to gzip the response (default: true) (NOTE: if the request's `accept-encoding` header does not contain `gzip` it will skip zipping the response)

#### Usage

```javascript
await streamResponse({
  responseStream,
  statusCode: 200,
  headers: { 'content-type': 'application/json' },
  body: Buffer.from(JSON.stringify(data))
});
```

### streamFile

Streams a file to the client with automatic MIME type detection and caching headers.

#### Parameters

- `responseStream` (Stream): The response stream
- `statusCode` (Number): HTTP status code
- `headers` (Object): Response headers
- `cookies` (Object): Response cookies
- `filePath` (String): Path to the file to stream
- `requestHeaders` (Object): the request headers
- `shouldGzipResponse` (Boolean): Whether to gzip the response (default: true) (NOTE: if the request's `accept-encoding` header does not contain `gzip` it will skip zipping the response)

#### Usage

```javascript
await streamFile({
  responseStream,
  filePath: '/path/to/file.html',
  headers: { 'cache-control': 'max-age=3600' }
});
```

### writeHead

Low-level function to write response headers, status code, and cookies to the stream.  Use this for fine-grained control over the response.

#### Parameters

- `responseStream` (Stream): The response stream
- `statusCode` (Number): HTTP status code
- `headers` (Object): Response headers
- `cookies` (Object): Response cookies

#### Usage

```javascript
writeHead({
  responseStream,
  statusCode: 200,
  headers: { 'content-type': 'text/html' },
  cookies: { sessionId: 'abc123' }
});
```

### responseStream

The raw response stream for maximum control over the response.  Use this when you need to stream data incrementally or have complex streaming requirements.

**Usage:**
```javascript
export const handler = createStreamingHandler(async ({ event, writeHead, responseStream }) => {
  // Write headers
  writeHead({
    statusCode: 200,
    headers: { 'content-type': 'application/json' }
  });
  
  // Stream JSON array incrementally
  responseStream.write('[');
  
  for (let i = 0; i < 1000; i++) {
    const item = { id: i, data: `item-${i}` };
    responseStream.write(JSON.stringify(item));
    
    if (i < 999) {
      responseStream.write(',');
    }
    
    // Add delay to demonstrate streaming
    await new Promise(resolve => setTimeout(resolve, 10));
  }
  
  responseStream.write(']');
  responseStream.end();
});
```

## License

MIT

## Author

Benjamin Bytheway