CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-backstage--types

Common TypeScript types used within Backstage for JSON handling and reactive programming patterns

99

1.67x
Quality

Pending

Does it follow best practices?

Impact

99%

1.67x

Average score across 5 eval scenarios

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

Backstage Types

Backstage Types provides essential TypeScript type definitions that serve as common building blocks throughout the Backstage ecosystem. It includes foundational JSON types for type-safe handling of JSON data structures and Observable types for reactive programming patterns following the TC39 Observable proposal.

Package Information

  • Package Name: @backstage/types
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @backstage/types

Core Imports

import { JsonValue, JsonObject, JsonArray, JsonPrimitive } from "@backstage/types";
import { Observable, Observer, Subscription } from "@backstage/types";

For CommonJS:

const { JsonValue, JsonObject, JsonArray, JsonPrimitive } = require("@backstage/types");
const { Observable, Observer, Subscription } = require("@backstage/types");

Basic Usage

import { JsonValue, JsonObject, Observable, Observer } from "@backstage/types";

// Type-safe JSON handling
const config: JsonObject = {
  name: "my-plugin",
  enabled: true,
  settings: {
    timeout: 5000,
    retries: 3
  }
};

const data: JsonValue = ["item1", "item2", { nested: true }];

// Observable pattern usage
const observer: Observer<string> = {
  next: (value) => console.log(`Received: ${value}`),
  error: (err) => console.error(`Error: ${err.message}`),
  complete: () => console.log("Stream completed")
};

// Subscribe to an observable (using compatible implementation like zen-observable)
const subscription: Subscription = someObservable.subscribe(observer);

// Clean up subscription
subscription.unsubscribe();

Architecture

Backstage Types is designed as a foundational layer providing standardized type definitions across the Backstage ecosystem:

  • JSON Type System: Recursive type definitions ensuring type safety for all JSON data structures
  • Observable Contracts: Implementation-agnostic interfaces following TC39 specification for reactive programming
  • Zero Runtime Dependencies: Pure TypeScript type definitions with no runtime overhead
  • Cross-Platform Compatibility: Works consistently across frontend and backend environments

Capabilities

JSON Type Safety

Provides comprehensive type definitions for all JSON value types, enabling type-safe JSON handling across frontend and backend Backstage components.

/** A type representing all allowed JSON primitive values */
type JsonPrimitive = number | string | boolean | null;

/** A type representing all allowed JSON object values */
type JsonObject = { [key in string]?: JsonValue };

/** A type representing all allowed JSON array values */
interface JsonArray extends Array<JsonValue> {}

/** A type representing all allowed JSON values */
type JsonValue = JsonObject | JsonArray | JsonPrimitive;

Usage Examples:

import { JsonValue, JsonObject, JsonPrimitive } from "@backstage/types";

// Type-safe API responses
function processApiResponse(response: JsonValue): void {
  if (typeof response === "object" && response !== null && !Array.isArray(response)) {
    // TypeScript knows this is JsonObject
    const obj = response as JsonObject;
    console.log(obj.status);
  }
}

// Configuration handling
interface PluginConfig extends JsonObject {
  name: string;
  version: string;
  settings?: JsonObject;
}

const config: PluginConfig = {
  name: "my-backstage-plugin",
  version: "1.0.0",
  settings: {
    enabled: true,
    timeout: 30000
  }
};

// Primitive value handling
function validatePrimitive(value: unknown): JsonPrimitive | null {
  if (typeof value === "string" || typeof value === "number" || 
      typeof value === "boolean" || value === null) {
    return value;
  }
  return null;
}

Reactive Programming Types

Provides standardized Observable types following the TC39 Observable proposal, enabling consistent reactive programming patterns across Backstage plugins and extensions.

/** Observer interface for consuming an Observable, see TC39 */
type Observer<T> = {
  next?(value: T): void;
  error?(error: Error): void;
  complete?(): void;
};

/** Subscription returned when subscribing to an Observable, see TC39 */
type Subscription = {
  /** Cancels the subscription */
  unsubscribe(): void;
  /** Value indicating whether the subscription is closed */
  readonly closed: boolean;
};

/** Observable sequence of values and errors, see TC39 */
type Observable<T> = {
  [Symbol.observable](): Observable<T>;
  /** Subscribes to this observable to start receiving new values */
  subscribe(observer: Observer<T>): Subscription;
  subscribe(
    onNext?: (value: T) => void,
    onError?: (error: Error) => void,
    onComplete?: () => void,
  ): Subscription;
};

Usage Examples:

import { Observable, Observer, Subscription } from "@backstage/types";

// Creating an observer
const dataObserver: Observer<string> = {
  next: (value: string) => {
    console.log(`Processing data: ${value}`);
  },
  error: (error: Error) => {
    console.error(`Data processing failed: ${error.message}`);
  },
  complete: () => {
    console.log("Data stream completed");
  }
};

// Using with zen-observable (common implementation)
import ZenObservable from 'zen-observable';

const observable: Observable<string> = new ZenObservable<string>(
  (subscriber: Observer<string>) => {
    subscriber.next?.("Hello");
    subscriber.next?.("World");
    subscriber.complete?.();
  }
);

// Subscribe with observer object
const subscription1: Subscription = observable.subscribe(dataObserver);

// Subscribe with callback functions
const subscription2: Subscription = observable.subscribe(
  (value) => console.log(`Value: ${value}`),
  (error) => console.error(`Error: ${error}`),
  () => console.log("Done!")
);

// Cleanup subscriptions
subscription1.unsubscribe();
subscription2.unsubscribe();

// Check subscription status
console.log(`Is closed: ${subscription1.closed}`);

Global Symbols

The package declares the global Symbol.observable symbol used by the Observable implementation:

declare global {
  interface SymbolConstructor {
    readonly observable: symbol;
  }
}

This declaration ensures compatibility with Observable implementations that rely on the well-known symbol, with the actual runtime polyfill typically provided by libraries like zen-observable.

Error Handling

The Observable types include built-in error handling through the Observer.error callback and the subscribe method's onError parameter. When implementing Observable consumers, always handle potential errors:

import { Observer } from "@backstage/types";

const robustObserver: Observer<any> = {
  next: (value) => {
    try {
      // Process value
      processValue(value);
    } catch (error) {
      console.error("Processing error:", error);
    }
  },
  error: (error) => {
    // Handle stream errors
    console.error("Stream error:", error);
    // Optionally attempt recovery or cleanup
  },
  complete: () => {
    console.log("Stream completed successfully");
  }
};
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@backstage/types@1.0.x
Publish Source
CLI
Badge
tessl/npm-backstage--types badge