CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jupyterlab--application

JupyterLab application framework providing the core application class, shell management, plugin system, layout restoration, and routing capabilities.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

service-tokens.mddocs/

Service Tokens

Dependency injection tokens for service-based architecture, enabling loose coupling and extensibility in the plugin system.

Capabilities

IConnectionLost Token

Service token and interface for handling server connection failures with customizable dialog behavior.

/**
 * Connection lost handler function type
 * @param manager - Service manager instance
 * @param err - Network error that occurred
 * @param translator - Optional translator for internationalization
 * @returns Promise resolving when handling is complete
 */
type IConnectionLost = (
  manager: ServiceManager.IManager,
  err: ServerConnection.NetworkError,
  translator?: ITranslator
) => Promise<void>;

/**
 * Service token for connection lost handling
 */
const IConnectionLost: Token<IConnectionLost>;

Usage Examples:

import { IConnectionLost } from "@jupyterlab/application";
import { JupyterFrontEndPlugin } from "@jupyterlab/application";

// Using connection lost service in a plugin
const connectionPlugin: JupyterFrontEndPlugin<void> = {
  id: 'my-connection-plugin',
  autoStart: true,
  requires: [IConnectionLost],
  activate: (app, connectionLost: IConnectionLost) => {
    // Monitor service manager for connection issues
    app.serviceManager.connectionFailure.connect(async (sender, err) => {
      await connectionLost(app.serviceManager, err);
    });
  }
};

// Providing custom connection lost handler
const customConnectionLostPlugin: JupyterFrontEndPlugin<IConnectionLost> = {
  id: 'custom-connection-lost',
  provides: IConnectionLost,
  activate: (app) => {
    return async (manager, err, translator) => {
      // Custom connection lost handling
      console.error('Connection lost:', err.message);
      
      // Show custom dialog or notification
      const dialog = document.createElement('div');
      dialog.textContent = 'Connection to server lost. Attempting to reconnect...';
      document.body.appendChild(dialog);
      
      // Attempt reconnection
      try {
        await manager.ready;
        dialog.remove();
      } catch (reconnectErr) {
        dialog.textContent = 'Failed to reconnect. Please refresh the page.';
      }
    };
  }
};

ILabStatus Token

Service token and interface for managing application busy and dirty states with reactive signals.

/**
 * Application status management interface
 */
interface ILabStatus {
  /** Signal emitted when application busy state changes */
  readonly busySignal: ISignal<JupyterFrontEnd<any, any>, boolean>;
  
  /** Signal emitted when application dirty state changes */
  readonly dirtySignal: ISignal<JupyterFrontEnd<any, any>, boolean>;
  
  /** Whether the application is currently busy */
  readonly isBusy: boolean;
  
  /** Whether the application has unsaved changes */
  readonly isDirty: boolean;
  
  /**
   * Set the application state to busy
   * @returns A disposable used to clear the busy state for the caller
   */
  setBusy(): IDisposable;
  
  /**
   * Set the application state to dirty
   * @returns A disposable used to clear the dirty state for the caller
   */
  setDirty(): IDisposable;
}

/**
 * Service token for application status management
 */
const ILabStatus: Token<ILabStatus>;

Usage Examples:

import { ILabStatus } from "@jupyterlab/application";
import { JupyterFrontEndPlugin } from "@jupyterlab/application";

// Using status service in a plugin
const statusPlugin: JupyterFrontEndPlugin<void> = {
  id: 'my-status-plugin',
  autoStart: true,
  requires: [ILabStatus],
  activate: (app, status: ILabStatus) => {
    // Listen to status changes
    status.busySignal.connect((sender, isBusy) => {
      console.log('Application busy state:', isBusy);
      // Update UI (e.g., show/hide spinner)
      document.body.classList.toggle('busy', isBusy);
    });
    
    status.dirtySignal.connect((sender, isDirty) => {
      console.log('Application dirty state:', isDirty);
      // Update UI (e.g., show unsaved indicator)
      document.title = isDirty ? '• My App' : 'My App';
    });
    
    // Set busy state during long operations
    const performLongOperation = async () => {
      const busyDisposable = status.setBusy();
      try {
        await someAsyncOperation();
      } finally {
        busyDisposable.dispose(); // Clear busy state
      }
    };
    
    // Set dirty state when content changes
    const handleContentChange = () => {
      const dirtyDisposable = status.setDirty();
      // Keep the disposable until content is saved
      return dirtyDisposable;
    };
  }
};

