CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-electron

Build cross-platform desktop apps with JavaScript, HTML, and CSS

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

platform-features.mddocs/

Platform-Specific Features

Platform-specific APIs for macOS, Windows, and Linux, including auto-updater, system preferences, and native integrations.

Capabilities

System Preferences

Access and monitor system preferences and theme information.

/**
 * Get system preferences
 */
interface SystemPreferences extends EventEmitter {
  /** Returns true if DarkAqua/DarkMode theme is active */
  isDarkMode(): boolean;
  
  /** Returns true if an inverted color scheme (high contrast with light text and dark backgrounds) is active */
  isInvertedColorScheme(): boolean;
  
  /** Returns true if a high contrast theme is active */
  isHighContrastColorScheme(): boolean;
  
  /** Returns the system color setting in hex format (#ABCDEF) */
  getAccentColor(): string;
  
  /** Returns the system color for the given color key */
  getSystemColor(color: SystemColor): string;
  
  /** Returns true if the Caps Lock key is currently on */
  isAeroGlassEnabled(): boolean;
  
  /** Returns the standard system color formatted as #RRGGBBAA for the given color */
  getColor(color: string): string;
  
  /** Returns true if the current process is a trusted accessibility client */
  isTrustedAccessibilityClient(prompt: boolean): boolean;
  
  /** Retrieves a macOS system preference value by key */
  getUserDefault(key: string, type: 'string' | 'boolean' | 'integer' | 'float' | 'double' | 'url' | 'array' | 'dictionary'): any;
  
  /** Set a macOS system preference value by key */
  setUserDefault(key: string, type: string, value: string): void;
  
  /** Removes the key in macOS system preferences */
  removeUserDefault(key: string): void;
  
  /** Returns true if the macOS system's Reduce Motion accessibility preference is enabled */
  isSwipeTrackingFromScrollEventsEnabled(): boolean;
  
  /** Posts event to macOS accessibility API */
  postNotification(event: string, userInfo: Record<string, any>, deliverImmediately?: boolean): void;
  
  /** Posts a local notification event to macOS accessibility API */
  postLocalNotification(event: string, userInfo: Record<string, any>): void;
  
  /** Posts a workspace notification event to macOS accessibility API */
  postWorkspaceNotification(event: string, userInfo: Record<string, any>): void;
  
  /** Subscribes to native macOS notifications */
  subscribeNotification(event: string, callback: (event: string, userInfo: Record<string, any>, object: string) => void): number;
  
  /** Same as subscribeNotification, but uses NSNotificationCenter's addObserverForName:object:queue:usingBlock: for local notifications */
  subscribeLocalNotification(event: string, callback: (event: string, userInfo: Record<string, any>, object: string) => void): number;
  
  /** Same as subscribeNotification, but uses NSWorkspace.sharedWorkspace.notificationCenter */
  subscribeWorkspaceNotification(event: string, callback: (event: string, userInfo: Record<string, any>, object: string) => void): number;
  
  /** Removes the subscriber with id */
  unsubscribeNotification(id: number): void;
  
  /** Same as unsubscribeNotification, but removes the subscriber from NSNotificationCenter */
  unsubscribeLocalNotification(id: number): void;
  
  /** Same as unsubscribeNotification, but removes the subscriber from NSWorkspace.sharedWorkspace.notificationCenter */
  unsubscribeWorkspaceNotification(id: number): void;
  
  /** Returns an object with system animation settings */
  getAnimationSettings(): AnimationSettings;
  
  /** A string property that can be dark, light or unknown */
  readonly effectiveAppearance: string;
  
  /** A string property that can be dark, light or unknown */
  readonly appLevelAppearance: string;
}

declare const systemPreferences: SystemPreferences;

Usage Examples:

const { systemPreferences, nativeTheme } = require('electron');

