@equinor/fusion-framework-dev-server 2.0.19 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @equinor/fusion-framework-dev-server
2
2
 
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f663b46: Expose `DevServerOptions` as an interface so optional development tooling can add typed
8
+ configuration through TypeScript module augmentation.
9
+
10
+ ### Patch Changes
11
+
12
+ - f663b46: Proxy mock services advertised through `<service>.localhost` via plain `localhost` while preserving
13
+ the service-key path. This avoids `ENOTFOUND` failures on Linux runners without changing normal
14
+ upstream service proxying.
15
+ - Updated dependencies [f663b46]
16
+ - Updated dependencies [f663b46]
17
+ - Updated dependencies [f663b46]
18
+ - @equinor/fusion-log@2.0.3
19
+ - @equinor/fusion-framework-vite-plugin-api-service@2.0.6
20
+ - @equinor/fusion-framework-vite-plugin-spa@4.1.0
21
+
3
22
  ## 2.0.19
4
23
 
5
24
  ### Patch Changes
package/README.md CHANGED
@@ -1,495 +1,105 @@
1
- # Fusion Framework Dev Server
1
+ # @equinor/fusion-framework-dev-server
2
2
 
3
- A powerful development server for Fusion Framework applications, built on Vite with integrated service discovery, API proxying, and portal support.
3
+ Development server primitives for Fusion Framework applications. The package combines Vite,
4
+ React Fast Refresh, SPA environment injection, Fusion service discovery, and local API proxying.
4
5
 
5
- ## Features
6
+ > [!TIP]
7
+ > Most application developers should start with `ffc app dev`. Use this package directly when you
8
+ > are building framework tooling, a custom development command, or a Vite integration that needs
9
+ > control over server creation.
6
10
 
7
- - 🚀 **Fast Development**: Powered by Vite for lightning-fast HMR and builds
8
- - 🔗 **Service Discovery**: Automatic API service discovery and proxying
9
- - 🏠 **Portal Support**: Built-in portal development with manifest loading
10
- - 🔧 **API Mocking**: Easy mocking and overriding of API responses
11
- - 📊 **Telemetry**: Integrated logging and debugging capabilities
12
- - ⚙️ **Flexible Configuration**: Extensive customization options
11
+ ## Choose your entry point
13
12
 
14
- ## Quick Start
13
+ | Goal | Start here |
14
+ | --- | --- |
15
+ | Run a Fusion application locally | `ffc app dev` from `@equinor/fusion-framework-cli` |
16
+ | Create and start a configured Vite server | `createDevServer(options, overrides?)` |
17
+ | Generate Vite configuration without starting a server | `createDevServerConfig(options, overrides?)` |
18
+ | Customize service discovery proxy routes | `processServices(data, args)` |
19
+ | Develop against local OpenAPI mocks | [`@equinor/fusion-framework-cli-plugin-mock-server`](../cli-plugins/mock-server/README.md) |
15
20
 
16
- Here's the minimal setup to get a Fusion Framework dev server running:
21
+ ## Quick start
17
22
 
