For programmatic trace uploads from your Node.js or browser applications, Flamedeck provides the @flamedeck/upload NPM package. This library offers a convenient function to send trace data directly to the Flamedeck API.

Installation

You can install the package using npm or yarn:

npm install @flamedeck/upload
# or
yarn add @flamedeck/upload

Basic Usage

The core of the library is the uploadTraceToApi function. You’ll need to import it along with the necessary types.

Prerequisites

Requirements:

  • API Key: You need a Flamedeck API key with trace:upload scope
  • Trace Data: Your trace data should be a File or Blob object when used in the browser, or an ArrayBuffer (e.g., from reading a file) when used in Node.js
  • Filename: The original filename for the trace

Example (Node.js)

Here’s a TypeScript example demonstrating how to upload a trace file from a Node.js environment:

import { uploadTraceToApi, UploadOptions, UploadError } from '@flamedeck/upload';
import fs from 'node:fs/promises'; // Using Node.js fs promises module
import path from 'node:path';

async function uploadMyTraceNode(filePath: string) {
  try {
    const apiKey = process.env.FLAMEDECK_API_KEY; // Recommended to use environment variables
    if (!apiKey) {
      throw new Error('FLAMEDECK_API_KEY environment variable is not set.');
    }

    const traceDataBuffer = await fs.readFile(filePath);
    const fileName = path.basename(filePath);

    const options: UploadOptions = {
      apiKey: apiKey,
      traceData: traceDataBuffer, // Pass ArrayBuffer for Node.js
      fileName: fileName,
      scenario: 'My Node.js Automated Performance Test',
      commitSha: 'abcdef1234567890',
      branch: 'main',
      notes: 'This trace was uploaded programmatically via @flamedeck/upload from Node.js.',
      folderId: 'your-optional-folder-id', // Optional: UUID of a folder
      public: true, // Optional: Make the trace publicly viewable
      // metadata: { custom_key: 'custom_value' }, // Optional
      // supabaseFunctionsUrl: 'your-custom-supabase-url' // Optional: For self-hosted or testing
    };

    console.log(`Uploading trace: ${fileName} with scenario: ${options.scenario}...`);
    const result = await uploadTraceToApi(options);

    console.log('Upload successful!');
    console.log(`Trace ID: ${result.id}`);
    console.log(`View URL: ${result.viewUrl}`);

    return result;
  } catch (error) {
    console.error('Failed to upload trace:');
    if (error instanceof UploadError) {
      console.error(`Status: ${error.status}, Message: ${error.message}`, error.details);
    } else {
      console.error('An unexpected error occurred:', error);
    }
    throw error;
  }
}

// Example usage:
// uploadMyTraceNode('/path/to/your/trace.json')
//   .then(() => console.log('Node.js upload process finished.'))
//   .catch(() => console.error('Node.js upload process failed.'));

Example (Browser)

When using in a browser environment (e.g., from a file input):

import { uploadTraceToApi, UploadOptions, UploadError } from '@flamedeck/upload';

async function handleFileUpload(file: File) {
  const apiKey = 'YOUR_FLAMEDECK_API_KEY'; // Obtain securely

  const options: UploadOptions = {
    apiKey: apiKey,
    traceData: file, // Pass a File or Blob object directly
    fileName: file.name,
    scenario: 'Browser Upload Example',
    commitSha: 'abcdef1',
    public: false,
    metadata: { client: 'web-app', userId: 'current_user_id' }
  };

  try {
    const result = await uploadTraceToApi(options);
    console.log('Upload successful! View URL:', result.viewUrl);
    // Update UI accordingly
  } catch (error) {
    console.error('Upload failed:');
    if (error instanceof UploadError) {
      console.error(`Status: ${error.status}, Message: ${error.message}`, error.details);
      // Update UI with error details
    } else {
      console.error('An unexpected error occurred:', error);
    }
  }
}

// Assuming 'fileInput' is an <input type="file" /> element:
// const fileInput = document.getElementById('fileInput');
// fileInput.addEventListener('change', (event) => {
//   const file = (event.target as HTMLInputElement).files?.[0];
//   if (file) {
//     handleFileUpload(file);
//   }
// });

UploadOptions Interface

The uploadTraceToApi function accepts an options object conforming to the UploadOptions interface:

apiKey
string
required

Your Flamedeck API key.

traceData
Blob | ArrayBuffer
required

The content of the trace file. Use File/Blob for browser, ArrayBuffer for Node.js.

fileName
string
required

The original filename.

scenario
string
required

A descriptive name for the trace.

commitSha
string

The Git commit SHA associated with this trace.

branch
string

The Git branch name associated with this trace.

notes
string

Free-form text notes to attach to the trace.

folderId
string

The UUID of an existing folder to upload the trace into.

public
boolean
default:"false"

Set to true to make the trace publicly accessible. Defaults to false (private).

metadata
Record<string, unknown> | string

Custom key-value metadata to associate with the trace.

supabaseFunctionsUrl
string

Override the default Supabase functions base URL (for self-hosted or testing).

For detailed descriptions of optional fields like commitSha, branch, notes, folderId, and metadata, please refer to the CLI Upload documentation, as they serve the same purpose.

Error Handling

The uploadTraceToApi function will throw an UploadError if the upload fails. This custom error object contains:

  • status: HTTP status code (if applicable)
  • message: Error message
  • details: Additional error information from the API

Always wrap your upload calls in try-catch blocks to handle potential errors gracefully.