// Monitor system theme changes
function setupThemeMonitoring() {
  // Check current theme
  const isDark = systemPreferences.isDarkMode();
  console.log('System is in dark mode:', isDark);
  
  // Listen for theme changes
  systemPreferences.on('accent-color-changed', (event, newColor) => {
    console.log('Accent color changed:', newColor);
    updateAppTheme(newColor);
  });
  
  systemPreferences.on('color-changed', (event) => {
    console.log('System colors changed');
    updateAppColors();
  });
  
  systemPreferences.on('inverted-color-scheme-changed', (event, invertedColorScheme) => {
    console.log('Inverted color scheme:', invertedColorScheme);
    updateAppForAccessibility(invertedColorScheme);
  });
  
  systemPreferences.on('high-contrast-color-scheme-changed', (event, highContrastColorScheme) => {
    console.log('High contrast mode:', highContrastColorScheme);
    updateAppForHighContrast(highContrastColorScheme);
  });
}

// Get system colors
function getSystemColors() {
  const colors = {
    accent: systemPreferences.getAccentColor(),
    windowBackground: systemPreferences.getSystemColor('window'),
    text: systemPreferences.getSystemColor('windowText'),
    highlight: systemPreferences.getSystemColor('highlight'),
    secondaryText: systemPreferences.getSystemColor('secondaryLabelColor')
  };
  
  console.log('System colors:', colors);
  return colors;
}

// macOS specific features
function setupMacOSFeatures() {
  if (process.platform !== 'darwin') return;
  
  // Check accessibility permissions
  const isTrusted = systemPreferences.isTrustedAccessibilityClient(false);
  if (!isTrusted) {
    console.log('App needs accessibility permissions');
    // Prompt user for permissions
    systemPreferences.isTrustedAccessibilityClient(true);
  }
  
  // Subscribe to workspace notifications
  const workspaceId = systemPreferences.subscribeWorkspaceNotification(
    'NSWorkspaceDidWakeNotification',
    (event, userInfo) => {
      console.log('System woke from sleep');
      handleSystemWake();
    }
  );
  
  // Subscribe to application notifications
  const appId = systemPreferences.subscribeNotification(
    'AppleInterfaceThemeChangedNotification',
    (event, userInfo) => {
      console.log('Interface theme changed');
      updateAppTheme();
    }
  );
  
  // Get/set user defaults
  const launchAtLogin = systemPreferences.getUserDefault('LSUIElement', 'boolean');
  console.log('Launch at login:', launchAtLogin);
  
  // Set a custom preference
  systemPreferences.setUserDefault('MyAppPreference', 'string', 'customValue');
  
  return { workspaceId, appId };
}

Auto Updater

Automatic application updates using platform-specific update mechanisms.

/**
 * Enable apps to automatically update themselves
 */
interface AutoUpdater extends EventEmitter {
  /** Sets the url and initialize the auto updater */
  setFeedURL(options: FeedURLOptions): void;
  
  /** Returns the current update feed URL */
  getFeedURL(): string;
  
  /** Asks the server whether there is an update */
  checkForUpdates(): void;
  
  /** Asks the server whether there is an update, returns a boolean */
  checkForUpdatesAndNotify(): Promise<UpdateCheckResult | null>;
  
  /** Restarts the app and installs the update after it has been downloaded */
  quitAndInstall(): void;
  
  /** Returns the current application version */
  getSupportedDirectoryTypes(): string[];
}

declare const autoUpdater: AutoUpdater;

Usage Examples:

const { autoUpdater, app, dialog } = require('electron');