18
- ```typescript
19
- import { createDevServer } from '@equinor/fusion-framework-dev-server';
20
-
21
- const devServer = await createDevServer({
22
- spa: {
23
- templateEnv: {
24
- portal: {
25
- id: '@equinor/fusion-framework-dev-portal',
26
- },
27
- title: 'My Fusion App',
28
- serviceDiscovery: {
29
- url: 'https://service-discovery.example.com',
30
- scopes: ['api://example.com/user_impersonation'],
31
- },
32
- msal: {
33
- clientId: 'your-client-id',
34
- tenantId: 'your-tenant-id',
35
- redirectUri: '/authentication/login-callback',
36
- requiresAuth: 'true',
37
- },
38
- },
39
- },
40
- api: {
41
- serviceDiscoveryUrl: 'https://service-discovery.example.com',
42
- },
43
- });
44
-
45
- await devServer.listen();
46
- devServer.printUrls();
47
- ```
48
-
49
- If you only need the Vite configuration object without starting the server, use `createDevServerConfig(options, overrides?)` instead. This returns a `UserConfig` that you can pass to Vite directly or merge with other configurations.
50
-
51
- ## Configuration
52
-
53
- The dev server accepts a configuration object with the following structure:
54
-
55
- ### SPA Configuration
56
-
57
- Configure the Single Page Application environment and template generation:
58
-
59
- ```typescript
60
- {
61
- spa: {
62
- templateEnv: {
63
- // Portal configuration
64
- portal: {
65
- id: 'your-portal-id', // Portal identifier
66
- },
67
-
68
- // Application title
69
- title: 'My Application',
70
-
71
- // Service discovery settings (SPA-side — tells the browser where to find services)
72
- // The API-side counterpart is `api.serviceDiscoveryUrl` which sets up server-side proxying.
73
- // During development you can redirect individual services to local URLs by storing
74
- // overrides in sessionStorage under the key "overriddenServiceDiscoveryUrls".
75
- serviceDiscovery: {
76
- url: 'https://service-discovery.example.com',
77
- scopes: ['scope1', 'scope2'],
78
- },
79
-
80
- // Authentication configuration
81
- msal: {
82
- clientId: 'your-client-id',
83
- tenantId: 'your-tenant-id',
84
- redirectUri: '/authentication/login-callback',
85
- requiresAuth: 'true', // or 'false'
86
- },
87
-
88
- // Optional telemetry configuration (browser console logging)
89
- telemetry: {
90
- consoleLevel: 1, // 0=Debug, 1=Information, 2=Warning, 3=Error, 4=Critical
91
- },
92
-
93
- // Optional service worker configuration
94
- serviceWorker: {
95
- resources: [
96
- {
97
- url: '/api',
98
- rewrite: '/api-v1',
99
- scopes: ['api://example.com/user_impersonation'],
100
- },
101
- ],
102
- },
103
- },
104
- },
105
- }
106
- ```
107
-
108
- ### API Configuration
109
-
110
- Configure API proxying and service discovery:
111
-
112
- ```typescript
113
- {
114
- api: {
115
- // Required: Service discovery endpoint
116
- serviceDiscoveryUrl: 'https://service-discovery.example.com',
117
-
118
- // Optional: Custom service processing
119
- // Takes an array of FusionService objects ({ key, uri, name }) from discovery
120
- // and returns { data: FusionService[], routes: ApiRoute[] } with proxy routes.
121
- processServices: (services, route) => {
122
- // Process and return services with routes
123
- return processServices(services, route);
124
- },
125
-
126
- // Optional: Additional API routes
127
- routes: [
128
- {
129
- match: '/api/custom/*',
130
- middleware: (req, res) => {
131
- // Custom middleware logic
132
- res.end(JSON.stringify({ custom: 'response' }));
133
- },
134
- },
135
- ],
136
- },
137
- }
138
- ```
139
-
140
- ### Logging Configuration
141
-
142
- Configure CLI/server-side logging levels and custom loggers:
143
-
144
- ```typescript
145
- {
146
- log: {
147
- // Optional: CLI log level (0=None, 1=Error, 2=Warning, 3=Info, 4=Debug)
148
- level: 3, // Default is Info level
149
-
150
- // Optional: Custom logger instance
151
- logger: new ConsoleLogger('my-dev-server'),
152
- },
153
- }
154
- ```
155
-
156
- > [!NOTE]
157
- > **Telemetry vs CLI Logging**: The `telemetry.consoleLevel` controls logging output in the browser console (visible to end users), while `log.level` controls server-side logging in the terminal/command line (visible to developers). These use different logging systems with different level mappings.
158
-
159
- ### Main Functions
160
-
161
- #### `createDevServer(options, overrides?)`
162
-
163
- Creates and configures a development server instance.
164
-
165
- **Parameters:**
166
- - `options` (`DevServerOptions`): Configuration object for the dev server
167
- - `overrides` (`UserConfig`): Optional Vite configuration overrides
168
-
169
- **Returns:** `Promise<ViteDevServer>` - Configured Vite development server
170
-
171
- **Example:**
172
- ```typescript
173
- const devServer = await createDevServer(config);
174
- await devServer.listen();
175
- ```
176
-
177
- #### `createDevServerConfig(options, overrides?)`
178
-
179
- Creates a Vite configuration object for the dev server.
180
-
181
- **Parameters:**
182
- - `options` (`DevServerOptions`): Configuration object for the dev server
183
- - `overrides` (`UserConfig`): Optional Vite configuration overrides
184
-
185
- **Returns:** `UserConfig` - Vite configuration object
186
-
187
- ### Utility Functions
188
-
189
- #### `processServices(data, args)`
190
-
191
- Processes service discovery data and generates proxy routes.
192
-
193
- **Parameters:**
194
- - `data` (`FusionService[]`): Array of services from service discovery
195
- - `args.route` (`string`): Base route for proxying
196
- - `args.request` (`IncomingMessage`): HTTP request object
197
-
198
- **Returns:** Object with processed services and routes
199
-
200
- ### Types
201
-
202
- #### `DevServerOptions<TEnv>`
203
-
204
- Configuration options for the development server.
205
-
206
- ```typescript
207
- type DevServerOptions<TEnv extends Partial<FusionTemplateEnv>> = {
208
- spa?: {
209
- templateEnv: TEnv | TemplateEnvFn<TEnv>;
210
- };
211
- api: {
212
- serviceDiscoveryUrl: string;
213
- processServices?: ApiDataProcessor<FusionService[]>;
214
- routes?: ApiRoute[];
215
- };
216
- log?: {
217
- level?: number;
218
- logger?: ConsoleLogger;
219
- };
220
- };
23
+ ```sh
24
+ pnpm add -D @equinor/fusion-framework-dev-server vite
221
25
  ```
222
26
 
223
- #### `FusionService`
224
-
225
- Represents a service in the Fusion ecosystem.
226
-
227
- ```typescript
228
- type FusionService = {
229
- key: string; // Service identifier
230
- uri: string; // Service endpoint URL
231
- name: string; // Human-readable service name
232
- };
233
- ```
234
-
235
- ## Examples
236
-
237
- ### Basic Portal Development
238
-
239
27
  ```typescript
