CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-theia--workspace

Theia workspace extension providing workspace functionality and services for Eclipse Theia IDE framework

Pending
Overview
Eval results
Files

workspace-service.mddocs/

Workspace Service

The WorkspaceService is the core service for workspace lifecycle management, providing workspace opening/closing, root folder management, and workspace state tracking. It serves as the central entry point for all workspace-related operations in Theia applications.

Capabilities

Service Initialization

Access to the service's ready state and workspace data.

/**
 * Promise that resolves when the service is ready to use
 */
readonly ready: Promise<void>;

/**
 * Promise that resolves to the workspace root folders
 */
readonly roots: Promise<FileStat[]>;

/**
 * Get synchronous access to current roots (may be empty if not ready)
 */
tryGetRoots(): FileStat[];

Usage Example:

import { injectable, inject } from "@theia/core/shared/inversify";
import { WorkspaceService } from "@theia/workspace/lib/browser";

@injectable()
export class MyService {
  
  @inject(WorkspaceService)
  protected readonly workspaceService: WorkspaceService;

  async initialize(): Promise<void> {
    // Wait for service to be ready
    await this.workspaceService.ready;
    
    // Get workspace roots
    const roots = await this.workspaceService.roots;
    console.log(`Workspace has ${roots.length} root folders`);
    
    // Or get roots synchronously (may be empty if not ready)
    const syncRoots = this.workspaceService.tryGetRoots();
  }
}

Workspace State Management

Access to current workspace state and properties.

/**
 * Current workspace file or directory (synchronous access)
 */
readonly workspace: FileStat | undefined;

/**
 * Returns true if theia has an opened workspace or folder
 */
readonly opened: boolean;

/**
 * Returns true if a multiple-root workspace is currently open
 */
readonly isMultiRootWorkspaceOpened: boolean;

/**
 * True if the current workspace is configured using a configuration file.
 * False if there is no workspace or the workspace is simply a folder.
 */
readonly saved: boolean;

Usage Example:

// Check workspace state
if (this.workspaceService.opened) {
  if (this.workspaceService.isMultiRootWorkspaceOpened) {
    console.log("Multi-root workspace is open");
  } else {
    console.log("Single folder workspace is open");
  }
  
  if (this.workspaceService.saved) {
    console.log("Workspace is saved as a .theia-workspace file");
    console.log(`Workspace file: ${this.workspaceService.workspace?.uri}`);
  }
} else {
  console.log("No workspace is currently open");
}

Workspace Opening and Closing

Core workspace lifecycle operations.

/**
 * Opens directory, or recreates a workspace from the file that `uri` points to.
 * @param uri - URI of the directory or workspace file to open
 * @param options - Options for opening the workspace
 */
open(uri: URI, options?: WorkspaceInput): void;

/**
 * Clears current workspace root.
 */
close(): Promise<void>;

/**
 * Save workspace data into a file
 * @param uri - URI or FileStat of the workspace file
 */
save(uri: URI | FileStat): Promise<void>;

Usage Example:

import URI from "@theia/core/lib/common/uri";

// Open a folder as workspace
const folderUri = new URI("file:///path/to/project");
this.workspaceService.open(folderUri);

// Open a workspace file
const workspaceUri = new URI("file:///path/to/project.theia-workspace");
this.workspaceService.open(workspaceUri, { preserveWindow: true });

// Save current workspace to a file
const saveUri = new URI("file:///path/to/my-workspace.theia-workspace"); 
await this.workspaceService.save(saveUri);

// Close current workspace
await this.workspaceService.close();

Root Folder Management

Managing workspace root folders for multi-root workspaces.

/**
 * Adds root folder(s) to the workspace
 * @param uris - URI or URIs of the root folder(s) to add
 */
addRoot(uris: URI[] | URI): Promise<void>;

/**
 * Removes root folder(s) from workspace.
 * @param uris - URIs of the root folders to remove
 */
removeRoots(uris: URI[]): Promise<void>;

/**
 * Splice roots - remove and/or add roots at specific position
 * @param start - Starting index for splice operation
 * @param deleteCount - Number of roots to remove (optional)
 * @param rootsToAdd - URIs of roots to add at the start position
 */
spliceRoots(start: number, deleteCount?: number, ...rootsToAdd: URI[]): Promise<URI[]>;

Usage Example:

// Add a single root folder
const newRoot = new URI("file:///path/to/additional-project");
await this.workspaceService.addRoot(newRoot);

// Add multiple root folders
const roots = [
  new URI("file:///path/to/project-a"),
  new URI("file:///path/to/project-b")
];
await this.workspaceService.addRoot(roots);

// Remove specific roots
const rootsToRemove = [new URI("file:///path/to/old-project")];
await this.workspaceService.removeRoots(rootsToRemove);

// Replace the first root with a new one
const newRoots = await this.workspaceService.spliceRoots(
  0, 1, new URI("file:///path/to/replacement-project")
);

Workspace Utilities

Utility methods for workspace path operations and validation.

/**
 * Return true if one of the paths in paths array is present in the workspace
 * NOTE: You should always explicitly use `/` as the separator between the path segments.
 * @param paths - Array of paths to check
 */
containsSome(paths: string[]): Promise<boolean>;

/**
 * Returns the workspace root uri that the given file belongs to.
 * In case that the file is found in more than one workspace roots, returns the root that is closest to the file.
 * If the file is not from the current workspace, returns `undefined`.
 * @param uri - URI of the file
 */
getWorkspaceRootUri(uri: URI | undefined): URI | undefined;

