Utilities

The MentraOS SDK provides several utility classes and functions that help with resource management and working with data streams.

ResourceTracker

ResourceTracker is a utility class used to manage the lifecycle of resources, ensuring they are properly cleaned up to prevent memory leaks.
import { ResourceTracker, createResourceTracker } from '@mentra/sdk';

Creating a ResourceTracker

const tracker = createResourceTracker();

Properties

disposed

A getter that checks if the tracker has been disposed.
get disposed(): boolean
Returns: true if the tracker has been disposed, false otherwise.

Methods

track()

Registers a cleanup function to be called when the tracker is disposed.
track(cleanup: CleanupFunction): CleanupFunction
Parameters:
  • cleanup: A function that will be called when the tracker is disposed
Returns: The same cleanup function, allowing for chaining Example:
const unsubscribe = tracker.track(() => {
  console.log('Resource cleaned up');
  // Clean up code here
});

// Later, if you want to manually clean up this specific resource:
unsubscribe();

trackDisposable()

Tracks an object that has a .dispose() or .close() method.
trackDisposable(disposable: Disposable): CleanupFunction
Parameters:
  • disposable: An object with a .dispose() or .close() method
Returns: A cleanup function that will dispose or close the object when called Example:
class MyResource {
  dispose() {
    console.log('Resource disposed');
  }
}

const resource = new MyResource();
tracker.trackDisposable(resource);

trackTimer(), trackTimeout(), trackInterval()

Track Node.js timers to ensure they are cleared when the tracker is disposed.
trackTimer(timerId: NodeJS.Timeout, isInterval?: boolean): CleanupFunction
trackTimeout(timerId: NodeJS.Timeout): CleanupFunction
trackInterval(timerId: NodeJS.Timeout): CleanupFunction
Parameters:
  • timerId: The ID returned by setTimeout or setInterval
  • isInterval: For trackTimer only - set to true if the timer is an interval
Returns: A cleanup function that will clear the timer when called Example:
const timeoutId = setTimeout(() => {
  console.log('Timeout executed');
}, 1000);

tracker.trackTimeout(timeoutId);

// Or use the convenience methods:
const intervalId = tracker.setInterval(() => {
  console.log('Interval executed');
}, 1000);

setTimeout(), setInterval()

Convenience methods that create and automatically track timers.
setTimeout(callback: (...args: any[]) => void, ms: number): NodeJS.Timeout
setInterval(callback: (...args: any[]) => void, ms: number): NodeJS.Timeout
Parameters:
  • callback: The function to execute
  • ms: The time in milliseconds to wait before execution
Returns: The timer ID, which is already being tracked Example:
// Create and track a timeout in one step
tracker.setTimeout(() => {
  console.log('Tracked timeout executed');
}, 1000);

// Create and track an interval in one step
tracker.setInterval(() => {
  console.log('Tracked interval executed');
}, 2000);

dispose()

Executes all registered cleanup functions and marks the tracker as disposed.
dispose(): void
Example:
// Clean up all tracked resources
tracker.dispose();

Example: Using ResourceTracker in a Resource Manager

class ResourceManager {
  private tracker = createResourceTracker();

  registerListener(element: HTMLElement, event: string, handler: EventListener) {
    element.addEventListener(event, handler);

    // Track the cleanup
    this.tracker.track(() => {
      element.removeEventListener(event, handler);
    });
  }

  startPolling(callback: () => void, intervalMs: number) {
    // Creates and tracks the interval automatically
    this.tracker.setInterval(callback, intervalMs);
  }

  cleanup() {
    // Dispose all tracked resources at once
    this.tracker.dispose();
  }
}

Stream Utility Functions

These utility functions help work with language-specific streams and stream types.

Language Stream Types

ExtendedStreamType

Represents either a standard StreamType enum value or a language-specific stream string.
type ExtendedStreamType = StreamType | string;

LanguageStreamInfo

Structure holding parsed information from a language-specific stream identifier string.
interface LanguageStreamInfo {
  type: StreamType.TRANSCRIPTION | StreamType.TRANSLATION;
  baseType: string;
  transcribeLanguage: string;
  translateLanguage?: string;
  original: ExtendedStreamType;
}

parseLanguageStream()

Parses a string to determine if it represents a language-specific stream and extracts its components.
function parseLanguageStream(
  subscription: ExtendedStreamType
): LanguageStreamInfo | null
Parameters:
  • subscription: The stream identifier to parse (e.g., “transcription:en-US”)
