or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

extension-points.mdindex.mdworkspace-commands.mdworkspace-file-handling.mdworkspace-preferences.mdworkspace-server.mdworkspace-service.md

workspace-service.mddocs/

0

# Workspace Service

1

2

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.

3

4

## Capabilities

5

6

### Service Initialization

7

8

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

9

10

```typescript { .api }

11

/**

12

* Promise that resolves when the service is ready to use

13

*/

14

readonly ready: Promise<void>;

15

16

/**

17

* Promise that resolves to the workspace root folders

18

*/

19

readonly roots: Promise<FileStat[]>;

20

21

/**

22

* Get synchronous access to current roots (may be empty if not ready)

23

*/

24

tryGetRoots(): FileStat[];

25

```

26

27

**Usage Example:**

28

29

```typescript

30

import { injectable, inject } from "@theia/core/shared/inversify";

31

import { WorkspaceService } from "@theia/workspace/lib/browser";

32

33

@injectable()

34

export class MyService {

35

36

@inject(WorkspaceService)

37

protected readonly workspaceService: WorkspaceService;

38

39

async initialize(): Promise<void> {

40

// Wait for service to be ready

41

await this.workspaceService.ready;

42

43

// Get workspace roots

44

const roots = await this.workspaceService.roots;

45

console.log(`Workspace has ${roots.length} root folders`);

46

47

// Or get roots synchronously (may be empty if not ready)

48

const syncRoots = this.workspaceService.tryGetRoots();

49

}

50

}

51

```

52

53

### Workspace State Management

54

55

Access to current workspace state and properties.

56

57

```typescript { .api }

58

/**

59

* Current workspace file or directory (synchronous access)

60

*/

61

readonly workspace: FileStat | undefined;

62

63

/**

64

* Returns true if theia has an opened workspace or folder

65

*/

66

readonly opened: boolean;

67

68

/**

69

* Returns true if a multiple-root workspace is currently open

70

*/

71

readonly isMultiRootWorkspaceOpened: boolean;

72

73

/**

74

* True if the current workspace is configured using a configuration file.

75

* False if there is no workspace or the workspace is simply a folder.

76

*/

77

readonly saved: boolean;

78

```

79

80

**Usage Example:**

81

82

```typescript

83

// Check workspace state

84

if (this.workspaceService.opened) {

85

if (this.workspaceService.isMultiRootWorkspaceOpened) {

86

console.log("Multi-root workspace is open");

87

} else {

88

console.log("Single folder workspace is open");

89

}

90

91

if (this.workspaceService.saved) {

92

console.log("Workspace is saved as a .theia-workspace file");

93

console.log(`Workspace file: ${this.workspaceService.workspace?.uri}`);

94

}

95

} else {

96

console.log("No workspace is currently open");

97

}

98

```

99

100

### Workspace Opening and Closing

101

102

Core workspace lifecycle operations.

103

104

```typescript { .api }

105

/**

106

* Opens directory, or recreates a workspace from the file that `uri` points to.

107

* @param uri - URI of the directory or workspace file to open

108

* @param options - Options for opening the workspace

109

*/

110

open(uri: URI, options?: WorkspaceInput): void;

111

112

/**

113

* Clears current workspace root.

114

*/

115

close(): Promise<void>;

116

117

/**

118

* Save workspace data into a file

119

* @param uri - URI or FileStat of the workspace file

120

*/

121

save(uri: URI | FileStat): Promise<void>;

122

```

123

124

**Usage Example:**

125

126

```typescript

127

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

128

129

// Open a folder as workspace

130

const folderUri = new URI("file:///path/to/project");

131

this.workspaceService.open(folderUri);

132

133

// Open a workspace file

134

const workspaceUri = new URI("file:///path/to/project.theia-workspace");

135

this.workspaceService.open(workspaceUri, { preserveWindow: true });

136

137

// Save current workspace to a file

138

const saveUri = new URI("file:///path/to/my-workspace.theia-workspace");

139

await this.workspaceService.save(saveUri);

140

141

// Close current workspace

142

await this.workspaceService.close();

143

```

144

145

### Root Folder Management

146

147

Managing workspace root folders for multi-root workspaces.

148

149