// Setup auto-updater
function setupAutoUpdater() {
  // Configure update feed
  autoUpdater.setFeedURL({
    url: 'https://updates.myapp.com/releases',
    headers: {
      'User-Agent': `MyApp/${app.getVersion()}`
    }
  });
  
  // Handle update events
  autoUpdater.on('checking-for-update', () => {
    console.log('Checking for updates...');
    showUpdateStatus('Checking for updates...');
  });
  
  autoUpdater.on('update-available', (info) => {
    console.log('Update available:', info);
    showUpdateStatus('Update available - downloading...');
  });
  
  autoUpdater.on('update-not-available', (info) => {
    console.log('Update not available:', info);
    showUpdateStatus('App is up to date');
  });
  
  autoUpdater.on('error', (err) => {
    console.error('Update error:', err);
    dialog.showErrorBox('Update Error', err.message);
  });
  
  autoUpdater.on('download-progress', (progressObj) => {
    const { bytesPerSecond, percent, transferred, total } = progressObj;
    console.log(`Download progress: ${percent.toFixed(2)}%`);
    showUpdateProgress(percent);
  });
  
  autoUpdater.on('update-downloaded', (info) => {
    console.log('Update downloaded:', info);
    showUpdateReadyDialog();
  });
  
  // Check for updates on startup
  setTimeout(() => {
    autoUpdater.checkForUpdates();
  }, 3000);
  
  // Check for updates every hour
  setInterval(() => {
    autoUpdater.checkForUpdates();
  }, 60 * 60 * 1000);
}

// Show update ready dialog
function showUpdateReadyDialog() {
  const response = dialog.showMessageBoxSync(null, {
    type: 'info',
    title: 'Update Ready',
    message: 'A new version has been downloaded.',
    detail: 'The application will restart to apply the update.',
    buttons: ['Restart Now', 'Later'],
    defaultId: 0,
    cancelId: 1
  });
  
  if (response === 0) {
    autoUpdater.quitAndInstall();
  }
}

// Manual update check
async function checkForUpdatesManually() {
  try {
    const result = await autoUpdater.checkForUpdatesAndNotify();
    if (result) {
      console.log('Update check result:', result);
    } else {
      dialog.showMessageBox(null, {
        type: 'info',
        title: 'No Updates',
        message: 'You are running the latest version.'
      });
    }
  } catch (error) {
    console.error('Manual update check failed:', error);
    dialog.showErrorBox('Update Check Failed', error.message);
  }
}

Power Monitor

Monitor system power state and prevent system sleep.

/**
 * Monitor power state changes
 */
interface PowerMonitor extends EventEmitter {
  /** Returns the system's current idle state */
  getSystemIdleState(idleThreshold: number): 'active' | 'idle' | 'locked' | 'unknown';
  
  /** Returns the number of seconds the system has been idle */
  getSystemIdleTime(): number;
  
  /** Returns the system's current thermal state */
  getCurrentThermalState(): 'unknown' | 'nominal' | 'fair' | 'serious' | 'critical';
  
  /** Returns true if the system is on battery power */
  isOnBatteryPower(): boolean;
}

declare const powerMonitor: PowerMonitor;

/**
 * Block the system from entering low-power (sleep) mode
 */
interface PowerSaveBlocker {
  /** Starts preventing the system from entering lower-power mode */
  start(type: 'prevent-app-suspension' | 'prevent-display-sleep'): number;
  
  /** Stops the specified power save blocker */
  stop(id: number): void;
  
  /** Returns whether the corresponding powerSaveBlocker has started */
  isStarted(id: number): boolean;
}

declare const powerSaveBlocker: PowerSaveBlocker;

Usage Examples:

const { powerMonitor, powerSaveBlocker, app } = require('electron');

// Setup power monitoring
function setupPowerMonitoring() {
  // Monitor power events
  powerMonitor.on('suspend', () => {
    console.log('System is going to sleep');
    handleSystemSuspend();
  });
  
  powerMonitor.on('resume', () => {
    console.log('System is resuming');
    handleSystemResume();
  });
  
  powerMonitor.on('on-ac', () => {
    console.log('System is on AC power');
    handleACPower();
  });
  
  powerMonitor.on('on-battery', () => {
    console.log('System is on battery power');
    handleBatteryPower();
  });
  
  powerMonitor.on('shutdown', () => {
    console.log('System is shutting down');
    handleSystemShutdown();
  });
  
  powerMonitor.on('lock-screen', () => {
    console.log('System is locking');
    handleScreenLock();
  });
  
  powerMonitor.on('unlock-screen', () => {
    console.log('System is unlocking');
    handleScreenUnlock();
  });
  
  powerMonitor.on('user-did-become-active', () => {
    console.log('User became active');
    handleUserActive();
  });
  
  powerMonitor.on('user-did-resign-active', () => {
    console.log('User resigned active');
    handleUserInactive();
  });
  
  // Check initial power state
  const isOnBattery = powerMonitor.isOnBatteryPower();
  console.log('On battery:', isOnBattery);
  
  const thermalState = powerMonitor.getCurrentThermalState();
  console.log('Thermal state:', thermalState);
}

