ToolBox Architecture
A comprehensive guide to the architecture of Power Platform Tool Box - an Electron-based desktop application built with TypeScript, Vite, and a modular design.
Overview
Power Platform Tool Box follows a modular architecture with clear separation between the main process, renderer process, and API layers. The application leverages Electron's multi-process model to ensure security, stability, and extensibility.
Technology Stack
Core Technologies
- Electron v28 - Cross-platform framework
- TypeScript v5.9.3 - Type-safe development
- Vite v7.1.11 - Modern build tool
- pnpm v10.18.3+ - Package management
Key Libraries
- electron-store v8.2.0 - Persistent storage
- electron-updater v6.6.2 - Auto-updates
- @azure/msal-node v3.8.0 - Authentication
- @fluentui/tokens - Design system
Architecture Diagram
┌───────────────────────────────────────────────────────────────────────┐
│ Power Platform Tool Box │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ Renderer Process│◄────────┤ IPC Communication │ │
│ │ │ │ (contextBridge) │ │
│ │ - UI (HTML) │─────────► │ │
│ │ - SCSS Styles │ └──────────────────────────┘ │
│ │ - TypeScript │ │ │
│ │ - Tool Iframes │ ▼ │
│ └──────────────────┘ ┌────────────────────────┐ │
│ │ Main Process │ │
│ │ │ │
│ │ ┌──────────────────┐ │ │
│ ┌──────────────┐ │ │ ToolBoxApp │ │ │
│ │ ToolBox API │◄─────────────┤ │ Coordinator │ │ │
│ │ │ │ └────────┬─────────┘ │ │
│ │ - Events │ │ │ │ │
│ │ - Notif. │ │ ┌────────▼─────────┐ │ │
│ └──────────────┘ │ │ Managers │ │ │
│ │ │ │ │ │
│ ┌──────────────┐ │ │ - Settings │ │ │
│ │ Tool (npm) │◄─────────────┤ │ - Connections │ │ │
│ │ - activate()│ │ │ - Tools │ │ │
│ │ - API calls │ │ │ - Auth (MSAL) │ │ │
│ │ - Isolated │ │ │ - Dataverse API │ │ │
│ └──────────────┘ │ │ - Terminal │ │ │
│ │ │ - AutoUpdate │ │ │
│ │ │ - Encryption │ │ │
│ │ └──────────────────┘ │ │
│ └────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────┐ │
│ │ Secure Storage │ │
│ │ │ │
│ │ - Encrypted Tokens │ │
│ │ - Settings (JSON) │ │
│ │ - Tool Storage │ │
│ │ - OS Keychain │ │
│ └────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
Core Components
1. Main Process (src/main/)
The main process is the entry point of the Electron application and manages the application lifecycle.
index.ts
Purpose: Main application entry point
Responsibilities:
- Initialize Electron app
- Create application window
- Set up IPC handlers
- Coordinate between managers
Managers (src/main/managers/)
The managers encapsulate specific functionality and provide clean separation of concerns:
- Name
settingsManager.ts- Description
User Settings Management
- Theme, language, auto-update preferences
- Persistent storage using electron-store
- Integration with encryption for sensitive data
- Name
connectionsManager.ts- Description
Dataverse Connections
- CRUD operations for connections
- Active connection management
- Encrypted storage of credentials (clientId, clientSecret, tokens)
- Connection validation and testing
- Name
toolsManager.ts- Description
Tool Lifecycle Management
- Load/unload tools
- Install tools from registry (primary method)
- Install/uninstall via npm/pnpm (legacy, deprecated)
- Track loaded tools
- Parse contribution points from package.json
- Emit tool lifecycle events
- Provide tool context (without exposing access tokens)
- Name
toolRegistryManager.ts- Description
Tool Registry & Downloads
- Fetch tool registry from server (VS Code marketplace style)
- Download pre-built tool archives via HTTP/HTTPS
- Extract and cache tools locally
- Manage tool manifests (installation tracking)
- Check for tool updates
- Handle tool versioning
- No npm/pnpm dependency required
- Name
authManager.ts- Description
Authentication & Authorization
- Handle OAuth flows with Azure AD
- Manage access tokens for Dataverse connections
- MSAL integration for secure authentication
- Token refresh and caching
- Username/password authentication support
- Name
dataverseManager.ts- Description
Dataverse Web API Operations
- CRUD operations (create, retrieve, update, delete)
- FetchXML query execution
- Entity metadata retrieval
- Execute actions and functions
- Automatic token management and refresh
- HTTP client for Dataverse Web API
- OData v4.0 compliant requests
- Entity set name conversion (singular to plural)
- Name
encryptionManager.ts- Description
Encryption of Sensitive Data
- Encrypt/decrypt using OS-native secure storage
- macOS: Keychain, Windows: DPAPI, Linux: libsecret
- Encrypt connection credentials (clientId, clientSecret, tokens)
- Automatic migration of plain-text data
- Field-level encryption utilities
- Name
terminalManager.ts- Description
Terminal Management
- Create and manage terminal instances
- Execute shell commands
- Stream command output
- Handle multiple shell types (bash, zsh, powershell, cmd)
- Emit terminal events (created, output, completed, error)
- Context-aware terminal isolation per tool
- Name
autoUpdateManager.ts- Description
Application Auto-Updates
- Check for updates using electron-updater
- Download and install updates
- Notify users of available updates
- Periodic update checks (configurable interval)
- User control over update installation
preload.ts
Purpose: Secure bridge between main and renderer processes
Responsibilities:
- Expose safe APIs to renderer via contextBridge
- IPC communication wrapper
- Security isolation
- Expose toolbox API methods to renderer
- Expose dataverse API methods to renderer
2. Renderer Process (src/renderer/)
The renderer process handles the UI and user interactions.
index.html
Purpose: Application UI structure
Features:
- Multi-panel layout (Tools, Connections, Settings, Terminal)
- Modal dialogs for tool installation and connections
- Modern, responsive design
- Tool iframes for isolated execution
- Terminal panel with tabs
styles.scss and styles/
Purpose: Application styling with SCSS
Features:
- Modular SCSS architecture with variables and mixins
- Fluent UI design tokens integration
- CSS custom properties for theming
- Responsive grid layouts
- Clean, professional appearance
_variables.scss: SCSS variables (colors, spacing, typography)_mixins.scss: Reusable SCSS mixins
renderer.ts
Purpose: UI logic and interactions (3,000+ lines)
Responsibilities:
- Handle user interactions
- Communicate with main process via IPC
- Update UI based on state changes
- Manage modal dialogs
- Load tools in iframes
- Context-aware API message routing
- Terminal UI management
- Tool context injection
toolboxAPIBridge.js
Purpose: API bridge for tools running in iframes
Responsibilities:
- Expose
toolboxAPIobject to tools - Expose
dataverseAPIobject to tools - Handle postMessage communication
- Auto-detect tool ID from context
- Context-aware API calls (terminals, events)
- Filter events relevant to specific tool
3. API Layer (src/api/)
toolboxAPI.ts
Purpose: Event-driven API for tools and application
Responsibilities:
- Event emission and subscription
- Notification system
- Event history tracking
- Communication hub for tools
- Event types: tool lifecycle, connections, terminals, settings, notifications
4. Type Definitions (src/types/)
index.ts
Purpose: Internal TypeScript type definitions
Contents:
- Tool interface with contribution points
- Contribution point types (commands, menus, views, configuration)
- Settings interfaces
- Connection interfaces
- Event types and payloads
- Notification options
- Terminal types
- Tool context (without access token)
5. Type Definitions Package (packages/)
Separate npm package (@pptoolbox/types) for tool developers with TypeScript type definitions.
toolboxAPI.d.ts
Purpose: TypeScript definitions for toolbox API
Contents:
- Utils API (notifications, clipboard, file operations, theme)
- Terminal API (create, execute, close, list, visibility)
- Events API (on, off, getHistory)
- Connections API (getActiveConnection)
dataverseAPI.d.ts
Purpose: TypeScript definitions for Dataverse API
Contents:
- CRUD operations (create, retrieve, update, delete)
- Query operations (fetchXmlQuery, retrieveMultiple)
- Metadata operations (getEntityMetadata, getAllEntitiesMetadata)
- Execute operations (actions and functions)
index.d.ts
Purpose: Main export for all type definitions
Exports: Both toolboxAPI and dataverseAPI types
Data Flow
Tool Installation Flow
User clicks "Install Tool"
↓
Renderer opens modal
↓
User enters package name
↓
Renderer → IPC → Main Process
↓
Tool Manager installs via pnpm (--dir flag for isolation)
↓
Tool Manager loads the tool
↓
Event emitted: tool:loaded
↓
ToolBox API broadcasts event
↓
Renderer updates UI
Connection Creation Flow
User clicks "Add Connection"
↓
Renderer opens modal
↓
User enters connection details
↓
Renderer → IPC → Main Process
↓
Connections Manager saves connection
↓
Encryption Manager encrypts sensitive fields
↓
Event emitted: connection:created
↓
ToolBox API broadcasts event
↓
Renderer updates UI
Context-Aware Tool API Flow
Tool (iframe) calls API
↓
toolboxAPIBridge.js auto-injects tool ID
↓
postMessage → Renderer Process
↓
Renderer routes based on tool context
↓
IPC → Main Process
↓
Manager executes with tool context
↓
Response → IPC → Renderer
↓
postMessage → Tool iframe
↓
Promise resolves in tool
Security Model
Tool Isolation Architecture
Power Platform Tool Box implements a secure iframe-based architecture for tool execution:
Isolated Execution
- Each tool runs in a separate iframe with limited API access
- Tools cannot directly access the main application or other tools
- Iframe isolation prevents memory leaks and crashes from affecting the main app
- Tools only have access to explicitly exposed APIs
Structured postMessage Protocol
- All tool communication uses window.postMessage
- Messages are validated for structure and content
- Request/response pattern with unique message IDs
- Context-aware message routing with automatic tool ID injection
API Injection
- Tools access
toolboxAPIanddataverseAPIobjects injected into iframe - The APIs are provided by
toolboxAPIBridge.js - Tools only have access to the specific APIs exposed by ToolBox
- No direct access to Node.js, Electron APIs, or other sensitive modules
Context-Aware APIs
- Tool ID Auto-Detection: Tools don't need to manually specify their ID
- Terminal Isolation: Each tool only sees its own terminals
- Event Filtering: Tools only receive events relevant to them
- No Token Exposure: Tools cannot access raw access tokens
Message Flow Example
Tool (iframe) toolboxAPIBridge.js Renderer Process Main Process
| | | |
|--dataverseAPI.retrieve()---->| | |
| |--postMessage(with ID)--->| |
| | |--IPC(invoke)---------->|
| | | |--HTTP-->Dataverse
| | |<---IPC(response)-------|
| |<--postMessage------------| |
|<--promise resolved-----------| | |
Encryption & Secure Storage
OS-Native Encryption
Uses Electron's safeStorage API for encryption:
- macOS: Keychain
- Windows: DPAPI (Data Protection API)
- Linux: libsecret
Encrypted Fields
The following sensitive fields are encrypted:
clientId- OAuth client identifierclientSecret- OAuth client secretaccessToken- Dataverse access tokenrefreshToken- Token refresh credentialspassword- Username/password authentication
Automatic Migration
- Existing plain-text connections are automatically encrypted on first launch
- No user intervention required
- Backwards compatible with older versions
Context Isolation & Communication
Context Isolation
- Renderer process runs in isolated context
- No direct access to Node.js APIs from tools
- Communication only through preload script (for main UI) or postMessage (for tools)
- Tools run in sandboxed iframes
IPC Communication (Main UI ↔ Main Process)
- All main-renderer communication via IPC
- Handlers validate and sanitize input
- Secure contextBridge API exposure in preload.ts
postMessage Communication (Tools ↔ Renderer)
- Tools communicate with renderer via window.postMessage
- toolboxAPIBridge.js handles message routing
- Context-aware: Tool ID automatically injected
- Event filtering ensures tools only receive relevant events
Settings Storage
- electron-store provides JSON storage
- Sensitive data encrypted using EncryptionManager
- Settings stored in user data directory
- Per-user, per-application isolation
Build Process
Build System
- Package Manager: pnpm (v10.18.3+)
- Build Tool: Vite (v7.1.11)
- Compiler: TypeScript (v5.9.3)
Build Commands
pnpm install # Install dependencies (~40s first time)
pnpm run lint # Lint TypeScript files (0 errors expected)
pnpm run build # Production build (2-5 seconds)
pnpm run watch # Watch mode for development
pnpm run dev # Development mode with Vite dev server
pnpm start # Run the built application
pnpm run package # Create distributable packages
Vite Build Process
Vite builds three separate bundles in parallel:
-
Main Process Build
- Entry:
src/main/index.ts - Output:
dist/main/index.js - Bundles all managers and dependencies
- Includes rollup-plugin-visualizer for bundle analysis
- Entry:
-
Preload Script Build
- Entry:
src/main/preload.ts - Output:
dist/main/preload.js - Secure bridge for IPC communication
- Entry:
-
Renderer Process Build
- Entry:
src/renderer/index.html - Output:
dist/renderer/ - Bundles TypeScript, compiles SCSS to CSS
- Code splitting: Vendor chunks separated
- Copies static assets (HTML, JSON, icons)
- Entry:
Bundle Analysis
After pnpm run build, view bundle analysis reports:
dist/stats-main.html- Main process bundle analysisdist/stats-renderer.html- Renderer process bundle analysis
Electron Packaging
electron-builder creates installers:
- Windows: NSIS installer
- macOS: DMG disk image
- Linux: AppImage
Output Structure
dist/
├── main/
│ ├── index.js # Main process
│ ├── preload.js # Preload script
│ └── managers/ # Manager modules
├── renderer/
│ ├── index.html # UI entry point
│ ├── assets/ # JavaScript and CSS bundles
│ ├── icons/ # UI icons
│ ├── tools.json # Tool registry
│ └── toolboxAPIBridge.js # Tool API bridge
└── stats-*.html # Bundle analysis reports
Terminal Integration
The Terminal feature allows tools to create and manage their own terminal instances for executing commands.
Terminal Manager
The TerminalManager provides:
- Terminal Creation: Tools can create named terminals with custom shell preferences
- Command Execution: Execute shell commands and receive real-time output
- Shell Selection: Tools specify preferred shell with automatic fallback to system default
- Context-Aware: Each tool only sees and manages its own terminals
- Event System: Real-time events for terminal output, completion, and errors
- Lifecycle Management: Proper cleanup and resource management
- Auto-Naming: Terminals automatically named with tool name if not specified
Supported Shells
- Unix/Linux: bash, zsh, sh
- macOS: bash, zsh
- Windows: PowerShell, cmd
Usage Example
// Create a terminal (auto-named with tool name)
const terminal = await toolboxAPI.terminal.create({
shell: "/bin/bash",
});
// Execute a command
await toolboxAPI.terminal.execute(terminal.id, "ls -la");
// Listen for output
toolboxAPI.events.on((event, payload) => {
if (event === "terminal:output" && payload.id === terminal.id) {
console.log("Output:", payload.output);
}
});
// Close terminal when done
await toolboxAPI.terminal.close(terminal.id);
File Structure
desktop-app/
├── src/
│ ├── api/
│ │ └── toolboxAPI.ts # Event system and API
│ ├── main/
│ │ ├── index.ts # Main process entry
│ │ ├── preload.ts # Secure IPC bridge
│ │ ├── constants.ts # App constants
│ │ └── managers/
│ │ ├── settingsManager.ts # Settings management
│ │ ├── connectionsManager.ts # Connection management
│ │ ├── toolsManager.ts # Tool lifecycle
│ │ ├── authManager.ts # Authentication (MSAL)
│ │ ├── dataverseManager.ts # Dataverse API operations
│ │ ├── encryptionManager.ts # Secure encryption
│ │ ├── terminalManager.ts # Terminal management
│ │ └── autoUpdateManager.ts # Auto-updates
│ ├── renderer/
│ │ ├── index.html # UI structure
│ │ ├── styles.scss # Main stylesheet
│ │ ├── styles/
│ │ │ ├── _variables.scss # SCSS variables
│ │ │ └── _mixins.scss # SCSS mixins
│ │ ├── renderer.ts # UI logic
│ │ ├── types.d.ts # Renderer types
│ │ ├── toolboxAPIBridge.js # API bridge for tools
│ │ ├── tools.json # Tool registry
│ │ └── icons/ # UI icons (light/dark themes)
│ └── types/
│ └── index.ts # Shared type definitions
├── packages/ # Type definitions package for tool developers
│ ├── toolboxAPI.d.ts # ToolBox API types
│ ├── dataverseAPI.d.ts # Dataverse API types
│ ├── index.d.ts # Main export
│ ├── package.json # Package metadata
│ └── README.md # Tool developer documentation
├── docs/ # Documentation
├── assets/
│ └── icon.png # Application icon
├── icons/
│ ├── icon.ico # Windows icon
│ ├── icon.icns # macOS icon
│ └── icon256x256.png # Linux icon
├── dist/ # Compiled output (gitignored)
├── build/ # Build artifacts (gitignored)
├── node_modules/ # Dependencies (gitignored)
├── package.json # Dependencies and scripts
├── pnpm-lock.yaml # pnpm lockfile
├── tsconfig.json # TypeScript config (main/api)
├── tsconfig.renderer.json # TypeScript config (renderer)
├── vite.config.ts # Vite build configuration
└── CONTRIBUTING.md # Contribution guidelines
Future Enhancements
Planned Features
- ✅ Tool Marketplace - Browse and install tools from a catalog
- Enhanced Tool Sandboxing - Additional security layers for third-party tools
- Multi-language Support - Internationalization (i18n)
- Theme Customization - User-defined themes and dark mode
- Enhanced Dataverse API - Batch requests, change tracking, upsert operations
- Testing Framework - Automated testing infrastructure
- Documentation Site - Comprehensive online documentation
- Plugin Versioning - Tool update management and version compatibility
- Sync Features - Sync local toolbox configuration across different machines without compromising security
Technical Debt
- Add comprehensive test coverage (unit, integration, E2E)
- Implement proper error boundaries in renderer
- Add structured logging system with log levels
- Implement tool verification/signing for security
- Add performance monitoring and metrics
- Improve bundle size optimization
- Add more comprehensive TypeScript types (reduce
anyusage)