Theia workspace extension providing workspace functionality and services for Eclipse Theia IDE framework
—
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.
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();
}
}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");
}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();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")
);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");
}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");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();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);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