newOS for Developers

Utilities

Helper functions, type guards, and data transformations used across newOS.

packages/newgraph-signals/src/utils/

XPromise

Externally resolvable promise. Unlike standard promises, XPromise can be resolved or rejected from outside the executor function.

class XPromise<T = void> {
  // Standard promise interface
  then<TResult1, TResult2>(
    onfulfilled?: (value: T) => TResult1,
    onrejected?: (reason: any) => TResult2
  ): Promise<TResult1 | TResult2>;
  
  catch<TResult>(
    onrejected?: (reason: any) => TResult
  ): Promise<T | TResult>;
  
  finally(onfinally?: () => void): Promise<T>;
  
  // External resolution
  resolve(value: T): void;
  reject(reason?: any): void;
}

Usage Example

// Create an externally resolvable promise
const xp = new XPromise<string>();

// Resolve from anywhere
setTimeout(() => {
  xp.resolve("Complete!");
}, 1000);

// Await like a normal promise
const result = await xp;
console.log(result); // "Complete!"

Common Use Cases

  • Transaction queue management in the cache system
  • Coordinating async operations across components
  • Building custom async control flow

batchAsync

Batches multiple async function calls into a single execution based on batch size and time constraints.

batchAsync<T, S extends Function, U>(
  f: S,                    // Function to batch
  opts: {
    batchSize: number;     // Max items before flush
    maxSecondsRetention: number;  // Max seconds before flush
  }
): (...params: S[]) => Promise<void>

Usage Example

// Create a batched API call
const batchedSave = batchAsync(
  async (items) => {
    await api.bulkSave(items);
  },
  { batchSize: 100, maxSecondsRetention: 5 }
);

// Items are collected and sent in batches
batchedSave(item1);
batchedSave(item2);
batchedSave(item3);
// Automatically flushes when 100 items or 5 seconds

Behavior

  • Accumulates parameters until batch size is reached
  • Sets up interval to flush after maxSecondsRetention
  • Waits for previous batch to complete before starting new one

Counters

Simple named counter utility for tracking quantities (e.g., concurrent transactions).

const counters = Counters();

counters.increment("transactions");  // 1
counters.increment("transactions");  // 2
counters.get("transactions");        // 2
counters.decrement("transactions");  // 1 (min: 0)
counters.getAll();                   // { transactions: 1 }
counters.table("Debug");             // Logs table to console
MethodDescription
increment(name)Increase counter by 1
decrement(name)Decrease counter by 1 (min: 0)
get(name)Get current value (default: 0)
getAll()Get all counters as object
table(title?)Log all counters as console.table

getBase64

Convert a File object to a base64-encoded data URL string.

function getBase64(file: File | undefined): Promise<string>

Usage Example

const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];

const base64 = await getBase64(file);
// "data:image/png;base64,iVBORw0KGgo..."

// Use for preview or upload
img.src = base64;
Error: Throws if file is undefined.

resizeImage

Resize an image blob to fit within a maximum dimension while maintaining aspect ratio.

function resizeImage(src: Blob): Promise<string>

// Default dimensions
const defaults = {
  width: 180,
  height: 180
};

Usage Example

const imageBlob = await fetch(imageUrl).then(r => r.blob());

// Resize to fit in 180x180 box
const resizedDataUrl = await resizeImage(imageBlob);

// Use for thumbnails
thumbnail.src = resizedDataUrl;

Behavior

  • Maintains aspect ratio
  • Uses createImageBitmap for high-quality resize
  • Returns base64 data URL (toDataURL)
  • Default max size: 180x180 pixels

Stats

Performance timing utility for measuring operation durations.

const stats = Stats();

stats.start("apiCall");
await fetch("/api/data");
stats.end("apiCall");

console.log(stats.get("apiCall"));      // Duration in ms
console.log(stats.getNoGap("apiCall")); // Total time since start
stats.table("Performance");              // Log all stats
MethodDescription
start(name)Start timing for named stat
end(name)Stop timing and accumulate duration
get(name)Get accumulated time in ms
getNoGap(name)Get total elapsed time since first start
showAll()Get all stats as object
table(title?)Log all stats as console.table

Advanced Usage

// Track multiple operations
stats.start("fetch");
const data = await fetchData();
stats.end("fetch");

stats.start("process");
const processed = processData(data);
stats.end("process");

stats.start("save");
await saveData(processed);
stats.end("save");

// View breakdown
stats.table("Pipeline Performance");
// | Name    | Duration (ms) |
// |---------|---------------|
// | fetch   | 245           |
// | process | 12            |
// | save    | 89            |

Summary

UtilityFilePurpose
XPromiseXPromise.tsExternally resolvable promise
batchAsyncbatchAsync.tsBatch async calls by size/time
Counterscounters.tsNamed counter tracking
getBase64getBase64.tsFile to base64 conversion
resizeImageresizeImage.tsImage thumbnail generation
Statsstats.tsPerformance timing