240
28
  import { createDevServer } from '@equinor/fusion-framework-dev-server';
241
29
 
242
- const devServer = await createDevServer({
30
+ const server = await createDevServer({
243
31
  spa: {
244
32
  templateEnv: {
245
33
  portal: { id: 'my-portal' },
246
- title: 'My Portal',
34
+ title: 'My application',
247
35
  serviceDiscovery: {
248
36
  url: 'https://service-discovery.example.com',
249
37
  scopes: ['api://example.com/user_impersonation'],
250
38
  },
251
39
  msal: {
252
- clientId: process.env.CLIENT_ID!,
253
- tenantId: process.env.TENANT_ID!,
40
+ clientId: 'client-id',
41
+ tenantId: 'tenant-id',
254
42
  redirectUri: '/authentication/login-callback',
255
43
  requiresAuth: 'true',
256
44
  },
257
45
  },
258
46
  },
259
- api: {
260
- serviceDiscoveryUrl: 'https://service-discovery.example.com',
261
- },
262
- });
263
-
264
- await devServer.listen();
265
- ```
266
-
267
- ### Adding Mock Services
268
-
269
- ```typescript
270
- import { createDevServer, processServices } from '@equinor/fusion-framework-dev-server';
271
-
272
- const devServer = await createDevServer({
273
- spa: { /* ... spa config ... */ },
274
- api: {
275
- serviceDiscoveryUrl: 'https://service-discovery.example.com',
276
- processServices: (data, route) => {
277
- const { data: services, routes } = processServices(data, route);
278
-
279
- // Add mock services
280
- return {
281
- data: services.concat({
282
- key: 'mock-api',
283
- name: 'Mock API Service',
284
- uri: '/mock-api',
285
- }),
286
- routes: routes.concat({
287
- match: '/mock-api/*',
288
- middleware: (req, res) => {
289
- res.setHeader('Content-Type', 'application/json');
290
- res.end(JSON.stringify({ mock: 'data' }));
291
- },
292
- }),
293
- };
294
- },
295
- },
296
- });
297
- ```
298
-
299
- ### Custom Vite Configuration
300
-
301
- ```typescript
302
- import { createDevServer } from '@equinor/fusion-framework-dev-server';
303
- import { defineConfig } from 'vite';
304
-
305
- const devServer = await createDevServer(
306
- { /* ... dev server config ... */ },
307
- defineConfig({
308
- server: {
309
- port: 3001,
310
- host: '0.0.0.0',
311
- },
312
- define: {
313
- __DEV__: true,
314
- },
315
- })
316
- );
317
- ```
318
-
319
-
320
- ## Troubleshooting
321
-
322
- ### Common Issues
323
-
324
- #### "Cannot find module '@equinor/fusion-framework-dev-server'"
325
-
326
- **Solution:** Make sure the package is installed and you're using the correct import path.
327
-
328
- ```bash
329
- pnpm add -D @equinor/fusion-framework-dev-server
330
- ```
331
-
332
- #### Service Discovery Connection Failed
333
-
334
- **Problem:** The dev server can't connect to the service discovery endpoint.
335
-
336
- **Solutions:**
337
- 1. Check that `serviceDiscoveryUrl` is correct and accessible
338
- 2. Verify network connectivity to the service discovery endpoint
339
- 3. Check for authentication requirements
340
-
341
- #### Portal Manifest Not Loading
342
-
343
- **Problem:** Portal configuration isn't loading properly.
344
-
345
- **Solutions:**
346
- 1. Verify the portal ID is correct in the `spa.templateEnv.portal.id` field
347
- 2. Check that the portal service is available and responding
348
- 3. Ensure proper authentication is configured
349
-
350
- #### API Routes Not Working
351
-
352
- **Problem:** Custom API routes or service proxying isn't functioning.
353
-
354
- **Solutions:**
355
- 1. Check the `routes` configuration in the `api` section
356
- 2. Verify route patterns match the expected request paths
357
- 3. Ensure middleware functions are properly implemented
358
- 4. Check for conflicts with existing routes
359
-
360
- #### Authentication Issues
361
-
362
- **Problem:** MSAL authentication isn't working.
363
-
364
- **Solutions:**
365
- 1. Verify `clientId` and `tenantId` are correct
366
- 2. Check that `redirectUri` matches your application configuration
367
- 3. Ensure the required scopes are properly configured
368
- 4. Check browser console for authentication errors
369
-
370
- ### Debug Logging
371
-
372
- Enable debug logging to troubleshoot issues:
373
-
374
- #### CLI/Server-Side Debug Logging
375
- ```typescript
376
- const devServer = await createDevServer({
377
- // ... config
378
- log: {
379
- level: 4, // Debug level (0=None, 1=Error, 2=Warning, 3=Info, 4=Debug)
380
- },
47
+ api: { serviceDiscoveryUrl: 'https://service-discovery.example.com' },
381
48
  });
382
- ```
383
49
 
384
- #### Browser Console Telemetry Logging
385
- ```typescript
386
- {
387
- spa: {
388
- templateEnv: {
389
- // ... other config
390
- telemetry: {
391
- consoleLevel: 0, // Debug level (0=Debug, 1=Information, 2=Warning, 3=Error, 4=Critical)
392
- },
393
- },
394
- },
395
- }
50
+ await server.listen();
51
+ server.printUrls();
396
52
  ```
397
53
 
398
- ## Advanced Usage
54
+ The browser receives `spa.templateEnv`. The Node development server uses
55
+ `api.serviceDiscoveryUrl` to fetch service definitions and create same-origin proxy routes. These
56
+ two URLs often point to the same endpoint, but they serve different consumers.
399
57
 
400
- ### Custom Service Processing
58
+ Continue with [Getting started](docs/getting-started.md) for the complete mental model.
401
59
 
402
- For advanced service discovery manipulation:
60
+ ## Mock APIs locally
403
61
 
404
- ```typescript
405
- import { createDevServer, processServices } from '@equinor/fusion-framework-dev-server';
62
+ Install the optional mock-server plugin when a backend is unavailable, unstable, or needs
63
+ deterministic responses:
406
64
 
407
- const devServer = await createDevServer({
408
- api: {
409
- serviceDiscoveryUrl: 'https://service-discovery.example.com',
410
- processServices: (services, route) => {
411
- const { data, routes } = processServices(services, route);
412
-
413
- // Filter out development-only services in production
414
- const filteredData = data.filter(service =>
415
- process.env.NODE_ENV !== 'production' || !service.key.includes('dev')
416
- );
417
-
418
- // Add custom routes for specific services
419
- const customRoutes = routes.map(route => ({
420
- ...route,
421
- // Add custom headers or modify proxy behavior
422
- }));
423
-
424
- return { data: filteredData, routes: customRoutes };
425
- },
426
- },
427
- });
428
- ```
429
-
430
- ### Integration with Build Tools
431
-
432
- The dev server works seamlessly with the Fusion Framework CLI:
433
-
434
- ```bash
435
- # Use with CLI for automatic configuration
436
- npx @equinor/fusion-framework-cli app dev
437
-
438
- # Or portal development
439
- npx @equinor/fusion-framework-cli portal dev
65
+ ```sh
66
+ pnpm add -D @equinor/fusion-framework-cli-plugin-mock-server
67
+ ffc mock-server ./mocks --port 4010
440
68
  ```
441
69
 
442
- ### Custom Plugins
70
+ > [!IMPORTANT]
71
+ > `ffc mock-server` is a standalone foreground process. Installing the plugin does not start it
72
+ > with `ffc app dev`; the developer or test runner owns its lifecycle.
443
73
 
444
- Extend the dev server with custom Vite plugins:
445
-
446
- ```typescript
447
- import { createDevServer } from '@equinor/fusion-framework-dev-server';
448
- import myCustomPlugin from 'my-custom-vite-plugin';
449
-
450
- const devServer = await createDevServer(
451
- { /* ... config ... */ },
452
- {
453
- plugins: [myCustomPlugin()],
454
- }
455
- );
456
- ```
74
+ The plugin adds typed `mockServer` settings to `DevServerOptions` only when its types are imported,
75
+ keeping this base package independent of optional mocking tools.
457
76
 
458
- ## Migration Guide
77
+ See [Develop with mock services](docs/mocking.md) for normal development overlays, isolated
78
+ `--mock` mode, direct-only services, and executable `<name>.mock.ts` modules.
459
79
 
460
- ### From Direct Vite Usage
80
+ ## Learn in order
461
81
 
462
- If you're migrating from a direct Vite setup:
82
+ 1. [Getting started](docs/getting-started.md) explains the server lifecycle and smallest useful setup.
83
+ 2. [Configure the dev server](docs/configuration.md) covers SPA environment, API proxying, and logging.
84
+ 3. [Develop with mock services](docs/mocking.md) shows the recommended optional mocking workflow.
85
+ 4. [Advanced usage](docs/advanced.md) covers service processing, routes, Vite overrides, and extension interfaces.
86
+ 5. [Troubleshooting](docs/troubleshooting.md) maps common symptoms to the responsible configuration.
463
87
 
464
- 1. Replace your Vite configuration with the dev server configuration
465
- 2. Move service discovery logic to the `api.processServices` function
466
- 3. Configure portal settings in `spa.templateEnv`
467
- 4. Update your start script to use `createDevServer`
88
+ ## Public API
468
89
 
469
- **Before:**
470
- ```typescript
471
- // vite.config.ts
472
- export default defineConfig({
473
- plugins: [react(), /* other plugins */],
474
- server: {
475
- proxy: { /* proxy config */ },
476
- },
477
- });
478
- ```
479
-
480
- **After:**
481
- ```typescript
482
- import { createDevServer } from '@equinor/fusion-framework-dev-server';
483
-
484
- const devServer = await createDevServer({
485
- // Move your config here
486
- });
487
- ```
90
+ - `createDevServer` creates a configured `ViteDevServer`. Call `listen()` yourself.
91
+ - `createDevServerConfig` returns a Vite `UserConfig` for another tool to consume.
92
+ - `processServices` rewrites discovered service URIs through the local proxy and returns routes.
93
+ - `DevServerOptions<TEnv>` configures SPA injection, API discovery, and logging. It is an interface so optional plugins can augment it.
94
+ - `FusionService` describes a backend using `key`, `uri`, `name`, and optional OAuth `scopes`.
488
95
 
489
- ## Contributing
96
+ ## Requirements and boundaries
490
97
 
491
- This package is part of the Fusion Framework monorepo. See the main [contributing guide](../../CONTRIBUTING.md) for details.
98
+ - Vite 7 or 8 is required as a peer dependency.
99
+ - `api.serviceDiscoveryUrl` is required by the low-level API.
100
+ - The package configures development; it does not build or publish applications.
101
+ - Mock-server installation and process lifecycle are optional and external to this package.
492
102
 
493
103
  ## License
494
104
 
495
- ISC
105
+ ISC
@@ -69,14 +69,22 @@ export const processServices = (data, args) => {
69
69
  // and replace the path with the local proxy path
70
70
  const serviceUrl = new URL(`${route}/${service.key}`, request.headers.referer);
71
71
  apiServices.push({ ...service, uri: String(serviceUrl) });
72
- // add the proxy route
72
+ // Add the proxy route for this service.
73
73
  const url = new URL(service.uri);
74
+ const usesLocalhostSubdomain = url.hostname.endsWith('.localhost');
75
+ // Node does not resolve localhost subdomains consistently across operating systems. The mock
76
+ // server also accepts /<service>/* on plain localhost, so proxy through that portable address.
77
+ if (usesLocalhostSubdomain) {
78
+ url.hostname = 'localhost';
79
+ }
74
80
  apiRoutes.push({
75
81
  match: `/${service.key}${url.pathname}*sub`,
76
- proxy: {
77
- target: url.origin,
78
- rewrite: (path) => path.replace(`/${service.key}`, ''),
79
- },
82
+ proxy: usesLocalhostSubdomain
83
+ ? { target: url.origin }
84
+ : {
85
+ target: url.origin,
86
+ rewrite: (path) => path.replace(`/${service.key}`, ''),
87
+ },
80
88
  });
81
89
  }
82
90
  return { data: apiServices, routes: apiRoutes };
@@ -1 +1 @@
1
- {"version":3,"file":"process-services.js","sourceRoot":"","sources":["../../src/process-services.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;IAC/E,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,SAAS,GAAG,EAAgB,CAAC;IACnC,MAAM,WAAW,GAAG,EAAqB,CAAC;IAE1C,6EAA6E;IAC7E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,oDAAoD;IACpD,gCAAgC;IAChC,KAAK,MAAM,OAAO,IAAI,IAAuB,EAAE,CAAC;QAC9C,oDAAoD;QACpD,iDAAiD;QACjD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/E,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAE1D,sBAAsB;QACtB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,SAAS,CAAC,IAAI,CAAC;YACb,KAAK,EAAE,IAAI,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,MAAM;YAC3C,KAAK,EAAE;gBACL,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;aACvD;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAClD,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"process-services.js","sourceRoot":"","sources":["../../src/process-services.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;IAC/E,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,SAAS,GAAG,EAAgB,CAAC;IACnC,MAAM,WAAW,GAAG,EAAqB,CAAC;IAE1C,6EAA6E;IAC7E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,oDAAoD;IACpD,gCAAgC;IAChC,KAAK,MAAM,OAAO,IAAI,IAAuB,EAAE,CAAC;QAC9C,oDAAoD;QACpD,iDAAiD;QACjD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/E,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAE1D,wCAAwC;QACxC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,sBAAsB,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACnE,6FAA6F;QAC7F,+FAA+F;QAC/F,IAAI,sBAAsB,EAAE,CAAC;YAC3B,GAAG,CAAC,QAAQ,GAAG,WAAW,CAAC;QAC7B,CAAC;QACD,SAAS,CAAC,IAAI,CAAC;YACb,KAAK,EAAE,IAAI,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,MAAM;YAC3C,KAAK,EAAE,sBAAsB;gBAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;gBACxB,CAAC,CAAC;oBACE,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;iBACvD;SACN,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAClD,CAAC,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { IncomingMessage } from 'node:http';
2
+ import { Socket } from 'node:net';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { processServices } from './process-services.js';
5
+ const request = new IncomingMessage(new Socket());
6
+ request.headers.referer = 'http://localhost:3000';
7
+ describe('processServices', () => {
8
+ it('proxies localhost subdomains through the portable shared-host route', () => {
9
+ const result = processServices([{ key: 'people', name: 'People', uri: 'http://people.localhost:4010' }], { route: '/@fusion-api', request });
10
+ expect(result.routes).toEqual([
11
+ {
12
+ match: '/people/*sub',
13
+ proxy: { target: 'http://localhost:4010' },
14
+ },
15
+ ]);
16
+ });
17
+ it('preserves normal upstream proxy targets and path rewriting', () => {
18
+ const result = processServices([{ key: 'people', name: 'People', uri: 'https://people.example/api' }], { route: '/@fusion-api', request });
19
+ const [route] = result.routes ?? [];
20
+ expect(route?.proxy?.target).toBe('https://people.example');
21
+ expect(route?.proxy?.rewrite?.('/people/api/persons')).toBe('/api/persons');
22
+ });
23
+ });
24
+ //# sourceMappingURL=process-services.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-services.test.js","sourceRoot":"","sources":["../../src/process-services.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;AAClD,OAAO,CAAC,OAAO,CAAC,OAAO,GAAG,uBAAuB,CAAC;AAElD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,MAAM,GAAG,eAAe,CAC5B,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,8BAA8B,EAAE,CAAC,EACxE,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,CACnC,CAAC;QAEF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YAC5B;gBACE,KAAK,EAAE,cAAc;gBACrB,KAAK,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE;aAC3C;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,MAAM,GAAG,eAAe,CAC5B,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,4BAA4B,EAAE,CAAC,EACtE,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,CACnC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;QAEpC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  // Generated by genversion.
2
- export const version = '2.0.19';
2
+ export const version = '2.1.0';
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}