CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-theia--core

Core framework for building cloud and desktop IDE applications using modern web technologies with TypeScript and dependency injection.

Pending
Overview
Eval results
Files

preferences-configuration.mddocs/

Preferences and Configuration

Theia's preference system provides type-safe preference management with schema definition, multiple providers, and runtime configuration changes for customizable applications.

Capabilities

Preference Service

Core service for accessing and modifying application preferences.

/**
 * Service for managing application preferences
 */
interface PreferenceService {
    /**
     * Get preference value
     * @param preferenceName - Preference identifier
     * @param defaultValue - Default value if preference not set
     * @returns Preference value or default
     */
    get<T>(preferenceName: string, defaultValue?: T): T | undefined;
    
    /**
     * Set preference value
     * @param preferenceName - Preference identifier
     * @param value - Value to set
     * @returns Promise that resolves when preference is saved
     */
    set(preferenceName: string, value: any): Promise<void>;
    
    /**
     * Check if preference has been set
     * @param preferenceName - Preference identifier
     * @returns True if preference exists
     */
    has(preferenceName: string): boolean;
    
    /**
     * Remove preference
     * @param preferenceName - Preference identifier
     * @returns Promise that resolves when preference is removed
     */
    unset(preferenceName: string): Promise<void>;
    
    /**
     * Event fired when preferences change
     */
    readonly onPreferenceChanged: Event<PreferenceChangeEvent<any>>;
    
    /**
     * Event fired when preferences are about to change
     */
    readonly onPreferencesChanged: Event<PreferenceChanges>;
}

/**
 * Service token for PreferenceService
 */
const PreferenceService: symbol;

Usage Example:

import { inject, injectable } from "@theia/core";
import { PreferenceService } from "@theia/core/lib/browser";

@injectable()
export class MyConfigurableService {
    constructor(
        @inject(PreferenceService) private readonly preferences: PreferenceService
    ) {
        // Listen for preference changes
        this.preferences.onPreferenceChanged(event => {
            if (event.preferenceName === 'myExtension.enableFeature') {
                this.updateFeatureState(event.newValue);
            }
        });
    }
    
    private updateFeatureState(enabled: boolean): void {
        console.log(`Feature ${enabled ? 'enabled' : 'disabled'}`);
    }
    
    async configure(): Promise<void> {
        // Get preference with default
        const theme = this.preferences.get('workbench.colorTheme', 'dark');
        
        // Check if preference exists
        if (!this.preferences.has('myExtension.initialized')) {
            await this.preferences.set('myExtension.initialized', true);
        }
        
        // Get typed preference
        const maxFiles = this.preferences.get<number>('files.maxOpenFiles', 50);
    }
}

Preference Schema

Define preference schemas with validation, types, and UI metadata.

/**
 * Preference schema definition
 */
interface PreferenceSchema {
    [name: string]: PreferenceSchemaProperty;
}

/**
 * Individual preference property definition
 */
interface PreferenceSchemaProperty {
    /** Property type */
    type?: 'boolean' | 'string' | 'number' | 'integer' | 'array' | 'object';
    
    /** Default value */
    default?: any;
    
    /** Human-readable description */
    description?: string;
    
    /** Allowed enum values */
    enum?: any[];
    
    /** Enum descriptions */
    enumDescriptions?: string[];
    
    /** Minimum value (numbers) */
    minimum?: number;
    
    /** Maximum value (numbers) */
    maximum?: number;
    
    /** Array item type */
    items?: PreferenceSchemaProperty;
    
    /** Object property definitions */
    properties?: { [key: string]: PreferenceSchemaProperty };
    
    /** Additional properties allowed */
    additionalProperties?: boolean | PreferenceSchemaProperty;
    
    /** Preference scope */
    scope?: PreferenceScope;
    
    /** UI order hint */
    order?: number;
    
    /** Deprecation message */
    deprecationMessage?: string;
}

/**
 * Preference scope enumeration
 */
enum PreferenceScope {
    /** User-wide preferences */
    User = 1,
    
    /** Workspace-specific preferences */
    Workspace = 2,
    
    /** Folder-specific preferences */
    Folder = 3
}

Usage Example:

import { PreferenceSchema } from "@theia/core/lib/browser";

export const myExtensionPreferenceSchema: PreferenceSchema = {
    'myExtension.enableFeature': {
        type: 'boolean',
        default: true,
        description: 'Enable the special feature',
        scope: PreferenceScope.User
    },
    
    'myExtension.maxRetries': {
        type: 'integer',
        default: 3,
        minimum: 1,
        maximum: 10,
        description: 'Maximum number of retry attempts'
    },
    
    'myExtension.theme': {
        type: 'string',
        default: 'auto',
        enum: ['light', 'dark', 'auto'],
        enumDescriptions: [
            'Light theme',
            'Dark theme', 
            'Auto-detect from system'
        ],
        description: 'Color theme preference'
    },
    
    'myExtension.excludePatterns': {
        type: 'array',
        items: {
            type: 'string'
        },
        default: ['*.tmp', '*.log'],
        description: 'File patterns to exclude'
    }
};

Preference Proxy

Type-safe preference access with automatic change detection.

/**
 * Type-safe preference proxy
 */
class PreferenceProxy<T> {
    /**
     * Event fired when preferences change
     */
    readonly onPreferenceChanged: Event<PreferenceChangeEvent<T>>;
    
    /**
     * Get all preference values
     * @returns Current preference values
     */
    getPreferences(): T;
    
    /**
     * Access preferences like object properties
     */
    [K in keyof T]: T[K];
}

/**
 * Create preference proxy
 * @param preferences - Preference service
 * @param schema - Preference schema
 * @returns Type-safe preference proxy
 */