IRouter Token

Service token for URL routing functionality (covered in detail in URL Routing documentation).

/**
 * Service token for URL router
 */
const IRouter: Token<IRouter>;

/**
 * URL routing service interface
 */
interface IRouter {
  readonly base: string;
  readonly commands: CommandRegistry;
  readonly current: IRouter.ILocation;
  readonly routed: ISignal<IRouter, IRouter.ILocation>;
  readonly stop: Token<void>;
  navigate(path: string, options?: IRouter.INavOptions): void;
  register(options: IRouter.IRegisterOptions): IDisposable;
  reload(): void;
  route(url: string): void;
}

ILayoutRestorer Token

Service token for layout restoration functionality (covered in detail in Layout Restoration documentation).

/**
 * Service token for layout restoration
 */
const ILayoutRestorer: Token<ILayoutRestorer>;

/**
 * Layout restoration service interface
 */
interface ILayoutRestorer extends IRestorer {
  readonly restored: Promise<void>;
  add(widget: Widget, name: string): void;
  restore<T extends Widget>(
    tracker: WidgetTracker<T>,
    options: IRestorer.IOptions<T>
  ): Promise<any>;
}

IMimeDocumentTracker Token

Service token for tracking MIME document widgets across the application.

/**
 * MIME document widget tracker interface
 */
interface IMimeDocumentTracker extends IWidgetTracker<MimeDocument> {
  // Inherits all IWidgetTracker methods for tracking MimeDocument widgets
}

/**
 * Service token for MIME document tracker
 */
const IMimeDocumentTracker: Token<IMimeDocumentTracker>;

Usage Examples:

import { IMimeDocumentTracker } from "@jupyterlab/application";
import { JupyterFrontEndPlugin } from "@jupyterlab/application";

const mimeTrackerPlugin: JupyterFrontEndPlugin<void> = {
  id: 'my-mime-tracker-plugin',
  autoStart: true,
  requires: [IMimeDocumentTracker],
  activate: (app, tracker: IMimeDocumentTracker) => {
    // Listen for new MIME documents
    tracker.widgetAdded.connect((sender, widget) => {
      console.log('New MIME document added:', widget.context.path);
    });
    
    // Access current MIME document
    const current = tracker.currentWidget;
    if (current) {
      console.log('Current MIME document:', current.title.label);
    }
    
    // Find specific MIME documents
    const htmlDocs = tracker.filter(widget => 
      widget.context.path.endsWith('.html')
    );
    console.log(`Found ${htmlDocs.length} HTML documents`);
  }
};

ITreePathUpdater Token

Service token for updating tree path information in the application.

/**
 * Tree path updater function type
 * @param treePath - New tree path to set
 */
type ITreePathUpdater = (treePath: string) => void;

/**
 * Service token for tree path updating
 */
const ITreePathUpdater: Token<ITreePathUpdater>;

Usage Examples:

import { ITreePathUpdater } from "@jupyterlab/application";
import { JupyterFrontEndPlugin } from "@jupyterlab/application";

const pathUpdaterPlugin: JupyterFrontEndPlugin<void> = {
  id: 'my-path-updater-plugin',
  autoStart: true,
  requires: [ITreePathUpdater],
  activate: (app, updatePath: ITreePathUpdater) => {
    // Update path when navigating
    const navigateToPath = (newPath: string) => {
      updatePath(newPath);
      console.log('Updated tree path to:', newPath);
    };
    
    // Example usage
    navigateToPath('/notebooks/analysis.ipynb');
    navigateToPath('/data/dataset.csv');
  }
};

Application-Specific Tokens

Additional service tokens from the JupyterFrontEnd namespace.

/**
 * Service token for application paths configuration
 */
const IPaths: Token<JupyterFrontEnd.IPaths>;

/**
 * Service token for tree resolver functionality
 */
const ITreeResolver: Token<JupyterFrontEnd.ITreeResolver>;

Plugin Integration Patterns

Common patterns for using service tokens in plugin development.

Basic Service Usage

// Single service dependency
const basicPlugin: JupyterFrontEndPlugin<void> = {
  id: 'basic-service-plugin',
  autoStart: true,
  requires: [ILabStatus],
  activate: (app, status: ILabStatus) => {
    // Use the service
    const disposable = status.setBusy();
    // ... do work
    disposable.dispose();
  }
};

Multiple Service Dependencies