Returns: A parsed LanguageStreamInfo object, or null if the input is not a valid language-specific stream Example:
const info = parseLanguageStream("transcription:en-US");
if (info) {
  console.log(info.type);              // StreamType.TRANSCRIPTION
  console.log(info.baseType);          // "transcription"
  console.log(info.transcribeLanguage); // "en-US"
}

createTranscriptionStream()

Creates a language-specific stream identifier string for transcription.
function createTranscriptionStream(language: string): ExtendedStreamType
Parameters:
  • language: The language code (e.g., “en-US”)
Returns: The formatted stream identifier string (e.g., “transcription:en-US”) Example:
// Subscribe to English transcription
const streamId = createTranscriptionStream("en-US");
session.subscribe(streamId);

createTranslationStream()

Creates a language-specific stream identifier string for translation.
function createTranslationStream(
  sourceLanguage: string,
  targetLanguage: string
): ExtendedStreamType
Parameters:
  • sourceLanguage: The source language code (e.g., “es-ES”)
  • targetLanguage: The target language code (e.g., “en-US”)
Returns: The formatted stream identifier string (e.g., “translation:es-ES-to-en-US”) Example:
// Subscribe to Spanish-to-English translation
const streamId = createTranslationStream("es-ES", "en-US");
session.subscribe(streamId);

isValidStreamType()

Checks if a value is either a valid StreamType enum member or a valid language-specific stream string.
function isValidStreamType(subscription: ExtendedStreamType): boolean
Parameters:
  • subscription: The value to check
Returns: true if the subscription type is valid, false otherwise Example:
if (isValidStreamType(StreamType.BUTTON_PRESS)) {
  // Valid standard stream type
}

if (isValidStreamType("transcription:en-US")) {
  // Valid language-specific stream
}

getBaseStreamType()

Extracts the base StreamType enum value from an ExtendedStreamType.
function getBaseStreamType(
  subscription: ExtendedStreamType
): StreamType | null
Parameters: Returns: The base StreamType, or null if invalid Example:
const baseType = getBaseStreamType("transcription:en-US");
// Returns StreamType.TRANSCRIPTION

const standardType = getBaseStreamType(StreamType.BUTTON_PRESS);
// Returns StreamType.BUTTON_PRESS

isLanguageStream()

Checks if an ExtendedStreamType represents a language-specific stream.
function isLanguageStream(subscription: ExtendedStreamType): boolean
Parameters: Returns: true if it’s a language-specific stream format, false otherwise Example:
if (isLanguageStream("transcription:en-US")) {
  // Handle language-specific stream
} else {
  // Handle standard stream type
}

getLanguageInfo()

Convenience function equivalent to parseLanguageStream().
function getLanguageInfo(
  subscription: ExtendedStreamType
): LanguageStreamInfo | null
Parameters: Returns: Parsed info or null

Usage Patterns

Managing Language-Specific Streams

class MyAppServer extends AppServer {
  protected async onSession(session: AppSession, sessionId: string, userId: string) {
    // Subscribe to English transcription
    const enTranscription = createTranscriptionStream("en-US");
    session.subscribe(enTranscription);

    // Subscribe to Spanish-to-English translation
    const esEnTranslation = createTranslationStream("es-ES", "en-US");
    session.subscribe(esEnTranslation);

    // Process the incoming streams
    session.on(StreamType.TRANSCRIPTION, (data) => {
      // Handle all transcription data
      console.log(`Transcription: ${data.text}`);
    });

    session.on(StreamType.TRANSLATION, (data) => {
      // Handle all translation data
      console.log(`Translation: ${data.text}`);
    });
  }
}

Resource Management in App Sessions

class MyAppServer extends AppServer {
  // Store active sessions with their resource trackers
  private activeSessions = new Map<string, ResourceTracker>();

  protected async onSession(session: AppSession, sessionId: string, userId: string) {
    // Create a resource tracker for this session
    const tracker = createResourceTracker();
    this.activeSessions.set(sessionId, tracker);

    // Set up timers that will be automatically cleaned up
    tracker.setInterval(() => {
      // Periodic task
      console.log(`Session ${sessionId} is active`);
    }, 60000); // Every minute

    // Track the event handlers
    const unsubscribeBtn = session.onButtonPress((data) => {
      console.log(`Button pressed: ${data.buttonId}`);
    });

    // Make sure the unsubscribe function gets called when we clean up
    tracker.track(unsubscribeBtn);
  }

  protected async onStop(sessionId: string, userId: string, reason: string) {
    // Clean up all resources for this session
    const tracker = this.activeSessions.get(sessionId);
    if (tracker) {
      tracker.dispose();
      this.activeSessions.delete(sessionId);
    }
  }
}