```typescript { .api }

150

/**

151

* Adds root folder(s) to the workspace

152

* @param uris - URI or URIs of the root folder(s) to add

153

*/

154

addRoot(uris: URI[] | URI): Promise<void>;

155

156

/**

157

* Removes root folder(s) from workspace.

158

* @param uris - URIs of the root folders to remove

159

*/

160

removeRoots(uris: URI[]): Promise<void>;

161

162

/**

163

* Splice roots - remove and/or add roots at specific position

164

* @param start - Starting index for splice operation

165

* @param deleteCount - Number of roots to remove (optional)

166

* @param rootsToAdd - URIs of roots to add at the start position

167

*/

168

spliceRoots(start: number, deleteCount?: number, ...rootsToAdd: URI[]): Promise<URI[]>;

169

```

170

171

**Usage Example:**

172

173

```typescript

174

// Add a single root folder

175

const newRoot = new URI("file:///path/to/additional-project");

176

await this.workspaceService.addRoot(newRoot);

177

178

// Add multiple root folders

179

const roots = [

180

new URI("file:///path/to/project-a"),

181

new URI("file:///path/to/project-b")

182

];

183

await this.workspaceService.addRoot(roots);

184

185

// Remove specific roots

186

const rootsToRemove = [new URI("file:///path/to/old-project")];

187

await this.workspaceService.removeRoots(rootsToRemove);

188

189

// Replace the first root with a new one

190

const newRoots = await this.workspaceService.spliceRoots(

191

0, 1, new URI("file:///path/to/replacement-project")

192

);

193

```

194

195

### Workspace Utilities

196

197

Utility methods for workspace path operations and validation.

198

199

```typescript { .api }

200

/**

201

* Return true if one of the paths in paths array is present in the workspace

202

* NOTE: You should always explicitly use `/` as the separator between the path segments.

203

* @param paths - Array of paths to check

204

*/

205

containsSome(paths: string[]): Promise<boolean>;

206

207

/**

208

* Returns the workspace root uri that the given file belongs to.

209

* In case that the file is found in more than one workspace roots, returns the root that is closest to the file.

210

* If the file is not from the current workspace, returns `undefined`.

211

* @param uri - URI of the file

212

*/

213

getWorkspaceRootUri(uri: URI | undefined): URI | undefined;

214

215

/**

216

* Returns the relative path of the given file to the workspace root.

217

* @param uri - URI of the file

218

*/

219

getWorkspaceRelativePath(uri: URI): Promise<string>;

220

221

/**

222

* Check if the given URIs are workspace roots

223

* @param uris - URIs to check

224

*/

225

areWorkspaceRoots(uris: URI[]): boolean;

226

227

/**

228

* Check if the given URI is an untitled workspace

229

* @param candidate - URI to check (optional, defaults to current workspace)

230

*/

231

isUntitledWorkspace(candidate?: URI): boolean;

232

233

/**

234

* Check if it's safe to reload with the given URI

235

* @param withURI - URI to check for reload safety

236

*/

237

isSafeToReload(withURI?: URI): Promise<boolean>;

238

```

239

240

**Usage Example:**

241

242

```typescript

243

// Check if workspace contains specific paths

244

const hasPackageJson = await this.workspaceService.containsSome(['package.json']);

245

const hasSourceFiles = await this.workspaceService.containsSome(['src/main.ts', 'lib/index.js']);

246

247

// Get workspace root for a file

248

const fileUri = new URI("file:///workspace/src/components/button.tsx");

249

const rootUri = this.workspaceService.getWorkspaceRootUri(fileUri);

250

if (rootUri) {

251

console.log(`File belongs to workspace root: ${rootUri}`);

252

}

253

254

// Get relative path within workspace

255

const relativePath = await this.workspaceService.getWorkspaceRelativePath(fileUri);

256

console.log(`Relative path: ${relativePath}`); // e.g., "src/components/button.tsx"

257

258

// Check if URIs are workspace roots

259

const someUris = [new URI("file:///project-a"), new URI("file:///project-b")];

260

if (this.workspaceService.areWorkspaceRoots(someUris)) {

261

console.log("These URIs are workspace roots");

262

}

263

264

// Check if workspace is untitled

265

if (this.workspaceService.isUntitledWorkspace()) {

266

console.log("Current workspace is untitled");

267

}

268

```

269

270

### Recent Workspaces Management

