@forestadmin/agent 1.99.2 → 1.100.1
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/README.md +73 -0
- package/dist/agent.d.ts +38 -1
- package/dist/agent.js +101 -14
- package/dist/bff-routes.d.ts +25 -0
- package/dist/bff-routes.js +49 -0
- package/dist/embedded-bff.d.ts +61 -0
- package/dist/embedded-bff.js +220 -0
- package/dist/framework-mounter.d.ts +8 -4
- package/dist/framework-mounter.js +21 -14
- package/dist/index.d.ts +1 -1
- package/dist/root-middleware.d.ts +33 -0
- package/dist/root-middleware.js +70 -0
- package/dist/types.d.ts +47 -1
- package/dist/types.js +1 -1
- package/package.json +12 -5
- package/dist/mcp-middleware.d.ts +0 -27
- package/dist/mcp-middleware.js +0 -67
package/README.md
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @forestadmin/agent
|
|
2
|
+
|
|
3
|
+
The main entry point of the Forest Admin Node.js SDK: `createAgent(options)` returns an agent to
|
|
4
|
+
which you attach datasources, customizations, charts and plugins, then mount on your HTTP server.
|
|
5
|
+
|
|
6
|
+
See the [developer guide](https://docs.forestadmin.com/developer-guide-agents-nodejs) for the full
|
|
7
|
+
documentation.
|
|
8
|
+
|
|
9
|
+
## Optional in-process components
|
|
10
|
+
|
|
11
|
+
Two components normally deployed on their own can run inside the agent instead. Both are optional
|
|
12
|
+
packages, loaded dynamically: an agent that does not use them never loads their code.
|
|
13
|
+
|
|
14
|
+
### A BFF — `agent.addBff()`
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @forestadmin/agent-bff
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
await createAgent(options)
|
|
22
|
+
.addDataSource(/* … */)
|
|
23
|
+
.addBff({ allowedOrigins: ['https://my-app.com'] })
|
|
24
|
+
.mountOnStandaloneServer(3351)
|
|
25
|
+
.start();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Serves the REST BFF under `/bff` on whatever port the agent is mounted on, on every mount target —
|
|
29
|
+
`mountOnStandaloneServer` above, or the host's own listener with `mountOnExpress`, `mountOnKoa`,
|
|
30
|
+
`mountOnFastify`, `mountOnNestJs`. A `mountOn*` call is what opens a socket: `start()` only builds
|
|
31
|
+
the agent's router, so a chain without one serves nothing, BFF included.
|
|
32
|
+
|
|
33
|
+
The BFF reaches the agent in the same process, so there is no second port, no agent url to
|
|
34
|
+
configure, and no secrets to keep in sync — `authSecret`, `envSecret`, the Forest urls and the
|
|
35
|
+
logger are inherited.
|
|
36
|
+
|
|
37
|
+
Everything `addBff()` takes is a feature it switches on: `tokenEncryptionKey` enables OAuth (and
|
|
38
|
+
with it the AI relay), `allowedOrigins` enables browser access, `openapiEnabled` serves the docs
|
|
39
|
+
(off by default when embedded). `GET /bff/health` reports which of them are on, under `configured`.
|
|
40
|
+
|
|
41
|
+
**Mount the agent before any body parser of your own** — a parser that runs first consumes the
|
|
42
|
+
request stream, and every BFF `POST` then answers `500 stream.not.readable`.
|
|
43
|
+
|
|
44
|
+
A permissive `cors()` registered ahead of the mount costs you the preflight but not the allow-list:
|
|
45
|
+
the host answers `OPTIONS` with its own policy, and nothing downstream can take that back, so the
|
|
46
|
+
request that follows arrives here anyway — and is refused with `403 origin_not_allowed` unless its
|
|
47
|
+
`Origin` is one you listed. The browser sees the wrong preflight; the collection is still never read
|
|
48
|
+
for that origin.
|
|
49
|
+
|
|
50
|
+
Mounting under a sub-path of your own works: `app.use('/api', mounted)` serves the BFF at
|
|
51
|
+
`/api/bff`, and the prefix is derived per request, so the OpenAPI `servers` entry and the docs page
|
|
52
|
+
carry `/api/bff` too.
|
|
53
|
+
|
|
54
|
+
**`agentTimeoutMs` bounds the wait, not the work.** When a call to the agent exceeds it the BFF
|
|
55
|
+
answers with an error, but nothing is cancelled: the in-process request runs to completion. An
|
|
56
|
+
action cut at the timeout still applies its mutation, so a client that retries applies it twice.
|
|
57
|
+
Size the timeout above your slowest action, and make actions idempotent if you intend to retry them.
|
|
58
|
+
|
|
59
|
+
**`addBff()` cannot be combined with `mountAiMcpServer({ basePath: '/bff' })`** — the MCP server
|
|
60
|
+
would claim `/bff/oauth` and `/bff/mcp`. Whichever you call second throws on the spot, at the
|
|
61
|
+
builder call and not from `start()`.
|
|
62
|
+
|
|
63
|
+
See [`@forestadmin/agent-bff`](../agent-bff/README.md) for the routes, the auth modes and the
|
|
64
|
+
differences with the standalone deployment.
|
|
65
|
+
|
|
66
|
+
### A workflow executor — `agent.addWorkflowExecutor()`
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm install @forestadmin/workflow-executor
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Runs a workflow executor alongside the agent, which proxies `/_internal/executor/*` to it. See
|
|
73
|
+
[`@forestadmin/workflow-executor`](../workflow-executor/README.md).
|
package/dist/agent.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ForestAdminHttpDriverServices } from './services';
|
|
2
|
-
import type { AgentOptions, AgentOptionsWithDefaults, WorkflowExecutorEmbedOptions } from './types';
|
|
2
|
+
import type { AgentOptions, AgentOptionsWithDefaults, BffEmbedOptions, WorkflowExecutorEmbedOptions } from './types';
|
|
3
3
|
import type { CollectionCustomizer, DataSourceChartDefinition, DataSourceOptions, Plugin, TCollectionName, TSchema } from '@forestadmin/datasource-customizer';
|
|
4
4
|
import type { DataSource, DataSourceFactory } from '@forestadmin/datasource-toolkit';
|
|
5
5
|
import type { FileUploadsOptions, TokenTtlOptions, ToolName } from '@forestadmin/mcp-server';
|
|
@@ -32,7 +32,15 @@ export default class Agent<S extends TSchema = TSchema> extends FrameworkMounter
|
|
|
32
32
|
private mcpFileUploads?;
|
|
33
33
|
/** In-process workflow executor, created only when addWorkflowExecutor() is called. */
|
|
34
34
|
private embeddedExecutor;
|
|
35
|
+
/** In-process BFF, created only when addBff() is called. */
|
|
36
|
+
private embeddedBff;
|
|
35
37
|
private isRestarting;
|
|
38
|
+
/**
|
|
39
|
+
* Set as soon as start() begins, not once it finishes: mount() drains the `onFirstStart` hooks
|
|
40
|
+
* partway through, so a builder call landing mid-startup is already too late. Cleared again when
|
|
41
|
+
* startup fails, which leaves nothing mounted and makes the agent configurable once more.
|
|
42
|
+
*/
|
|
43
|
+
private startupBegun;
|
|
36
44
|
/**
|
|
37
45
|
* Create a new Agent Builder.
|
|
38
46
|
* If any options are missing, the default will be applied:
|
|
@@ -179,6 +187,35 @@ export default class Agent<S extends TSchema = TSchema> extends FrameworkMounter
|
|
|
179
187
|
* .start();
|
|
180
188
|
*/
|
|
181
189
|
addWorkflowExecutor(options?: WorkflowExecutorEmbedOptions): this;
|
|
190
|
+
/**
|
|
191
|
+
* Serve a BFF in-process, alongside the agent, at `/bff` — no second deployment, no second port.
|
|
192
|
+
* The agent builds it on start(), stops it on stop(), and hands it a dispatcher that reaches its
|
|
193
|
+
* own stack without a socket, so this works the same on every mount target.
|
|
194
|
+
*
|
|
195
|
+
* Requires the `@forestadmin/agent-bff` package to be installed:
|
|
196
|
+
* ```bash
|
|
197
|
+
* npm install @forestadmin/agent-bff
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* The secrets, the Forest urls and the logger are inherited from the agent. Everything left is
|
|
201
|
+
* a feature the BFF switches on when configured: `tokenEncryptionKey` enables OAuth (and with it
|
|
202
|
+
* the AI relay), `allowedOrigins` enables browser access, `openapiEnabled` serves the docs.
|
|
203
|
+
*
|
|
204
|
+
* @param options embedded BFF options
|
|
205
|
+
* @returns the agent instance for chaining
|
|
206
|
+
* @throws Error if called more than once, or if the MCP server already claims `/bff`
|
|
207
|
+
*
|
|
208
|
+
* A `mountOn*` call is what opens a socket — start() only builds the router — so the BFF is only
|
|
209
|
+
* reachable on an agent that is mounted somewhere.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* await createAgent(options)
|
|
213
|
+
* .addDataSource(...)
|
|
214
|
+
* .addBff({ allowedOrigins: ['https://my-app.com'] })
|
|
215
|
+
* .mountOnStandaloneServer(3351)
|
|
216
|
+
* .start();
|
|
217
|
+
*/
|
|
218
|
+
addBff(options?: BffEmbedOptions): this;
|
|
182
219
|
protected getRoutes(dataSource: DataSource, services: ForestAdminHttpDriverServices): import("./routes/base-route").default[];
|
|
183
220
|
/**
|
|
184
221
|
* Create an http handler which can respond to all queries which are expected from an agent.
|
package/dist/agent.js
CHANGED
|
@@ -43,6 +43,8 @@ const router_1 = __importDefault(require("@koa/router"));
|
|
|
43
43
|
const promises_1 = require("fs/promises");
|
|
44
44
|
const json_stringify_pretty_compact_1 = __importDefault(require("json-stringify-pretty-compact"));
|
|
45
45
|
const audit_trail_1 = require("./audit-trail");
|
|
46
|
+
const bff_routes_1 = require("./bff-routes");
|
|
47
|
+
const embedded_bff_1 = __importDefault(require("./embedded-bff"));
|
|
46
48
|
const embedded_workflow_executor_1 = __importDefault(require("./embedded-workflow-executor"));
|
|
47
49
|
const framework_mounter_1 = __importDefault(require("./framework-mounter"));
|
|
48
50
|
const routes_1 = __importDefault(require("./routes"));
|
|
@@ -51,6 +53,12 @@ const customization_1 = __importDefault(require("./services/model-customizations
|
|
|
51
53
|
const correlation_id_1 = require("./utils/correlation-id");
|
|
52
54
|
const generator_1 = __importDefault(require("./utils/forest-schema/generator"));
|
|
53
55
|
const options_validator_1 = __importDefault(require("./utils/options-validator"));
|
|
56
|
+
// Whichever is registered second raises it. `addBff()` registers at builder time and the MCP
|
|
57
|
+
// server only at start(), and the root middleware answers with the first handler whose matcher
|
|
58
|
+
// claims the url — so the BFF wins and the whole MCP surface would go silently dark.
|
|
59
|
+
const bffMcpCollision = (mcpBasePath) => `Cannot use addBff together with mountAiMcpServer({ basePath: '${mcpBasePath}' }): the MCP ` +
|
|
60
|
+
`server would claim ${bff_routes_1.BFF_PREFIX} paths the embedded BFF answers on (${bff_routes_1.BFF_PREFIX}/oauth, ` +
|
|
61
|
+
`${bff_routes_1.BFF_PREFIX}/mcp). Mount the MCP server elsewhere.`;
|
|
54
62
|
/**
|
|
55
63
|
* Allow to create a new Forest Admin agent from scratch.
|
|
56
64
|
* Builds the application by composing and configuring all the collection decorators.
|
|
@@ -85,7 +93,15 @@ class Agent extends framework_mounter_1.default {
|
|
|
85
93
|
this.mcpEnabled = false;
|
|
86
94
|
/** In-process workflow executor, created only when addWorkflowExecutor() is called. */
|
|
87
95
|
this.embeddedExecutor = null;
|
|
96
|
+
/** In-process BFF, created only when addBff() is called. */
|
|
97
|
+
this.embeddedBff = null;
|
|
88
98
|
this.isRestarting = false;
|
|
99
|
+
/**
|
|
100
|
+
* Set as soon as start() begins, not once it finishes: mount() drains the `onFirstStart` hooks
|
|
101
|
+
* partway through, so a builder call landing mid-startup is already too late. Cleared again when
|
|
102
|
+
* startup fails, which leaves nothing mounted and makes the agent configurable once more.
|
|
103
|
+
*/
|
|
104
|
+
this.startupBegun = false;
|
|
89
105
|
this.options = allOptions;
|
|
90
106
|
this.customizer = new datasource_customizer_1.DataSourceCustomizer({
|
|
91
107
|
ignoreMissingSchemaElementErrors: options.ignoreMissingSchemaElementErrors || false,
|
|
@@ -98,18 +114,31 @@ class Agent extends framework_mounter_1.default {
|
|
|
98
114
|
*/
|
|
99
115
|
async start() {
|
|
100
116
|
let mounted = false;
|
|
117
|
+
this.startupBegun = true;
|
|
101
118
|
try {
|
|
102
|
-
|
|
119
|
+
// First, before anything is mounted or subscribed: everything it validates is what the caller
|
|
120
|
+
// handed to addBff(), so a mistyped key must fail on that line rather than leave the host
|
|
121
|
+
// serving /forest with a permanently bricked /bff.
|
|
122
|
+
await this.embeddedBff?.prepare();
|
|
123
|
+
const { router, mcp } = await this.buildRouterAndSendSchema();
|
|
103
124
|
await this.options.forestAdminClient.subscribeToServerEvents();
|
|
104
125
|
this.options.forestAdminClient.onRefreshCustomizations(this.restart.bind(this));
|
|
105
|
-
this.setMcpCallback(
|
|
126
|
+
this.setMcpCallback(mcp ?? null);
|
|
106
127
|
await this.mount(router);
|
|
107
128
|
mounted = true;
|
|
108
129
|
// Boot after mount(): the embedded executor reaches the agent over HTTP, and the
|
|
109
130
|
// standalone server's host/port (used to derive that URL) are only known once mounted.
|
|
110
131
|
await this.embeddedExecutor?.start(this.standaloneServerHost, this.standaloneServerPort);
|
|
132
|
+
// Same reason, without the socket: the dispatcher injects into the stack mount() just built.
|
|
133
|
+
await this.embeddedBff?.start(this.getInProcessDispatcher());
|
|
111
134
|
}
|
|
112
135
|
catch (error) {
|
|
136
|
+
// Only when nothing was mounted. Past mount() the host framework is already serving this
|
|
137
|
+
// agent, so it is not configurable again: clearing the flag would let a later addBff() past
|
|
138
|
+
// its guard and register a BFF whose start() nothing calls — /bff would answer 503 for the
|
|
139
|
+
// rest of the process, and restart() only invalidates, it never starts it.
|
|
140
|
+
if (!mounted)
|
|
141
|
+
this.startupBegun = false;
|
|
113
142
|
const { message } = error;
|
|
114
143
|
this.options.logger('Error', `Forest Admin agent startup failure: ${message}`);
|
|
115
144
|
// buildRouterAndSendSchema() may already have opened the audit-trail connection even
|
|
@@ -133,7 +162,10 @@ class Agent extends framework_mounter_1.default {
|
|
|
133
162
|
* Stop the agent.
|
|
134
163
|
*/
|
|
135
164
|
async stop() {
|
|
136
|
-
//
|
|
165
|
+
// Stop answering before the stack it dispatches into goes away: the host application keeps
|
|
166
|
+
// whatever middleware it registered, so a stopped agent would otherwise still serve BFF data.
|
|
167
|
+
this.embeddedBff?.stop();
|
|
168
|
+
// Drain the embedded executor next, while the agent it depends on is still serving.
|
|
137
169
|
await this.embeddedExecutor?.stop();
|
|
138
170
|
// Close anything related to ForestAdmin client
|
|
139
171
|
this.options.forestAdminClient.close();
|
|
@@ -163,9 +195,11 @@ class Agent extends framework_mounter_1.default {
|
|
|
163
195
|
this.isRestarting = true;
|
|
164
196
|
try {
|
|
165
197
|
// We force sending schema when restarting
|
|
166
|
-
const { router,
|
|
167
|
-
this.setMcpCallback(
|
|
198
|
+
const { router, mcp } = await this.buildRouterAndSendSchema();
|
|
199
|
+
this.setMcpCallback(mcp ?? null);
|
|
168
200
|
await this.remount(router);
|
|
201
|
+
// A restart means the customizations changed, so the schema the BFF read is stale.
|
|
202
|
+
this.embeddedBff?.invalidate();
|
|
169
203
|
}
|
|
170
204
|
finally {
|
|
171
205
|
this.isRestarting = false;
|
|
@@ -277,6 +311,9 @@ class Agent extends framework_mounter_1.default {
|
|
|
277
311
|
* agent.mountAiMcpServer({ fileUploads: false });
|
|
278
312
|
*/
|
|
279
313
|
mountAiMcpServer(options) {
|
|
314
|
+
if (this.embeddedBff && (0, bff_routes_1.collidesWithBff)(options?.basePath)) {
|
|
315
|
+
throw new Error(bffMcpCollision(options?.basePath));
|
|
316
|
+
}
|
|
280
317
|
this.mcpEnabled = true;
|
|
281
318
|
this.mcpEnabledTools = options?.enabledTools;
|
|
282
319
|
this.mcpBasePath = options?.basePath;
|
|
@@ -320,6 +357,58 @@ class Agent extends framework_mounter_1.default {
|
|
|
320
357
|
this.embeddedExecutor = executor;
|
|
321
358
|
return this;
|
|
322
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Serve a BFF in-process, alongside the agent, at `/bff` — no second deployment, no second port.
|
|
362
|
+
* The agent builds it on start(), stops it on stop(), and hands it a dispatcher that reaches its
|
|
363
|
+
* own stack without a socket, so this works the same on every mount target.
|
|
364
|
+
*
|
|
365
|
+
* Requires the `@forestadmin/agent-bff` package to be installed:
|
|
366
|
+
* ```bash
|
|
367
|
+
* npm install @forestadmin/agent-bff
|
|
368
|
+
* ```
|
|
369
|
+
*
|
|
370
|
+
* The secrets, the Forest urls and the logger are inherited from the agent. Everything left is
|
|
371
|
+
* a feature the BFF switches on when configured: `tokenEncryptionKey` enables OAuth (and with it
|
|
372
|
+
* the AI relay), `allowedOrigins` enables browser access, `openapiEnabled` serves the docs.
|
|
373
|
+
*
|
|
374
|
+
* @param options embedded BFF options
|
|
375
|
+
* @returns the agent instance for chaining
|
|
376
|
+
* @throws Error if called more than once, or if the MCP server already claims `/bff`
|
|
377
|
+
*
|
|
378
|
+
* A `mountOn*` call is what opens a socket — start() only builds the router — so the BFF is only
|
|
379
|
+
* reachable on an agent that is mounted somewhere.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* await createAgent(options)
|
|
383
|
+
* .addDataSource(...)
|
|
384
|
+
* .addBff({ allowedOrigins: ['https://my-app.com'] })
|
|
385
|
+
* .mountOnStandaloneServer(3351)
|
|
386
|
+
* .start();
|
|
387
|
+
*/
|
|
388
|
+
addBff(options = {}) {
|
|
389
|
+
if (this.embeddedBff) {
|
|
390
|
+
throw new Error('addBff can only be called once.');
|
|
391
|
+
}
|
|
392
|
+
// Refused rather than accepted and left dark: once startup has begun the dispatcher hook has no
|
|
393
|
+
// mount left to attach to and nothing calls the BFF's own start(), so `/bff` would answer 503
|
|
394
|
+
// for the rest of the process while every other route works. A throw on the line the developer
|
|
395
|
+
// wrote instead. Refused from the first line of start(), not from its last: `start()` is async,
|
|
396
|
+
// so a call made while it is still in flight is just as late.
|
|
397
|
+
if (this.startupBegun) {
|
|
398
|
+
throw new Error('addBff must be called before start(): the agent is already starting.');
|
|
399
|
+
}
|
|
400
|
+
if ((0, bff_routes_1.collidesWithBff)(this.mcpBasePath)) {
|
|
401
|
+
throw new Error(bffMcpCollision(this.mcpBasePath));
|
|
402
|
+
}
|
|
403
|
+
const bff = new embedded_bff_1.default(this.options, options);
|
|
404
|
+
this.embeddedBff = bff;
|
|
405
|
+
// Registered now rather than at start(): getInProcessDispatcher() pushes its hook the first
|
|
406
|
+
// time it is called, and mount() only runs the hooks registered before it — asked for later,
|
|
407
|
+
// the dispatcher would have no handler until the first restart.
|
|
408
|
+
this.getInProcessDispatcher();
|
|
409
|
+
this.setBffCallback(bff.handle);
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
323
412
|
getRoutes(dataSource, services) {
|
|
324
413
|
return (0, routes_1.default)(dataSource, this.options, services);
|
|
325
414
|
}
|
|
@@ -333,11 +422,9 @@ class Agent extends framework_mounter_1.default {
|
|
|
333
422
|
const routes = this.getRoutes(dataSource, services);
|
|
334
423
|
await Promise.all(routes.map(route => route.bootstrap()));
|
|
335
424
|
// Initialize MCP server if enabled via mountAiMcpServer()
|
|
336
|
-
let
|
|
337
|
-
let mcpIsMcpRoute;
|
|
425
|
+
let mcp;
|
|
338
426
|
if (this.mcpEnabled) {
|
|
339
|
-
|
|
340
|
-
await this.initializeMcpServer());
|
|
427
|
+
mcp = await this.initializeMcpServer();
|
|
341
428
|
}
|
|
342
429
|
// Build main router
|
|
343
430
|
const router = new router_1.default();
|
|
@@ -355,7 +442,7 @@ class Agent extends framework_mounter_1.default {
|
|
|
355
442
|
}));
|
|
356
443
|
router.use(correlation_id_1.correlationIdMiddleware);
|
|
357
444
|
routes.forEach(route => route.setupRoutes(router));
|
|
358
|
-
return { router,
|
|
445
|
+
return { router, mcp };
|
|
359
446
|
}
|
|
360
447
|
/**
|
|
361
448
|
* Initialize the MCP server.
|
|
@@ -382,11 +469,11 @@ class Agent extends framework_mounter_1.default {
|
|
|
382
469
|
fileUploads: this.mcpFileUploads,
|
|
383
470
|
agentDispatcher: this.getInProcessDispatcher(),
|
|
384
471
|
});
|
|
385
|
-
const
|
|
386
|
-
const
|
|
472
|
+
const callback = await mcpServer.getHttpCallback();
|
|
473
|
+
const matches = makeIsMcpRoute(this.mcpBasePath);
|
|
387
474
|
mcpLogger('Info', 'Server initialized successfully');
|
|
388
475
|
mcpLogger('Info', 'Tool calls dispatch in-process and skip any middleware mounted in front of the agent');
|
|
389
|
-
return {
|
|
476
|
+
return { callback, matches };
|
|
390
477
|
}
|
|
391
478
|
catch (error) {
|
|
392
479
|
const { message } = error;
|
|
@@ -507,4 +594,4 @@ class Agent extends framework_mounter_1.default {
|
|
|
507
594
|
}
|
|
508
595
|
}
|
|
509
596
|
exports.default = Agent;
|
|
510
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFxQkEsOEVBQTBFO0FBQzFFLGlFQUF5QztBQUN6QyxxREFBNkI7QUFDN0IseURBQWlDO0FBQ2pDLDBDQUFrRDtBQUNsRCxrR0FBc0Q7QUFFdEQsK0NBQXVEO0FBQ3ZELDhGQUFvRTtBQUNwRSw0RUFBbUQ7QUFDbkQsc0RBQWtDO0FBQ2xDLDBEQUFzQztBQUN0QyxrR0FBaUY7QUFDakYsMkRBQXdGO0FBQ3hGLGdGQUE4RDtBQUM5RCxrRkFBeUQ7QUFFekQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBcUIsS0FBbUMsU0FBUSwyQkFBZ0I7SUFvQjlFOzs7Ozs7Ozs7Ozs7Ozs7T0FlRztJQUNILFlBQVksT0FBcUI7UUFDL0IsTUFBTSxVQUFVLEdBQUcsMkJBQWdCLENBQUMsUUFBUSxDQUFDLDJCQUFnQixDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3JGLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQS9COUMsMkNBQTJDO1FBQ25DLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFPM0IsdUZBQXVGO1FBQy9FLHFCQUFnQixHQUFvQyxJQUFJLENBQUM7UUFFekQsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFzQjNCLElBQUksQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO1FBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSw0Q0FBb0IsQ0FBSTtZQUM1QyxnQ0FBZ0MsRUFBRSxPQUFPLENBQUMsZ0NBQWdDLElBQUksS0FBSztTQUNwRixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsSUFBSSx1QkFBb0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqRSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksbUJBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsS0FBSztRQUNULElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztRQUVwQixJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1lBRXpGLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQy9ELElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUVoRixJQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsSUFBSSxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDNUQsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pCLE9BQU8sR0FBRyxJQUFJLENBQUM7WUFFZixpRkFBaUY7WUFDakYsdUZBQXVGO1lBQ3ZGLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDM0YsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsS0FBYyxDQUFDO1lBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSx1Q0FBdUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUUvRSxxRkFBcUY7WUFDckYsdUZBQXVGO1lBQ3ZGLDJGQUEyRjtZQUMzRiwwRkFBMEY7WUFDMUYsdUZBQXVGO1lBQ3ZGLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDYixJQUFJLENBQUM7b0JBQ0gsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQztnQkFDekMsQ0FBQztnQkFBQyxPQUFPLFVBQVUsRUFBRSxDQUFDO29CQUNwQixNQUFNLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLFVBQW1CLENBQUM7b0JBQ3RELElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUNqQixPQUFPLEVBQ1Asd0RBQXdELFlBQVksRUFBRSxDQUN2RSxDQUFDO2dCQUNKLENBQUM7WUFDSCxDQUFDO1lBRUQsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ00sS0FBSyxDQUFDLElBQUk7UUFDakIscUZBQXFGO1FBQ3JGLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3BDLCtDQUErQztRQUMvQyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZDLDRGQUE0RjtRQUM1RiwwRkFBMEY7UUFDMUYsMkZBQTJGO1FBQzNGLHVGQUF1RjtRQUN2RixNQUFNLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUVuQixzRkFBc0Y7UUFDdEYsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUN6QyxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFjLENBQUM7WUFDbkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQ2pCLE9BQU8sRUFDUCx3REFBd0QsT0FBTyxFQUFFLENBQ2xFLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLE9BQU87UUFDWCxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN0QixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsMENBQTBDLENBQUMsQ0FBQztZQUV6RSxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO1FBRXRELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBRXpCLElBQUksQ0FBQztZQUNILDBDQUEwQztZQUMxQyxNQUFNLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1lBRXpGLElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxJQUFJLElBQUksRUFBRSxhQUFhLENBQUMsQ0FBQztZQUM1RCxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0IsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGFBQWEsQ0FBQyxPQUEwQixFQUFFLE9BQTJCO1FBQ25FLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUV6RSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxXQUFtQixFQUFFLGVBQXVCO1FBQ3hFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7T0FhRztJQUNILFFBQVEsQ0FBQyxJQUFZLEVBQUUsVUFBd0M7UUFDN0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRTNDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxtQkFBbUIsQ0FDakIsSUFBTyxFQUNQLE1BQTJEO1FBRTNELElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRWxELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZ0JBQWdCLENBQUMsR0FBRyxLQUEyQjtRQUM3QyxJQUFJLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFFM0MsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsR0FBRyxDQUFVLE1BQXVCLEVBQUUsT0FBaUI7UUFDckQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXJDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQTZCRztJQUNILGdCQUFnQixDQUFDLE9BTWhCO1FBQ0MsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLGVBQWUsR0FBRyxPQUFPLEVBQUUsWUFBWSxDQUFDO1FBQzdDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxFQUFFLFFBQVEsQ0FBQztRQUNyQyxJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sRUFBRSxRQUFRLENBQUM7UUFDckMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQztRQUMzRCxJQUFJLENBQUMsY0FBYyxHQUFHLE9BQU8sRUFBRSxXQUFXLENBQUM7UUFFM0MsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FzQkc7SUFDSCxtQkFBbUIsQ0FBQyxVQUF3QyxFQUFFO1FBQzVELElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQ2xFLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLG9DQUF3QixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM1RCw4RkFBOEY7UUFDOUYsd0ZBQXdGO1FBQ3hGLGlGQUFpRjtRQUNoRixJQUFJLENBQUMsT0FBd0IsQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2pGLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxRQUFRLENBQUM7UUFFakMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRVMsU0FBUyxDQUFDLFVBQXNCLEVBQUUsUUFBdUM7UUFDakYsT0FBTyxJQUFBLGdCQUFVLEVBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVEOzs7T0FHRztJQUNLLEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBc0I7UUFLNUMsZ0JBQWdCO1FBQ2hCLE1BQU0sUUFBUSxHQUFHLElBQUEsa0JBQVksRUFBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFFcEQsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTFELDBEQUEwRDtRQUMxRCxJQUFJLGVBQXlDLENBQUM7UUFDOUMsSUFBSSxhQUEwQyxDQUFDO1FBRS9DLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLENBQUMsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUU7Z0JBQzNELE1BQU0sSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQztRQUN0QyxDQUFDO1FBRUQsb0JBQW9CO1FBQ3BCLE1BQU0sTUFBTSxHQUFHLElBQUksZ0JBQU0sRUFBRSxDQUFDO1FBQzVCLE1BQU0sQ0FBQyxHQUFHLENBQ1IsTUFBTSxFQUNOLElBQUEsY0FBSSxFQUFDO1lBQ0gsV0FBVyxFQUFFLElBQUk7WUFDakIsTUFBTSxFQUFFLEVBQUUsR0FBRyxJQUFJO1lBQ2pCLG9CQUFvQixFQUFFLElBQUk7WUFDMUIsYUFBYSxFQUFFLENBQUMsc0NBQXFCLENBQUM7U0FDdkMsQ0FBQyxDQUNILENBQUM7UUFDRixNQUFNLENBQUMsR0FBRyxDQUNSLElBQUEsb0JBQVUsRUFBQztZQUNULFFBQVEsRUFBRSxPQUFPO1lBQ2pCLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDbkMsYUFBYSxFQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDO1lBQ2pELEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUI7U0FDbEMsQ0FBQyxDQUNILENBQUM7UUFDRixNQUFNLENBQUMsR0FBRyxDQUFDLHdDQUF1QixDQUFDLENBQUM7UUFDcEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUVuRCxPQUFPLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLEtBQUssQ0FBQyxtQkFBbUI7UUFJL0IsTUFBTSxTQUFTLEdBQUcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsU0FBUyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBRXJGLElBQUksQ0FBQztZQUNILHdEQUF3RDtZQUN4RCxNQUFNLEVBQUUsZUFBZSxFQUFFLHNCQUFzQixFQUFFLGNBQWMsRUFBRSxHQUFHLHdEQUNsRSx5QkFBeUIsR0FDMUIsQ0FBQztZQUVGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxzQkFBc0IsQ0FDbkQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLEVBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLEVBQ2xELElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLEVBQy9DLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUM3QixDQUFDO1lBRUYsTUFBTSxTQUFTLEdBQUcsSUFBSSxlQUFlLENBQUM7Z0JBQ3BDLGVBQWUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWU7Z0JBQzdDLFlBQVksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVk7Z0JBQ3ZDLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVM7Z0JBQ2pDLFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVU7Z0JBQ25DLE1BQU0sRUFBRSxTQUFTO2dCQUNqQixrQkFBa0I7Z0JBQ2xCLFlBQVksRUFBRSxJQUFJLENBQUMsZUFBZTtnQkFDbEMsUUFBUSxFQUFFLElBQUksQ0FBQyxXQUFXO2dCQUMxQixRQUFRLEVBQUUsSUFBSSxDQUFDLFdBQVc7Z0JBQzFCLG1CQUFtQixFQUFFLElBQUksQ0FBQyxzQkFBc0I7Z0JBQ2hELFdBQVcsRUFBRSxJQUFJLENBQUMsY0FBYztnQkFDaEMsZUFBZSxFQUFFLElBQUksQ0FBQyxzQkFBc0IsRUFBRTthQUMvQyxDQUFDLENBQUM7WUFFSCxNQUFNLFlBQVksR0FBRyxNQUFNLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN2RCxNQUFNLFVBQVUsR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXBELFNBQVMsQ0FBQyxNQUFNLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztZQUNyRCxTQUFTLENBQ1AsTUFBTSxFQUNOLHNGQUFzRixDQUN2RixDQUFDO1lBRUYsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsQ0FBQztRQUN0QyxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFjLENBQUM7WUFDbkMsU0FBUyxDQUFDLE9BQU8sRUFBRSxvQ0FBb0MsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNsRSxNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0lBRUQsMEZBQTBGO0lBQzFGLDBGQUEwRjtJQUMxRix1RUFBdUU7SUFDL0QsS0FBSyxDQUFDLHFCQUFxQixDQUFDLEVBQUUsaUJBQWlCLEdBQUcsSUFBSSxFQUFFLEdBQUcsRUFBRTtRQUNuRSxnRkFBZ0Y7UUFDaEYsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksNENBQW9CLENBQUk7WUFDbEQsZ0NBQWdDLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQ0FBZ0MsSUFBSSxLQUFLO1lBQ3hGLFFBQVEsRUFBRSxRQUFRO1NBQ25CLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFdkUsSUFBSSxpQkFBaUIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2pELE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO1lBQzVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsb0NBQXNCLEVBQUU7Z0JBQ2hELEtBQUs7Z0JBQ0wsTUFBTTtnQkFDTixRQUFRO2dCQUNSLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU07YUFDNUIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFTyxlQUFlO1FBQ3JCLE9BQU8sbUJBQWUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3ZGLENBQUM7SUFFTyxLQUFLLENBQUMsd0JBQXdCO1FBS3BDLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRTVFLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDdEQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUNsQyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQztZQUMxQixJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztZQUMzQixDQUFDLFlBQVksSUFBSSxXQUFXO2dCQUMxQixDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyx1QkFBdUIsQ0FBQyxXQUFXLEVBQUUsZUFBZSxFQUFFLE1BQU0sQ0FBQztnQkFDL0UsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUU7U0FDdEIsQ0FBQyxDQUFDO1FBRUgsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOztPQUVHO0lBQ08sS0FBSyxDQUFDLFVBQVUsQ0FBQyxVQUFzQjtRQUMvQyxNQUFNLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRWxGLG1EQUFtRDtRQUNuRCxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQ2pCLE1BQU0sRUFDTixxRUFBcUUsQ0FDdEUsQ0FBQztZQUVGLE9BQU87UUFDVCxDQUFDO1FBRUQsMERBQTBEO1FBQzFELElBQUksTUFBeUMsQ0FBQztRQUM5QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFcEMsNEZBQTRGO1FBQzVGLElBQUksQ0FBQyxZQUFZLEVBQUUsb0JBQW9CLElBQUksWUFBWSxFQUFFLENBQUM7WUFDeEQsSUFBSSxDQUFDO2dCQUNILE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sSUFBQSxtQkFBUSxFQUFDLFVBQVUsRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDekUsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyxjQUFjLFVBQVUsa0RBQWtELENBQUMsQ0FBQztZQUM5RixDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUU1RCxNQUFNLE1BQU0sR0FBRyxJQUFBLHVDQUFTLEVBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sSUFBQSxvQkFBUyxFQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBRUQsZ0NBQWdDO1FBQ2hDLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0F1Qkc7SUFDSCxLQUFLLENBQUMsa0JBQWtCO1FBQ3RCLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRTFFLElBQUksQ0FBQztZQUNILE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLEVBQUUsaUJBQWlCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNsRixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUVwQyxNQUFNLElBQUEsb0JBQVMsRUFBQyxVQUFVLEVBQUUsSUFBQSx1Q0FBUyxFQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRTtnQkFDOUUsUUFBUSxFQUFFLE9BQU87YUFDbEIsQ0FBQyxDQUFDO1lBRUgsSUFBSSxXQUFXLEVBQUUsQ0FBQztnQkFDaEIsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDdEYsQ0FBQztZQUVELE1BQU0sQ0FBQyxNQUFNLEVBQUUscUJBQXFCLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDcEQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsS0FBYyxDQUFDO1lBQ25DLE1BQU0sQ0FBQyxPQUFPLEVBQUUsMENBQTBDLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDckUsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBL2lCRCx3QkEraUJDIn0=
|
|
597
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFxQkEsOEVBQTBFO0FBQzFFLGlFQUF5QztBQUN6QyxxREFBNkI7QUFDN0IseURBQWlDO0FBQ2pDLDBDQUFrRDtBQUNsRCxrR0FBc0Q7QUFFdEQsK0NBQXVEO0FBQ3ZELDZDQUEyRDtBQUMzRCxrRUFBeUM7QUFDekMsOEZBQW9FO0FBQ3BFLDRFQUFtRDtBQUNuRCxzREFBa0M7QUFDbEMsMERBQXNDO0FBQ3RDLGtHQUFpRjtBQUNqRiwyREFBd0Y7QUFDeEYsZ0ZBQThEO0FBQzlELGtGQUF5RDtBQUV6RCw2RkFBNkY7QUFDN0YsK0ZBQStGO0FBQy9GLHFGQUFxRjtBQUNyRixNQUFNLGVBQWUsR0FBRyxDQUFDLFdBQW1CLEVBQUUsRUFBRSxDQUM5QyxpRUFBaUUsV0FBVyxnQkFBZ0I7SUFDNUYsc0JBQXNCLHVCQUFVLHVDQUF1Qyx1QkFBVSxVQUFVO0lBQzNGLEdBQUcsdUJBQVUsd0NBQXdDLENBQUM7QUFFeEQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBcUIsS0FBbUMsU0FBUSwyQkFBZ0I7SUE4QjlFOzs7Ozs7Ozs7Ozs7Ozs7T0FlRztJQUNILFlBQVksT0FBcUI7UUFDL0IsTUFBTSxVQUFVLEdBQUcsMkJBQWdCLENBQUMsUUFBUSxDQUFDLDJCQUFnQixDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3JGLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQXpDOUMsMkNBQTJDO1FBQ25DLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFPM0IsdUZBQXVGO1FBQy9FLHFCQUFnQixHQUFvQyxJQUFJLENBQUM7UUFFakUsNERBQTREO1FBQ3BELGdCQUFXLEdBQXVCLElBQUksQ0FBQztRQUV2QyxpQkFB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
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an embedded BFF answers, at the root of the host application. Fixed: the BFF serves its own
|
|
3
|
+
* `/oauth/*` and `/docs`, which would otherwise collide with the MCP server's root paths and with
|
|
4
|
+
* whatever the host already serves.
|
|
5
|
+
*/
|
|
6
|
+
export declare const BFF_PREFIX = "/bff";
|
|
7
|
+
/**
|
|
8
|
+
* Matches on the pathname and on a segment boundary, so `/bff?x=1` is claimed and `/bffalo` is not.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isBffRoute(url: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The url the BFF itself expects: it knows nothing of the prefix the host serves it under, and its
|
|
13
|
+
* routes are absolute (`/agent/v1/…`, `/health`). Never yields an empty string — Koa would read that
|
|
14
|
+
* as a malformed request rather than as the root.
|
|
15
|
+
*/
|
|
16
|
+
export declare function stripBffPrefix(url: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Whether an MCP mount path would land inside `/bff`. The MCP server normalizes its `basePath`
|
|
19
|
+
* (trim, leading slash, collapsed and stripped trailing slashes) before deriving
|
|
20
|
+
* `<basePath>/oauth/` and `<basePath>/mcp`, so comparing the raw option to `/bff` would let `bff`,
|
|
21
|
+
* `/bff/` and `/bff/ai` through — each of which claims paths the BFF answers on. The normalization
|
|
22
|
+
* is mirrored rather than imported: mcp-server keeps it internal.
|
|
23
|
+
*/
|
|
24
|
+
export declare function collidesWithBff(mcpBasePath?: string): boolean;
|
|
25
|
+
//# sourceMappingURL=bff-routes.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BFF_PREFIX = void 0;
|
|
4
|
+
exports.isBffRoute = isBffRoute;
|
|
5
|
+
exports.stripBffPrefix = stripBffPrefix;
|
|
6
|
+
exports.collidesWithBff = collidesWithBff;
|
|
7
|
+
/**
|
|
8
|
+
* Where an embedded BFF answers, at the root of the host application. Fixed: the BFF serves its own
|
|
9
|
+
* `/oauth/*` and `/docs`, which would otherwise collide with the MCP server's root paths and with
|
|
10
|
+
* whatever the host already serves.
|
|
11
|
+
*/
|
|
12
|
+
exports.BFF_PREFIX = '/bff';
|
|
13
|
+
/**
|
|
14
|
+
* Matches on the pathname and on a segment boundary, so `/bff?x=1` is claimed and `/bffalo` is not.
|
|
15
|
+
*/
|
|
16
|
+
function isBffRoute(url) {
|
|
17
|
+
const [pathname] = url.split(/[?#]/, 1);
|
|
18
|
+
return pathname === exports.BFF_PREFIX || pathname.startsWith(`${exports.BFF_PREFIX}/`);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The url the BFF itself expects: it knows nothing of the prefix the host serves it under, and its
|
|
22
|
+
* routes are absolute (`/agent/v1/…`, `/health`). Never yields an empty string — Koa would read that
|
|
23
|
+
* as a malformed request rather than as the root.
|
|
24
|
+
*/
|
|
25
|
+
function stripBffPrefix(url) {
|
|
26
|
+
const remainder = url.slice(exports.BFF_PREFIX.length);
|
|
27
|
+
if (remainder === '')
|
|
28
|
+
return '/';
|
|
29
|
+
return remainder.startsWith('/') ? remainder : `/${remainder}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether an MCP mount path would land inside `/bff`. The MCP server normalizes its `basePath`
|
|
33
|
+
* (trim, leading slash, collapsed and stripped trailing slashes) before deriving
|
|
34
|
+
* `<basePath>/oauth/` and `<basePath>/mcp`, so comparing the raw option to `/bff` would let `bff`,
|
|
35
|
+
* `/bff/` and `/bff/ai` through — each of which claims paths the BFF answers on. The normalization
|
|
36
|
+
* is mirrored rather than imported: mcp-server keeps it internal.
|
|
37
|
+
*/
|
|
38
|
+
function collidesWithBff(mcpBasePath) {
|
|
39
|
+
if (!mcpBasePath)
|
|
40
|
+
return false;
|
|
41
|
+
const trimmed = mcpBasePath.trim();
|
|
42
|
+
if (trimmed === '' || trimmed === '/')
|
|
43
|
+
return false;
|
|
44
|
+
const normalized = (trimmed.startsWith('/') ? trimmed : `/${trimmed}`)
|
|
45
|
+
.replace(/\/+/g, '/')
|
|
46
|
+
.replace(/\/+$/, '');
|
|
47
|
+
return isBffRoute(`${normalized}/mcp`);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmZmLXJvdXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9iZmYtcm91dGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVVBLGdDQUlDO0FBT0Qsd0NBTUM7QUFTRCwwQ0FZQztBQWhERDs7OztHQUlHO0FBQ1UsUUFBQSxVQUFVLEdBQUcsTUFBTSxDQUFDO0FBRWpDOztHQUVHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLEdBQVc7SUFDcEMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRXhDLE9BQU8sUUFBUSxLQUFLLGtCQUFVLElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxHQUFHLGtCQUFVLEdBQUcsQ0FBQyxDQUFDO0FBQzFFLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLEdBQVc7SUFDeEMsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxrQkFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRS9DLElBQUksU0FBUyxLQUFLLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUVqQyxPQUFPLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxTQUFTLEVBQUUsQ0FBQztBQUNqRSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLFdBQW9CO0lBQ2xELElBQUksQ0FBQyxXQUFXO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFFL0IsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO0lBRW5DLElBQUksT0FBTyxLQUFLLEVBQUUsSUFBSSxPQUFPLEtBQUssR0FBRztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBRXBELE1BQU0sVUFBVSxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDO1NBQ25FLE9BQU8sQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDO1NBQ3BCLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFdkIsT0FBTyxVQUFVLENBQUMsR0FBRyxVQUFVLE1BQU0sQ0FBQyxDQUFDO0FBQ3pDLENBQUMifQ==
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { AgentOptionsWithDefaults, BffEmbedOptions, HttpCallback } from './types';
|
|
2
|
+
import type { AgentDispatcher } from '@forestadmin/agent-bff';
|
|
3
|
+
/**
|
|
4
|
+
* Owns the lifecycle of a BFF embedded in the agent process: configuration, dynamic loading of the
|
|
5
|
+
* optional package, build, and the request handler the agent mounts at `/bff`. The agent only wires
|
|
6
|
+
* the callback and delegates start/stop.
|
|
7
|
+
*/
|
|
8
|
+
export default class EmbeddedBff {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private readonly embedOptions;
|
|
11
|
+
private config;
|
|
12
|
+
private bff;
|
|
13
|
+
private stopped;
|
|
14
|
+
constructor(options: AgentOptionsWithDefaults, embedOptions: BffEmbedOptions);
|
|
15
|
+
/**
|
|
16
|
+
* Load the package and validate the options the caller handed to `addBff()`. Called before the
|
|
17
|
+
* agent mounts anything: everything checked here is caller input, and `parseConfig` throws on a
|
|
18
|
+
* mistyped `tokenEncryptionKey`, timezone, timeout or url. Failing here leaves nothing serving,
|
|
19
|
+
* where failing after mount() would leave the host with a live `/forest` and a bricked `/bff`.
|
|
20
|
+
*/
|
|
21
|
+
prepare(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Build the BFF. Called from agent.start() after mount(), because the dispatcher only reaches the
|
|
24
|
+
* agent's own stack once that stack is mounted.
|
|
25
|
+
*/
|
|
26
|
+
start(dispatcher: AgentDispatcher): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* The whitelist exempts a caller arriving over a loopback socket with no proxy hop, which is
|
|
29
|
+
* exactly what the in-process transport looks like — so every BFF request escapes it. That is the
|
|
30
|
+
* decision, not an oversight: propagating the caller's ip would make the embedded mode stricter
|
|
31
|
+
* than the standalone one, where the whitelist only ever sees the BFF's own host, and would refuse
|
|
32
|
+
* the browsers a third-party UI is made of. What it must not be is silent — an operator who turned
|
|
33
|
+
* the whitelist on to close a door has no other way to learn this door is not part of it.
|
|
34
|
+
*
|
|
35
|
+
* Reads the configuration itself rather than borrowing the one `IpWhitelist` already fetched: that
|
|
36
|
+
* route keeps it private, and reaching into it would put BFF concerns in an unrelated part of the
|
|
37
|
+
* agent. Costs one round-trip at boot. Never fails the boot: a warning is not worth refusing to
|
|
38
|
+
* serve over, and this is the same posture as the rest of the BFF's startup.
|
|
39
|
+
*/
|
|
40
|
+
private warnIfExemptFromIpWhitelist;
|
|
41
|
+
/** Drop what the BFF read from the SaaS. Called on a restart, which means the schema moved. */
|
|
42
|
+
invalidate(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Stop answering. The host application keeps whatever middleware it registered, so without this
|
|
45
|
+
* a stopped agent would go on serving BFF data through a dispatcher pointing at a dead stack.
|
|
46
|
+
*/
|
|
47
|
+
stop(): void;
|
|
48
|
+
/**
|
|
49
|
+
* The callback the agent registers at `/bff`. Answers 503 rather than falling through while the
|
|
50
|
+
* BFF is not serving: a 404 from the host would read as "wrong url" instead of "not available".
|
|
51
|
+
* Boot and shutdown are told apart, because a probe should wait on the first and drain on the
|
|
52
|
+
* second.
|
|
53
|
+
*/
|
|
54
|
+
readonly handle: HttpCallback;
|
|
55
|
+
/**
|
|
56
|
+
* Dynamically load the optional @forestadmin/agent-bff package. Deferred so agents that embed no
|
|
57
|
+
* BFF never load its code at startup.
|
|
58
|
+
*/
|
|
59
|
+
private importPackage;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=embedded-bff.d.ts.map
|