/**
 * Returns the relative path of the given file to the workspace root.
 * @param uri - URI of the file
 */
getWorkspaceRelativePath(uri: URI): Promise<string>;

/**
 * Check if the given URIs are workspace roots
 * @param uris - URIs to check
 */
areWorkspaceRoots(uris: URI[]): boolean;

/**
 * Check if the given URI is an untitled workspace
 * @param candidate - URI to check (optional, defaults to current workspace)
 */
isUntitledWorkspace(candidate?: URI): boolean;

/**
 * Check if it's safe to reload with the given URI
 * @param withURI - URI to check for reload safety
 */
isSafeToReload(withURI?: URI): Promise<boolean>;

Usage Example:

// Check if workspace contains specific paths
const hasPackageJson = await this.workspaceService.containsSome(['package.json']);
const hasSourceFiles = await this.workspaceService.containsSome(['src/main.ts', 'lib/index.js']);

// Get workspace root for a file
const fileUri = new URI("file:///workspace/src/components/button.tsx");
const rootUri = this.workspaceService.getWorkspaceRootUri(fileUri);
if (rootUri) {
  console.log(`File belongs to workspace root: ${rootUri}`);
}

// Get relative path within workspace
const relativePath = await this.workspaceService.getWorkspaceRelativePath(fileUri);
console.log(`Relative path: ${relativePath}`); // e.g., "src/components/button.tsx"

// Check if URIs are workspace roots
const someUris = [new URI("file:///project-a"), new URI("file:///project-b")];
if (this.workspaceService.areWorkspaceRoots(someUris)) {
  console.log("These URIs are workspace roots");
}

// Check if workspace is untitled
if (this.workspaceService.isUntitledWorkspace()) {
  console.log("Current workspace is untitled");
}

Recent Workspaces Management

Managing the list of recently used workspaces.

/**
 * Get recent workspaces list
 */
recentWorkspaces(): Promise<string[]>;

/**
 * Remove a workspace from recent workspaces list
 * @param uri - URI string of the workspace to remove
 */
removeRecentWorkspace(uri: string): Promise<void>;

Usage Example:

// Get list of recent workspaces
const recentWorkspaces = await this.workspaceService.recentWorkspaces();
console.log("Recent workspaces:", recentWorkspaces);

// Remove a workspace from recent list
await this.workspaceService.removeRecentWorkspace("file:///old/workspace/path");

Event Handling

Events fired when workspace state changes.

/**
 * Event fired when workspace roots change
 */
readonly onWorkspaceChanged: Event<FileStat[]>;

/**
 * Event fired when workspace location changes (e.g., when saving untitled workspace)  
 */
readonly onWorkspaceLocationChanged: Event<FileStat | undefined>;

Usage Example:

import { Disposable } from "@theia/core";

// Listen to workspace changes
const disposable1: Disposable = this.workspaceService.onWorkspaceChanged(roots => {
  console.log(`Workspace roots changed. New count: ${roots.length}`);
  roots.forEach((root, index) => {
    console.log(`Root ${index}: ${root.uri}`);
  });
});

// Listen to workspace location changes
const disposable2: Disposable = this.workspaceService.onWorkspaceLocationChanged(workspace => {
  if (workspace) {
    console.log(`Workspace location changed to: ${workspace.uri}`);
  } else {
    console.log("Workspace was closed");
  }
});

// Don't forget to dispose listeners when done
disposable1.dispose();
disposable2.dispose();

Schema Management

Managing workspace configuration schemas.

/**
 * Update workspace schema
 * @param key - The property key under which to store the schema (e.g. tasks, launch)
 * @param schema - The schema for the property. If none is supplied, the update is treated as a deletion.
 */
updateSchema(key: string, schema?: IJSONSchema): Promise<boolean>;

Usage Example:

import { IJSONSchema } from "@theia/core/lib/common/json-schema";

// Add a custom schema for workspace configuration
const customSchema: IJSONSchema = {
  type: "object",
  properties: {
    customTool: {
      type: "object", 
      properties: {
        enabled: { type: "boolean" },
        settings: { type: "object" }
      }
    }
  }
};

const success = await this.workspaceService.updateSchema("customTool", customSchema);
if (success) {
  console.log("Schema updated successfully");
}

// Remove a schema by passing undefined
await this.workspaceService.updateSchema("customTool", undefined);

Types

interface WorkspaceInput {
  /**
   * Tests whether the same window should be used or a new one has to be opened after setting the workspace root. 
   * By default it is `false`.
   */
  preserveWindow?: boolean;
}

interface WorkspaceData {
  folders: Array<{ path: string; name?: string }>;
  [key: string]: { [id: string]: any };
}

namespace WorkspaceData {
  /**
   * Type guard to check if data is WorkspaceData
   */
  function is(data: unknown): data is WorkspaceData;
  
  /**
   * Build workspace data from folders and additional fields
   */
  function buildWorkspaceData(folders: string[] | FileStat[], additionalFields?: Partial<WorkspaceData>): WorkspaceData;
  
  /**
   * Transform workspace data to relative paths
   */
  function transformToRelative(data: WorkspaceData, workspaceFile?: FileStat): WorkspaceData;
  
  /**
   * Transform workspace data to absolute paths
   */
  function transformToAbsolute(data: WorkspaceData, workspaceFile?: BaseStat): WorkspaceData;
}

Install with Tessl CLI

npx tessl i tessl/npm-theia--workspace

docs

extension-points.md

index.md

workspace-commands.md

workspace-file-handling.md

workspace-preferences.md

workspace-server.md

workspace-service.md

tile.json