// Power save blocking
let displayBlockerId = null;
let systemBlockerId = null;

function preventSystemSleep() {
  if (!systemBlockerId) {
    systemBlockerId = powerSaveBlocker.start('prevent-app-suspension');
    console.log('Preventing system sleep, ID:', systemBlockerId);
  }
}

function allowSystemSleep() {
  if (systemBlockerId) {
    powerSaveBlocker.stop(systemBlockerId);
    console.log('Allowing system sleep');
    systemBlockerId = null;
  }
}

function preventDisplaySleep() {
  if (!displayBlockerId) {
    displayBlockerId = powerSaveBlocker.start('prevent-display-sleep');
    console.log('Preventing display sleep, ID:', displayBlockerId);
  }
}

function allowDisplaySleep() {
  if (displayBlockerId) {
    powerSaveBlocker.stop(displayBlockerId);
    console.log('Allowing display sleep');
    displayBlockerId = null;
  }
}

// Monitor user activity
function monitorUserActivity() {
  setInterval(() => {
    const idleTime = powerMonitor.getSystemIdleTime();
    const idleState = powerMonitor.getSystemIdleState(60); // 60 seconds threshold
    
    console.log(`Idle time: ${idleTime}s, State: ${idleState}`);
    
    if (idleState === 'idle' && idleTime > 300) { // 5 minutes
      console.log('User has been idle for 5+ minutes');
      handleUserIdle();
    }
  }, 30000); // Check every 30 seconds
}

// Handle thermal state changes
function handleThermalState() {
  powerMonitor.on('thermal-state-change', (state) => {
    console.log('Thermal state changed:', state);
    
    switch (state) {
      case 'critical':
        console.warn('System is critically hot!');
        // Reduce app performance
        reducePerformance();
        break;
      case 'serious':
        console.warn('System is getting hot');
        // Moderate performance reduction
        moderatePerformance();
        break;
      case 'nominal':
        console.log('System temperature is normal');
        // Restore full performance
        restorePerformance();
        break;
    }
  });
}

In-App Purchase (macOS/Windows)

Handle in-app purchases on supported platforms.

/**
 * In-app purchases on Mac App Store and Microsoft Store
 */
interface InAppPurchase extends EventEmitter {
  /** Returns true if the system allows purchases */
  canMakePayments(): boolean;
  
  /** Retrieves the product descriptions */
  getProducts(productIDs: string[]): Promise<Product[]>;
  
  /** Purchase the product */
  purchaseProduct(productID: string, quantity?: number): Promise<boolean>;
  
  /** Retrieves and consumes all unconsumed transactions */
  getReceiptURL(): string;
  
  /** Finishes all pending transactions */
  finishAllTransactions(): void;
  
  /** Finishes the pending transactions corresponding to the date */
  finishTransactionByDate(date: string): void;
}

declare const inAppPurchase: InAppPurchase;

Usage Examples:

const { inAppPurchase } = require('electron');

// Setup in-app purchases
function setupInAppPurchases() {
  if (!inAppPurchase.canMakePayments()) {
    console.log('In-app purchases not available');
    return;
  }
  
  // Handle transaction updates
  inAppPurchase.on('transactions-updated', (event, transactions) => {
    transactions.forEach((transaction) => {
      console.log('Transaction:', transaction);
      
      switch (transaction.transactionState) {
        case 'purchasing':
          console.log('Purchase in progress...');
          break;
        case 'purchased':
          console.log('Purchase successful!');
          handleSuccessfulPurchase(transaction);
          break;
        case 'failed':
          console.log('Purchase failed:', transaction.errorMessage);
          handleFailedPurchase(transaction);
          break;
        case 'restored':
          console.log('Purchase restored');
          handleRestoredPurchase(transaction);
          break;
        case 'deferred':
          console.log('Purchase deferred');
          break;
      }
    });
  });
}

