Skip to main content

Workspace Lifecycle

This document defines the lifecycle operations for Morphir workspaces: creation, opening, closing, and configuration management.

Overview

Workspace lifecycle operations manage the overall state of a workspace session. A workspace must be opened before any project operations can be performed.

State Machine

                    ┌─────────────────┐
│ (none) │
└────────┬────────┘
│ create / open

┌─────────────────┐
│ initializing │
└────────┬────────┘

┌──────────────┴──────────────┐
│ success │ failure
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ open │ │ error │
└────────┬────────┘ └────────┬────────┘
│ close │ close
└──────────────┬──────────────┘

┌─────────────────┐
│ closed │
└─────────────────┘

Types

WorkspaceState

/// Workspace lifecycle state
pub type WorkspaceState {
/// Workspace is not active
Closed
/// Workspace is being initialized
Initializing
/// Workspace is ready for operations
Open
/// Workspace has unrecoverable errors
Error
}

WorkspaceInfo

/// Complete workspace information
pub type WorkspaceInfo {
WorkspaceInfo(
/// Absolute path to workspace root
root: String,
/// Workspace name (from config or derived from root)
name: String,
/// Current lifecycle state
state: WorkspaceState,
/// Projects in this workspace
projects: List(ProjectInfo),
/// Workspace-level configuration
config: Option(Document),
)
}

WorkspaceError

/// Errors that can occur during workspace operations
pub type WorkspaceError {
/// Workspace directory not found
NotFound(path: String)
/// Workspace already exists at path
AlreadyExists(path: String)
/// No workspace is currently open
NotOpen
/// Invalid workspace configuration
InvalidConfig(message: String)
/// IO error during operation
IoError(message: String)
}

Operations

Create Workspace

Creates a new workspace at the specified path.

Behavior

  1. Verify path does not already contain a workspace
  2. Create morphir.toml with initial configuration
  3. Create .morphir/ directory for cache and state
  4. Transition to Open state
  5. Return workspace info

WIT Interface

/// Create a new workspace
create-workspace: func(
/// Workspace root path (must not exist or be empty)
root: string,
/// Initial configuration (optional)
config: option<document-value>,
) -> result<workspace-info, workspace-error>;

JSON-RPC

Request:

{
"method": "workspace/create",
"params": {
"root": "/path/to/workspace",
"config": {
"name": "my-workspace"
}
}
}

Response:

{
"result": {
"root": "/path/to/workspace",
"name": "my-workspace",
"state": "open",
"projects": []
}
}

CLI

morphir workspace init [path]
morphir workspace init --name my-workspace

Open Workspace

Opens an existing workspace for operations.

Behavior

  1. Locate morphir.toml (search upward if needed)
  2. Parse workspace configuration
  3. Discover projects in workspace
  4. Load project metadata (not full IR)
  5. Transition to Open state
  6. Return workspace info

WIT Interface

/// Open an existing workspace
open-workspace: func(
/// Workspace root path
root: string,
) -> result<workspace-info, workspace-error>;

JSON-RPC

Request:

{
"method": "workspace/open",
"params": {
"root": "/path/to/workspace"
}
}

Response:

{
"result": {
"root": "/path/to/workspace",
"name": "my-workspace",
"state": "open",
"projects": [
{
"name": "my-org/core",
"version": "1.0.0",
"path": "packages/core",
"state": "unloaded",
"sourceDir": "src"
}
]
}
}

CLI

morphir workspace open [path]
cd /path/to/workspace && morphir workspace open

Close Workspace

Closes the current workspace, releasing resources.

Behavior

  1. Stop file watching if active
  2. Unload all projects
  3. Flush any pending state
  4. Transition to Closed state

WIT Interface

/// Close the current workspace
close-workspace: func() -> result<_, workspace-error>;

JSON-RPC

Request:

{
"method": "workspace/close",
"params": {}
}

Response:

{
"result": null
}

Get Workspace Info

Returns current workspace state and information.

WIT Interface

/// Get current workspace info
get-workspace-info: func() -> result<workspace-info, workspace-error>;

JSON-RPC

Request:

{
"method": "workspace/info",
"params": {}
}

Update Configuration

Updates workspace-level configuration.

Behavior

  1. Validate new configuration
  2. Merge with existing configuration
  3. Write updated morphir.toml
  4. Notify affected projects if needed

WIT Interface

/// Update workspace configuration
update-workspace-config: func(
config: document-value,
) -> result<_, workspace-error>;

JSON-RPC

Request:

{
"method": "workspace/updateConfig",
"params": {
"config": {
"defaultSourceDir": "lib",
"outputDir": "dist"
}
}
}

Configuration

See Configuration System for full configuration documentation.

morphir.toml

[morphir]
version = "^4.0.0"

[workspace]
# Output directory for workspace-level artifacts
output_dir = ".morphir"

# Glob patterns for discovering member projects
members = ["packages/*"]

# Patterns to exclude from discovery
exclude = ["packages/deprecated-*"]

# Default member when no project specified
default_member = "packages/core"

# Shared dependencies (resolved once for all projects)
[workspace.dependencies]
"morphir/sdk" = "3.0.0"

# Default settings inherited by all projects
[ir]
format_version = 4

[codegen]
targets = ["typescript"]

Error Handling

ErrorCauseRecovery
NotFoundPath doesn't exist or has no workspaceUse create instead
AlreadyExistsWorkspace already at pathUse open instead
NotOpenOperation requires open workspaceCall open first
InvalidConfigMalformed configuration fileFix configuration
IoErrorFile system errorCheck permissions

Best Practices

  1. Single Active Workspace: Only one workspace should be open per daemon instance
  2. Workspace Discovery: Search upward for morphir.toml to support nested directories
  3. Graceful Degradation: If workspace config is missing, treat directory as single-project workspace
  4. State Persistence: Save workspace state to .morphir/state.json for session recovery