function createPreferenceProxy<T>(
    preferences: PreferenceService,
    schema: PreferenceSchema
): PreferenceProxy<T>;

Usage Example:

interface MyExtensionConfig {
    enableFeature: boolean;
    maxRetries: number;
    theme: 'light' | 'dark' | 'auto';
    excludePatterns: string[];
}

@injectable()
export class MyConfigurableService {
    private readonly config: PreferenceProxy<MyExtensionConfig>;
    
    constructor(
        @inject(PreferenceService) preferences: PreferenceService
    ) {
        this.config = createPreferenceProxy(preferences, myExtensionPreferenceSchema);
        
        // Listen for specific preference changes
        this.config.onPreferenceChanged(event => {
            if (event.preferenceName === 'myExtension.enableFeature') {
                this.handleFeatureToggle(event.newValue);
            }
        });
    }
    
    private handleFeatureToggle(enabled: boolean): void {
        // Type-safe access to preferences
        console.log(`Feature ${enabled ? 'enabled' : 'disabled'}`);
        console.log(`Max retries: ${this.config.maxRetries}`);
        console.log(`Theme: ${this.config.theme}`);
        console.log(`Exclude patterns: ${this.config.excludePatterns.join(', ')}`);
    }
}

Preference Providers

Extensible preference provider system for different preference sources.

/**
 * Preference provider interface
 */
interface PreferenceProvider {
    /**
     * Get preference value
     * @param preferenceName - Preference name
     * @returns Preference value or undefined
     */
    get<T>(preferenceName: string): T | undefined;
    
    /**
     * Set preference value
     * @param preferenceName - Preference name
     * @param value - Value to set
     * @returns Promise that resolves when saved
     */
    set(preferenceName: string, value: any): Promise<boolean>;
    
    /**
     * Get all preference names
     * @returns Array of preference names
     */
    getPreferenceNames(): string[];
    
    /**
     * Event fired when preferences change
     */
    readonly onDidPreferencesChanged: Event<PreferenceChanges>;
    
    /**
     * Provider domain (user, workspace, folder)
     */
    readonly domain: PreferenceDomain;
}

/**
 * Preference domain types
 */
type PreferenceDomain = 'user' | 'workspace' | 'folder';

/**
 * Service token for PreferenceProvider
 */
const PreferenceProvider: symbol;

Configuration Files

Support for various configuration file formats.

/**
 * JSON preference provider for .json config files
 */
class JsonPreferenceProvider implements PreferenceProvider {
    constructor(uri: URI, scope: PreferenceScope);
    
    get<T>(preferenceName: string): T | undefined;
    set(preferenceName: string, value: any): Promise<boolean>;
    getPreferenceNames(): string[];
    
    readonly onDidPreferencesChanged: Event<PreferenceChanges>;
    readonly domain: PreferenceDomain;
}

/**
 * Workspace preference provider
 */
class WorkspacePreferenceProvider extends JsonPreferenceProvider {
    constructor(workspaceUri: URI);
}

/**
 * User preference provider
 */
class UserPreferenceProvider extends JsonPreferenceProvider {
    constructor();
}

Events and Changes

Preference Change Events

Detailed information about preference changes.

/**
 * Event fired when a preference changes
 */
interface PreferenceChangeEvent<T> {
    /** Name of the preference that changed */
    readonly preferenceName: string;
    
    /** New preference value */
    readonly newValue: T | undefined;
    
    /** Previous preference value */
    readonly oldValue: T | undefined;
    
    /** Preference scope that changed */
    readonly scope: PreferenceScope;
    
    /** Domain where change occurred */
    readonly domain: PreferenceDomain;
}

/**
 * Collection of preference changes
 */
interface PreferenceChanges {
    [preferenceName: string]: PreferenceChange;
}

/**
 * Individual preference change
 */
interface PreferenceChange {
    /** New value */
    readonly newValue: any;
    
    /** Old value */
    readonly oldValue: any;
    
    /** Change scope */
    readonly scope: PreferenceScope;
}

Advanced Usage

Custom Preference Providers

Create custom providers for specialized preference sources.

import { injectable } from "@theia/core";
import { PreferenceProvider, PreferenceChanges } from "@theia/core/lib/browser";

@injectable()
export class DatabasePreferenceProvider implements PreferenceProvider {
    readonly domain = 'user';
    private readonly onDidPreferencesChangedEmitter = new Emitter<PreferenceChanges>();
    readonly onDidPreferencesChanged = this.onDidPreferencesChangedEmitter.event;
    
    async get<T>(preferenceName: string): Promise<T | undefined> {
        // Load from database
        return this.database.getPreference(preferenceName);
    }
    
    async set(preferenceName: string, value: any): Promise<boolean> {
        const oldValue = await this.get(preferenceName);
        await this.database.setPreference(preferenceName, value);
        
        // Fire change event
        this.onDidPreferencesChangedEmitter.fire({
            [preferenceName]: {
                newValue: value,
                oldValue,
                scope: PreferenceScope.User
            }
        });
        
        return true;
    }
    
    getPreferenceNames(): string[] {
        return this.database.getAllPreferenceNames();
    }
}

Types

/**
 * Preference-related type definitions
 */
type PreferenceValue = string | number | boolean | object | undefined;

type PreferenceInspection<T> = {
    preferenceName: string;
    defaultValue?: T;
    globalValue?: T;
    workspaceValue?: T;
    folderValue?: T;
    value?: T;
};

interface PreferenceConfiguration {
    [name: string]: PreferenceValue;
}

Install with Tessl CLI

npx tessl i tessl/npm-theia--core

docs

application-framework.md

commands.md

dependency-injection.md

events-messaging.md

index.md

keybindings.md

menus.md

preferences-configuration.md

resources-files.md

widgets-ui.md

tile.json