// Get available products
async function loadProducts() {
  try {
    const productIds = ['com.myapp.premium', 'com.myapp.addon1', 'com.myapp.addon2'];
    const products = await inAppPurchase.getProducts(productIds);
    
    console.log('Available products:', products);
    return products;
  } catch (error) {
    console.error('Failed to load products:', error);
    return [];
  }
}

// Purchase a product
async function purchaseProduct(productId) {
  try {
    const success = await inAppPurchase.purchaseProduct(productId);
    
    if (success) {
      console.log('Purchase initiated successfully');
    } else {
      console.log('Purchase failed to initiate');
    }
  } catch (error) {
    console.error('Purchase error:', error);
  }
}

Types

type SystemColor = 
  | 'blue'
  | 'brown'
  | 'gray'
  | 'green'
  | 'orange'
  | 'pink'
  | 'purple'
  | 'red'
  | 'yellow'
  | 'window'
  | 'windowText'
  | 'controlBackground'
  | 'control'
  | 'controlText'
  | 'disabledControlText'
  | 'selectedControlText'
  | 'selectedControlBackground'
  | 'windowBackground'
  | 'underPageBackground'
  | 'label'
  | 'secondaryLabelColor'
  | 'tertiaryLabelColor'
  | 'quaternaryLabelColor'
  | 'textColor'
  | 'placeholderTextColor'
  | 'selectedTextColor'
  | 'selectedTextBackgroundColor'
  | 'keyboardFocusIndicatorColor'
  | 'unemphasizedSelectedTextColor'
  | 'unemphasizedSelectedTextBackgroundColor'
  | 'linkColor'
  | 'separatorColor'
  | 'selectedContentBackgroundColor'
  | 'unemphasizedSelectedContentBackgroundColor'
  | 'selectedMenuItemTextColor'
  | 'gridColor'
  | 'headerTextColor'
  | 'alternatingContentBackgroundColors'
  | 'controlAccentColor'
  | 'controlAlternatingRowBackgroundColors';

interface AnimationSettings {
  shouldRenderRichAnimation: boolean;
  scrollAnimationsEnabledBySystem: boolean;
  prefersReducedFrameRate: boolean;
}

interface FeedURLOptions {
  url: string;
  headers?: Record<string, string>;
  serverType?: 'json' | 'default';
}

interface UpdateCheckResult {
  updateInfo: UpdateInfo;
  downloadPromise?: Promise<any>;
  cancellationToken?: CancellationToken;
  versionInfo?: VersionInfo;
}

interface UpdateInfo {
  version: string;
  files: Array<{
    url: string;
    sha512: string;
    size: number;
  }>;
  releaseName?: string;
  releaseNotes?: string;
  releaseDate: string;
  stagingPercentage?: number;
}

interface Product {
  productIdentifier: string;
  localizedDescription: string;
  localizedTitle: string;
  contentVersion: string;
  contentLengths: number[];
  price: number;
  formattedPrice: string;
  currencyCode: string;
  downloadContentLengths: number[];
  downloadContentVersion: string;
}

interface Transaction {
  transactionIdentifier: string;
  transactionDate: string;
  originalTransactionIdentifier: string;
  transactionState: 'purchasing' | 'purchased' | 'failed' | 'restored' | 'deferred';
  errorCode: number;
  errorMessage: string;
  productIdentifier: string;
  quantity: number;
}

Install with Tessl CLI

npx tessl i tessl/npm-electron

docs

app-lifecycle.md

development.md

index.md

ipc.md

menu-system.md

network-protocols.md

platform-features.md

security.md

system-integration.md

window-management.md

tile.json