271

272

Managing the list of recently used workspaces.

273

274

```typescript { .api }

275

/**

276

* Get recent workspaces list

277

*/

278

recentWorkspaces(): Promise<string[]>;

279

280

/**

281

* Remove a workspace from recent workspaces list

282

* @param uri - URI string of the workspace to remove

283

*/

284

removeRecentWorkspace(uri: string): Promise<void>;

285

```

286

287

**Usage Example:**

288

289

```typescript

290

// Get list of recent workspaces

291

const recentWorkspaces = await this.workspaceService.recentWorkspaces();

292

console.log("Recent workspaces:", recentWorkspaces);

293

294

// Remove a workspace from recent list

295

await this.workspaceService.removeRecentWorkspace("file:///old/workspace/path");

296

```

297

298

### Event Handling

299

300

Events fired when workspace state changes.

301

302

```typescript { .api }

303

/**

304

* Event fired when workspace roots change

305

*/

306

readonly onWorkspaceChanged: Event<FileStat[]>;

307

308

/**

309

* Event fired when workspace location changes (e.g., when saving untitled workspace)

310

*/

311

readonly onWorkspaceLocationChanged: Event<FileStat | undefined>;

312

```

313

314

**Usage Example:**

315

316

```typescript

317

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

318

319

// Listen to workspace changes

320

const disposable1: Disposable = this.workspaceService.onWorkspaceChanged(roots => {

321

console.log(`Workspace roots changed. New count: ${roots.length}`);

322

roots.forEach((root, index) => {

323

console.log(`Root ${index}: ${root.uri}`);

324

});

325

});

326

327

// Listen to workspace location changes

328

const disposable2: Disposable = this.workspaceService.onWorkspaceLocationChanged(workspace => {

329

if (workspace) {

330

console.log(`Workspace location changed to: ${workspace.uri}`);

331

} else {

332

console.log("Workspace was closed");

333

}

334

});

335

336

// Don't forget to dispose listeners when done

337

disposable1.dispose();

338

disposable2.dispose();

339

```

340

341

### Schema Management

342

343

Managing workspace configuration schemas.

344

345

```typescript { .api }

346

/**

347

* Update workspace schema

348

* @param key - The property key under which to store the schema (e.g. tasks, launch)

349

* @param schema - The schema for the property. If none is supplied, the update is treated as a deletion.

350

*/

351

updateSchema(key: string, schema?: IJSONSchema): Promise<boolean>;

352

```

353

354

**Usage Example:**

355

356

```typescript

357

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

358

359

// Add a custom schema for workspace configuration

360

const customSchema: IJSONSchema = {

361

type: "object",

362

properties: {

363

customTool: {

364

type: "object",

365

properties: {

366

enabled: { type: "boolean" },

367

settings: { type: "object" }

368

}

369

}

370

}

371

};

372

373

const success = await this.workspaceService.updateSchema("customTool", customSchema);

374

if (success) {

375

console.log("Schema updated successfully");

376

}

377

378

// Remove a schema by passing undefined

379

await this.workspaceService.updateSchema("customTool", undefined);

380

```

381

382

## Types

383

384

```typescript { .api }

385

interface WorkspaceInput {

386

/**

387

* Tests whether the same window should be used or a new one has to be opened after setting the workspace root.

388

* By default it is `false`.

389

*/

390

preserveWindow?: boolean;

391

}

392

393

interface WorkspaceData {

394

folders: Array<{ path: string; name?: string }>;

395

[key: string]: { [id: string]: any };

396

}

397

398

namespace WorkspaceData {

399

/**

400

* Type guard to check if data is WorkspaceData

401

*/

402

function is(data: unknown): data is WorkspaceData;

403

404

/**

405

* Build workspace data from folders and additional fields

406

*/

407

function buildWorkspaceData(folders: string[] | FileStat[], additionalFields?: Partial<WorkspaceData>): WorkspaceData;

408

409

/**

410

* Transform workspace data to relative paths

411

*/

412

function transformToRelative(data: WorkspaceData, workspaceFile?: FileStat): WorkspaceData;

413

414

/**

415

* Transform workspace data to absolute paths

416

*/

417

function transformToAbsolute(data: WorkspaceData, workspaceFile?: BaseStat): WorkspaceData;

418

}

419

```