Framework CLI - Dev Server Config
The dev-server supports optional configuration through a dev-server.config.ts
file in your project root. This allows you to customize how your application interacts with the Fusion Framework during development.
Note
Basic server options like port
, host
, and open
are configured via CLI flags or Vite configuration, not through dev-server.config.ts
.
Why Configure the Dev Server?
The default dev-server configuration works for most applications, but you may want to customize it when:
- Testing API integrations: Mock services or override API responses during development
- Debugging service discovery: Filter or modify discovered services for testing
- Customizing the development environment: Adjust template variables, CLI logging, or browser console logging
- Isolating development scenarios: Configure different behaviors for different development stages
Getting Started
Create a dev-server.config.ts
file in your project root. Start simple with object configuration:
// Simple object configuration
export default {
api: {
routes: [{
match: '/my-api/test',
middleware: (req, res) => res.end('OK')
}]
}
};
For conditional configuration based on environment or other runtime logic, use function configuration:
import { defineDevServerConfig } from '@equinor/fusion-framework-cli';
export default defineDevServerConfig(({ base }) => {
// Access to base config and environment for advanced logic
const isLocalDev = process.env.USER === 'your-username'; // Example condition
return {
api: {
routes: [
// Different routes based on conditions
isLocalDev && { match: '/api/local-dev', middleware: localHandler }
].filter(Boolean) // Remove falsy values
}
};
});
Tips
Start with object config. Use function config only when you need conditional logic or access to the base configuration.
TypeScript Integration
For full TypeScript support and intellisense, import the configuration types:
import { defineDevServerConfig, type DevServerConfig } from '@equinor/fusion-framework-cli';
// Fully typed configuration
export default defineDevServerConfig(({ base }): DevServerConfig => ({
...base,
api: {
...base.api,
routes: [
{
match: '/api/users',
middleware: (req, res) => {
// req and res are properly typed
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify([]));
}
}
]
}
}));
The configuration object supports full TypeScript intellisense, including:
- Auto-completion for all configuration options
- Type checking for middleware functions
- Proper typing for service discovery responses
Configuration Overview
The dev-server configuration supports these main areas:
Area | Purpose | Common Use Cases |
---|---|---|
api.routes | Mock API endpoints | Testing UI without backend, error scenarios |
api.processServices | Modify service discovery | Add mock services, override endpoints |
api.serviceDiscoveryUrl | Change discovery endpoint | Custom/dev environments |
spa.templateEnv | Override Fusion config | Portal settings, MSAL config, telemetry |
log | Control CLI logging verbosity | Debug dev-server issues, reduce terminal noise |
How Configuration Works
The dev-server.config.ts
file is designed for overriding the default dev-server behavior. You only specify what you want to change - the system automatically merges your overrides with the defaults.
Object Configuration (Recommended)
Just export the properties you want to override:
export default {
// Only override what you need to change
api: {
routes: [{
match: '/api/users',
middleware: (req, res) => res.end(JSON.stringify([]))
}]
},
spa: {
templateEnv: {
telemetry: { consoleLevel: 0 } // Only override telemetry
}
}
};
The dev-server automatically merges this with its default configuration.
Function Configuration (Advanced)
Use functions when you need conditional logic or access to runtime values:
export default defineDevServerConfig(({ base }) => {
// You have access to base config and runtime environment
return {
api: {
routes: [
// Your routes automatically merge with any existing ones
{ match: '/api/test', middleware: testHandler }
]
}
};
});
Key Point: You don't need to manually spread/merge anything. Just provide the overrides you want - the merging happens automatically.
Array Merging Behavior
The dev-server uses intelligent array merging:
- Routes: Merged by
match
path - routes with identical paths are replaced (yours wins) - Other arrays: Deduplicated using
Set
- removes exact duplicates - Services: In service discovery, arrays are typically replaced rather than merged
Example route merging:
// Base config has:
routes: [{ match: '/api/users', middleware: baseHandler }]
// Your config has:
routes: [{ match: '/api/users', middleware: yourHandler }]
// Result: yourHandler replaces baseHandler for /api/users
Quick Start Examples
I Need To...
I want to... | Configuration | Example |
---|---|---|
Mock an API endpoint | api.routes | routes: [{ match: '/api/users', middleware: (req, res) => res.end('[]') }] |
Add a mock service | api.processServices | Add services to the service discovery response |
Override MSAL config | spa.templateEnv.msal | msal: { clientId: 'dev-client-id' } |
Change telemetry logging | spa.templateEnv.telemetry | telemetry: { consoleLevel: 0 } |
Reduce CLI noise | log.level | log: { level: 2 } |
Essential Configurations
API Mocking
When you need it: Your application depends on backend services that aren't available during development, or you want to test specific API responses without hitting real services.
How it works: Add custom routes that intercept API calls and return mock data.
export default defineDevServerConfig(() => ({
api: {
routes: [
{
match: '/api/users',
middleware: (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify([
{ id: 1, name: 'John Doe', role: 'developer' },
{ id: 2, name: 'Jane Smith', role: 'designer' }
]));
}
},
// Mock error responses
{
match: '/api/users/404',
middleware: (req, res) => {
res.statusCode = 404;
res.end(JSON.stringify({ error: 'User not found' }));
}
}
]
}
}));
Benefits: Develop UI components and user flows without backend dependencies. Test error handling scenarios easily.
Service Discovery Customization
When you need it: You're developing against a service that doesn't exist yet in the remote service discovery, or you want to override service endpoints for local development.
How it works: Add mock services to the service discovery response that your application can use during development.
export default defineDevServerConfig(() => ({
api: {
processServices: (dataResponse) => {
const { data, routes } = dataResponse;
// Add mock services for development
const mockServices = [
{
key: 'my-new-service',
name: 'My New Service (Mock)',
uri: '/api/mock-service' // This will be proxied by the dev server
},
{
key: 'beta-feature-api',
name: 'Beta Feature API (Mock)',
uri: 'https://beta-api.example.com'
}
];
return {
data: [...data, ...mockServices],
routes
};
}
}
}));
Benefits: Develop against planned services before they're deployed. Test integration scenarios with mock endpoints.
Template Environment Variables
When you need it: You need to override default Fusion Framework template configuration for development.
How it works: Modify the template environment variables that control the SPA bootstrap process.
export default defineDevServerConfig(() => ({
spa: {
templateEnv: {
// Override document title
title: 'My Custom App Title',
// Override portal configuration
portal: {
id: 'my-custom-portal',
},
// Modify service discovery
serviceDiscovery: {
url: 'https://custom-service-discovery.example.com',
scopes: ['api://custom-scope/.default']
},
// Override MSAL configuration
msal: {
tenantId: 'custom-tenant-id',
clientId: 'custom-client-id',
redirectUri: 'https://localhost:3000/auth-callback',
requiresAuth: 'true'
},
// Configure telemetry logging level
telemetry: {
consoleLevel: 0 // Debug level (most verbose)
}
}
}
}));
Benefits: Customize the Fusion Framework bootstrap behavior and control browser console logging verbosity for your specific development needs.
Available telemetry levels:
0
: Debug (shows all telemetry including debug messages)1
: Information (shows info, warnings, errors, critical)2
: Warning (shows warnings, errors, critical - default)3
: Error (shows only errors and critical messages)4
: Critical (shows only critical messages - least verbose)
Portal Proxy Configuration
When you need it: You want to control how portal assets are loaded during development - either from the Fusion portal service or from locally installed portal packages.
How it works:
proxy: true
: Routes portal assets through the dev-server's/portal-proxy
endpoint, which fetches content from the Fusion portal serviceproxy: false
(default): Loads portal assets directly fromnode_modules
(typically@equinor/fusion-dev-server
or another portal package installed locally)
export default defineDevServerConfig(() => ({
spa: {
templateEnv: {
portal: {
id: 'fusion',
tag: 'latest',
proxy: true // Load portal from Fusion portal service via /portal-proxy
}
}
}
}));
Benefits:
proxy: true
: Access production portal templates or custom portal deployments via the Fusion portal serviceproxy: false
: Use locally installed portal packages for offline development or custom portal development
CLI Logging
When you need it: You want to control the verbosity of dev-server output in your terminal/console.
How it works: Configure the logger level or provide a custom logger instance for CLI output.
export default defineDevServerConfig(() => ({
log: {
// Info level (default) - shows info, warnings, and errors
level: 3,
}
}));
Available levels:
0
: Silent (no logging)1
: Error (errors only)2
: Warning (warnings and errors)3
: Info (info, warnings, and errors - default)4
: Debug (debug, info, warnings, and errors - most verbose)
Quick reference:
// Quiet development (reduce noise)
log: { level: 2 }
// Default logging (recommended)
log: { level: 3 }
// Debug dev-server issues
log: { level: 4 }
Common Patterns
Override MSAL for Local Development
export default {
spa: {
templateEnv: {
msal: {
clientId: 'dev-client-id',
redirectUri: 'http://localhost:3000/auth-callback'
}
}
}
};
Troubleshooting
Configuration Not Loading
- Verify file name:
dev-server.config.ts
in project root - Ensure default export:
export default { ... }
- Check for TypeScript errors in config file
Services Not Appearing
- Ensure
processServices
returns{ data: Service[], routes: Route[] }
- Verify you're not accidentally filtering out needed services
Template Variables Not Available
- Variables are injected as
import.meta.env.FUSION_SPA_*
- Access them as
import.meta.env.FUSION_SPA_MY_VAR
Advanced Usage
Custom Service Discovery Endpoint
For custom environments with different service discovery URLs:
export default {
api: {
serviceDiscoveryUrl: 'https://custom-discovery.example.com/api/service-discovery'
}
};
Warning
Only use when working with non-standard environments. The default Fusion service discovery endpoint is usually correct.