// Multiple service dependencies
const multiServicePlugin: JupyterFrontEndPlugin<void> = {
  id: 'multi-service-plugin',
  autoStart: true,
  requires: [ILabStatus, IRouter, ILayoutRestorer],
  activate: (app, status: ILabStatus, router: IRouter, restorer: ILayoutRestorer) => {
    // Use multiple services together
    router.routed.connect(() => {
      const busyDisposable = status.setBusy();
      
      // Restore layout after routing
      restorer.restored.then(() => {
        busyDisposable.dispose();
      });
    });
  }
};

Optional Service Dependencies

// Optional service dependencies
const optionalServicePlugin: JupyterFrontEndPlugin<void> = {
  id: 'optional-service-plugin',
  autoStart: true,
  requires: [ILabStatus],
  optional: [IRouter],
  activate: (app, status: ILabStatus, router: IRouter | null) => {
    // Required service is always available
    status.setBusy();
    
    // Optional service might be null
    if (router) {
      router.navigate('/optional-feature');
    } else {
      console.log('Router not available, using fallback');
    }
  }
};

Providing Custom Services

// Providing a service implementation
const serviceProviderPlugin: JupyterFrontEndPlugin<IConnectionLost> = {
  id: 'custom-connection-lost-provider',
  provides: IConnectionLost,
  activate: (app): IConnectionLost => {
    return async (manager, err, translator) => {
      // Custom implementation
      console.error('Custom connection lost handler:', err);
    };
  }
};

// Overriding default service
const overrideServicePlugin: JupyterFrontEndPlugin<ILabStatus> = {
  id: 'custom-status-provider',
  provides: ILabStatus,
  activate: (app): ILabStatus => {
    // Return custom implementation
    return new CustomLabStatus(app);
  }
};

Service Composition

// Composing services to create higher-level functionality
const compositeServicePlugin: JupyterFrontEndPlugin<IMyCompositeService> = {
  id: 'composite-service',
  provides: IMyCompositeService,
  requires: [ILabStatus, IRouter, ILayoutRestorer],
  activate: (app, status, router, restorer): IMyCompositeService => {
    return new MyCompositeService(status, router, restorer);
  }
};

interface IMyCompositeService {
  navigateWithBusyState(path: string): Promise<void>;
  saveAndNavigate(path: string): Promise<void>;
}

class MyCompositeService implements IMyCompositeService {
  constructor(
    private status: ILabStatus,
    private router: IRouter,
    private restorer: ILayoutRestorer
  ) {}
  
  async navigateWithBusyState(path: string): Promise<void> {
    const busyDisposable = this.status.setBusy();
    try {
      this.router.navigate(path);
      await this.restorer.restored;
    } finally {
      busyDisposable.dispose();
    }
  }
  
  async saveAndNavigate(path: string): Promise<void> {
    const dirtyDisposable = this.status.setDirty();
    try {
      // Save current state
      await this.saveCurrentState();
      dirtyDisposable.dispose();
      
      // Navigate to new path
      await this.navigateWithBusyState(path);
    } catch (error) {
      // Keep dirty state if save failed
      throw error;
    }
  }
  
  private async saveCurrentState(): Promise<void> {
    // Implementation for saving state
  }
}

Service Token Best Practices

Token Definition

// Good: Descriptive token with documentation
const IMyService: Token<IMyService> = new Token<IMyService>(
  '@myapp/myservice:IMyService',
  'A service for managing custom functionality in my application.'
);

// Good: Interface with clear contracts
interface IMyService {
  /** Initialize the service */
  initialize(): Promise<void>;
  
  /** Clean up resources */
  dispose(): void;
}

Error Handling

// Service with proper error handling
const robustServicePlugin: JupyterFrontEndPlugin<void> = {
  id: 'robust-service-plugin',
  requires: [ILabStatus],
  activate: (app, status: ILabStatus) => {
    try {
      // Service initialization
      const disposable = status.setBusy();
      
      // Handle service errors gracefully
      status.busySignal.connect((sender, isBusy) => {
        if (isBusy) {
          // Set up error recovery
          setTimeout(() => {
            if (status.isBusy) {
              console.warn('Operation taking longer than expected');
            }
          }, 5000);
        }
      });
      
    } catch (error) {
      console.error('Failed to initialize service:', error);
      // Graceful degradation
    }
  }
};

docs

application-framework.md

index.md

layout-restoration.md

mime-rendering.md

service-tokens.md

shell-management.md

status-management.md

url-routing.md

utility-functions.md

tile.json