cdk-local-lambda 0.0.2
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/LICENSE +202 -0
- package/README.md +94 -0
- package/lib/aspect/docker-function-hook.d.ts +18 -0
- package/lib/aspect/docker-function-hook.js +31 -0
- package/lib/aspect/live-lambda-aspect.d.ts +85 -0
- package/lib/aspect/live-lambda-aspect.js +277 -0
- package/lib/aspect/live-lambda-bootstrap.d.ts +17 -0
- package/lib/aspect/live-lambda-bootstrap.js +260 -0
- package/lib/aspect/nodejs-function-hook.d.ts +20 -0
- package/lib/aspect/nodejs-function-hook.js +27 -0
- package/lib/bootstrap-stack/bootstrap-stack.d.ts +60 -0
- package/lib/bootstrap-stack/bootstrap-stack.js +338 -0
- package/lib/cli/appsync/client.d.ts +30 -0
- package/lib/cli/appsync/client.js +227 -0
- package/lib/cli/cdk-app.d.ts +7 -0
- package/lib/cli/cdk-app.js +25 -0
- package/lib/cli/commands/bootstrap.d.ts +9 -0
- package/lib/cli/commands/bootstrap.js +50 -0
- package/lib/cli/commands/local.d.ts +40 -0
- package/lib/cli/commands/local.js +1172 -0
- package/lib/cli/daemon.d.ts +22 -0
- package/lib/cli/daemon.js +18 -0
- package/lib/cli/docker/container.d.ts +116 -0
- package/lib/cli/docker/container.js +414 -0
- package/lib/cli/docker/types.d.ts +71 -0
- package/lib/cli/docker/types.js +5 -0
- package/lib/cli/docker/watcher.d.ts +44 -0
- package/lib/cli/docker/watcher.js +115 -0
- package/lib/cli/index.d.ts +9 -0
- package/lib/cli/index.js +26 -0
- package/lib/cli/runtime-api/server.d.ts +102 -0
- package/lib/cli/runtime-api/server.js +396 -0
- package/lib/cli/runtime-api/types.d.ts +149 -0
- package/lib/cli/runtime-api/types.js +10 -0
- package/lib/cli/runtime-wrapper/nodejs-runtime.d.ts +16 -0
- package/lib/cli/runtime-wrapper/nodejs-runtime.js +248 -0
- package/lib/cli/watcher/file-watcher.d.ts +32 -0
- package/lib/cli/watcher/file-watcher.js +57 -0
- package/lib/functions/bridge/appsync-client.d.ts +73 -0
- package/lib/functions/bridge/appsync-client.js +345 -0
- package/lib/functions/bridge/handler.d.ts +17 -0
- package/lib/functions/bridge/handler.js +79 -0
- package/lib/functions/bridge/ssm-config.d.ts +19 -0
- package/lib/functions/bridge/ssm-config.js +45 -0
- package/lib/functions/bridge-builder/handler.d.ts +12 -0
- package/lib/functions/bridge-builder/handler.js +181 -0
- package/lib/functions/bridge-docker/runtime.d.ts +9 -0
- package/lib/functions/bridge-docker/runtime.js +127 -0
- package/lib/index.d.ts +24 -0
- package/lib/index.js +28 -0
- package/lib/shared/types.d.ts +102 -0
- package/lib/shared/types.js +125 -0
- package/package.json +111 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lambda Runtime API HTTP server using Effect HttpServer.
|
|
3
|
+
*
|
|
4
|
+
* This server emulates the AWS Lambda Runtime API that Docker containers
|
|
5
|
+
* use to receive invocations and send responses.
|
|
6
|
+
*
|
|
7
|
+
* Each Lambda function gets its own server on an ephemeral port. The server
|
|
8
|
+
* maintains a queue of pending invocations. When a container polls
|
|
9
|
+
* /invocation/next, it blocks until an invocation is available.
|
|
10
|
+
*
|
|
11
|
+
* @see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html
|
|
12
|
+
*/
|
|
13
|
+
import * as Headers from "@effect/platform/Headers";
|
|
14
|
+
import * as HttpRouter from "@effect/platform/HttpRouter";
|
|
15
|
+
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
|
16
|
+
import * as HttpServerResponse from "@effect/platform/HttpServerResponse";
|
|
17
|
+
import * as BunHttpServer from "@effect/platform-bun/BunHttpServer";
|
|
18
|
+
import { Effect, HashMap, Option, Queue, Ref } from "effect";
|
|
19
|
+
/**
|
|
20
|
+
* Create a new Runtime API state (queues only, no port).
|
|
21
|
+
*
|
|
22
|
+
* @param functionMetadata - Function metadata for extension registration responses
|
|
23
|
+
*/
|
|
24
|
+
export const makeRuntimeApiState = (functionMetadata) => Effect.gen(function* () {
|
|
25
|
+
const invocationQueue = yield* Queue.unbounded();
|
|
26
|
+
const responseQueue = yield* Queue.unbounded();
|
|
27
|
+
const extensions = yield* Ref.make(HashMap.empty());
|
|
28
|
+
return {
|
|
29
|
+
invocationQueue,
|
|
30
|
+
responseQueue,
|
|
31
|
+
extensions,
|
|
32
|
+
functionMetadata,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Default poll timeout - used when not overridden.
|
|
37
|
+
*
|
|
38
|
+
* ## Why containers can't stay warm indefinitely (like AWS Lambda does)
|
|
39
|
+
*
|
|
40
|
+
* AWS Lambda keeps containers warm for ~5-15 minutes between invocations.
|
|
41
|
+
* Their Runtime API implementation can hold HTTP connections open indefinitely
|
|
42
|
+
* because they control the entire infrastructure end-to-end.
|
|
43
|
+
*
|
|
44
|
+
* In local development, we're constrained by HTTP server limitations:
|
|
45
|
+
* - Bun's maximum `idleTimeout` is 255 seconds (~4.25 minutes)
|
|
46
|
+
* - This is a practical limit to prevent resource exhaustion in HTTP servers
|
|
47
|
+
* - When the timeout expires, Bun forcefully closes the connection
|
|
48
|
+
* - The Lambda RIC interprets this as a fatal "No Response from endpoint" error
|
|
49
|
+
*
|
|
50
|
+
* Our solution: timeout slightly before Bun does (240s vs 255s) and return
|
|
51
|
+
* HTTP 503, which causes the RIC to exit gracefully. The container will be
|
|
52
|
+
* automatically restarted on the next invocation (~2 seconds for warm images).
|
|
53
|
+
*
|
|
54
|
+
* This is an inherent limitation of local Lambda emulation - AWS's purpose-built
|
|
55
|
+
* infrastructure simply doesn't have the same timeout constraints.
|
|
56
|
+
*/
|
|
57
|
+
const DEFAULT_POLL_TIMEOUT_MS = 240_000; // 4 minutes
|
|
58
|
+
/**
|
|
59
|
+
* Handle GET /2018-06-01/runtime/invocation/next
|
|
60
|
+
* Polls for an invocation with a bounded timeout to handle idle containers gracefully.
|
|
61
|
+
* This ensures that if no invocations arrive within the timeout, the container
|
|
62
|
+
* exits cleanly rather than being killed by an HTTP timeout.
|
|
63
|
+
*
|
|
64
|
+
* When the timeout expires, we return a 503 Service Unavailable which signals
|
|
65
|
+
* to the Lambda RIC that it should exit. The container will be restarted
|
|
66
|
+
* automatically when the next invocation arrives.
|
|
67
|
+
*/
|
|
68
|
+
const handleInvocationNext = (state, pollTimeoutMs) => Effect.gen(function* () {
|
|
69
|
+
yield* Effect.logDebug("Container polling for next invocation");
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
// Poll with timeout instead of blocking indefinitely
|
|
72
|
+
// This allows us to detect connection issues and keep the invocation in the queue
|
|
73
|
+
let invocation = null;
|
|
74
|
+
while (invocation === null) {
|
|
75
|
+
// Check if we've exceeded the timeout
|
|
76
|
+
if (Date.now() - startTime > pollTimeoutMs) {
|
|
77
|
+
yield* Effect.logDebug("Invocation poll timeout - returning 503 to trigger container exit");
|
|
78
|
+
// Return 503 Service Unavailable to signal the RIC to exit gracefully
|
|
79
|
+
// This is expected behavior for idle containers in local development
|
|
80
|
+
return HttpServerResponse.empty({
|
|
81
|
+
status: 503,
|
|
82
|
+
headers: Headers.fromInput({
|
|
83
|
+
"Content-Type": "application/json",
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Try to take from queue with a short timeout
|
|
88
|
+
const result = yield* Queue.poll(state.invocationQueue);
|
|
89
|
+
if (Option.isSome(result)) {
|
|
90
|
+
invocation = result.value;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// Queue is empty, wait a bit before retrying
|
|
94
|
+
yield* Effect.sleep("100 millis");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
yield* Effect.logDebug(`Returning invocation ${invocation.requestId} to container`);
|
|
98
|
+
return yield* HttpServerResponse.json(invocation.event, {
|
|
99
|
+
status: 200,
|
|
100
|
+
headers: Headers.fromInput({
|
|
101
|
+
"Lambda-Runtime-Aws-Request-Id": invocation.requestId,
|
|
102
|
+
"Lambda-Runtime-Deadline-Ms": String(invocation.deadlineMs),
|
|
103
|
+
"Lambda-Runtime-Invoked-Function-Arn": invocation.invokedFunctionArn,
|
|
104
|
+
"Lambda-Runtime-Log-Group-Name": invocation.logGroupName,
|
|
105
|
+
"Lambda-Runtime-Log-Stream-Name": invocation.logStreamName,
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
/**
|
|
110
|
+
* Handle POST /2018-06-01/runtime/invocation/:requestId/response
|
|
111
|
+
*/
|
|
112
|
+
const handleInvocationResponse = (state) => Effect.gen(function* () {
|
|
113
|
+
const params = yield* HttpRouter.params;
|
|
114
|
+
const requestId = params.requestId ?? "";
|
|
115
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
116
|
+
// Body might not be JSON, so gracefully handle parse errors
|
|
117
|
+
const body = yield* Effect.orElseSucceed(request.json, () => null);
|
|
118
|
+
const response = {
|
|
119
|
+
requestId,
|
|
120
|
+
body,
|
|
121
|
+
};
|
|
122
|
+
yield* Effect.logDebug(`Received response for ${requestId}`);
|
|
123
|
+
yield* Queue.offer(state.responseQueue, response);
|
|
124
|
+
return HttpServerResponse.empty({ status: 202 });
|
|
125
|
+
});
|
|
126
|
+
/**
|
|
127
|
+
* Handle POST /2018-06-01/runtime/invocation/:requestId/error
|
|
128
|
+
*/
|
|
129
|
+
const handleInvocationError = (state) => Effect.gen(function* () {
|
|
130
|
+
const params = yield* HttpRouter.params;
|
|
131
|
+
const requestId = params.requestId ?? "";
|
|
132
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
133
|
+
// Body might not be JSON, so gracefully handle parse errors
|
|
134
|
+
const errorBody = yield* Effect.orElseSucceed(request.json, () => ({}));
|
|
135
|
+
const errorTypeHeader = Headers.get(request.headers, "lambda-runtime-function-error-type");
|
|
136
|
+
const errorType = Option.getOrElse(errorTypeHeader, () => "Error");
|
|
137
|
+
const error = {
|
|
138
|
+
requestId,
|
|
139
|
+
errorType: String(errorType),
|
|
140
|
+
errorMessage: errorBody.errorMessage ?? "Unknown error",
|
|
141
|
+
stackTrace: errorBody.stackTrace,
|
|
142
|
+
};
|
|
143
|
+
yield* Effect.logDebug(`Received error for ${requestId}: ${error.errorMessage}`);
|
|
144
|
+
yield* Queue.offer(state.responseQueue, error);
|
|
145
|
+
return HttpServerResponse.empty({ status: 202 });
|
|
146
|
+
});
|
|
147
|
+
/**
|
|
148
|
+
* Handle POST /2018-06-01/runtime/init/error
|
|
149
|
+
*/
|
|
150
|
+
const handleInitError = (state) => Effect.gen(function* () {
|
|
151
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
152
|
+
// Body might not be JSON, so gracefully handle parse errors
|
|
153
|
+
const errorBody = yield* Effect.orElseSucceed(request.json, () => ({}));
|
|
154
|
+
const errorTypeHeader = Headers.get(request.headers, "lambda-runtime-function-error-type");
|
|
155
|
+
const errorType = Option.getOrElse(errorTypeHeader, () => "InitError");
|
|
156
|
+
const error = {
|
|
157
|
+
errorType: String(errorType),
|
|
158
|
+
errorMessage: errorBody.errorMessage ?? "Unknown init error",
|
|
159
|
+
stackTrace: errorBody.stackTrace,
|
|
160
|
+
};
|
|
161
|
+
yield* Effect.logDebug(`Received init error: ${error.errorMessage}`);
|
|
162
|
+
yield* Queue.offer(state.responseQueue, error);
|
|
163
|
+
return HttpServerResponse.empty({ status: 202 });
|
|
164
|
+
});
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Extensions API handlers
|
|
167
|
+
// @see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html
|
|
168
|
+
// ============================================================================
|
|
169
|
+
/**
|
|
170
|
+
* Handle POST /2020-01-01/extension/register
|
|
171
|
+
* Extensions call this to register for lifecycle events.
|
|
172
|
+
*/
|
|
173
|
+
const handleExtensionRegister = (state) => Effect.gen(function* () {
|
|
174
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
175
|
+
// Get extension name from header (required)
|
|
176
|
+
const extensionNameHeader = Headers.get(request.headers, "lambda-extension-name");
|
|
177
|
+
const extensionName = Option.getOrElse(extensionNameHeader, () => "unknown-extension");
|
|
178
|
+
// Parse request body for events to register for
|
|
179
|
+
const body = yield* Effect.orElseSucceed(request.json, () => ({}));
|
|
180
|
+
const events = body.events ?? ["INVOKE", "SHUTDOWN"];
|
|
181
|
+
// Generate unique extension ID
|
|
182
|
+
const extensionId = crypto.randomUUID();
|
|
183
|
+
// Create event queue for this extension
|
|
184
|
+
const eventQueue = yield* Queue.unbounded();
|
|
185
|
+
const extensionState = {
|
|
186
|
+
extension: {
|
|
187
|
+
extensionId,
|
|
188
|
+
name: extensionName,
|
|
189
|
+
events,
|
|
190
|
+
},
|
|
191
|
+
eventQueue,
|
|
192
|
+
};
|
|
193
|
+
// Register the extension
|
|
194
|
+
yield* Ref.update(state.extensions, (exts) => HashMap.set(exts, extensionId, extensionState));
|
|
195
|
+
yield* Effect.logDebug(`Extension registered: ${extensionName} (${extensionId}) for events: ${events.join(", ")}`);
|
|
196
|
+
return yield* HttpServerResponse.json({
|
|
197
|
+
functionName: state.functionMetadata.functionName,
|
|
198
|
+
functionVersion: state.functionMetadata.functionVersion,
|
|
199
|
+
handler: state.functionMetadata.handler,
|
|
200
|
+
}, {
|
|
201
|
+
status: 200,
|
|
202
|
+
headers: Headers.fromInput({
|
|
203
|
+
"Lambda-Extension-Identifier": extensionId,
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
/**
|
|
208
|
+
* Handle GET /2020-01-01/extension/event/next
|
|
209
|
+
* Extensions call this to poll for the next lifecycle event.
|
|
210
|
+
*/
|
|
211
|
+
const handleExtensionEventNext = (state, pollTimeoutMs) => Effect.gen(function* () {
|
|
212
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
213
|
+
// Get extension ID from header (required)
|
|
214
|
+
const extensionIdHeader = Headers.get(request.headers, "lambda-extension-identifier");
|
|
215
|
+
const extensionId = Option.getOrElse(extensionIdHeader, () => "");
|
|
216
|
+
if (!extensionId) {
|
|
217
|
+
return HttpServerResponse.empty({
|
|
218
|
+
status: 403,
|
|
219
|
+
headers: Headers.fromInput({
|
|
220
|
+
"Content-Type": "application/json",
|
|
221
|
+
}),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
// Find the extension
|
|
225
|
+
const extensions = yield* Ref.get(state.extensions);
|
|
226
|
+
const extensionState = HashMap.get(extensions, extensionId);
|
|
227
|
+
if (Option.isNone(extensionState)) {
|
|
228
|
+
yield* Effect.logDebug(`Extension not found: ${extensionId}`);
|
|
229
|
+
return HttpServerResponse.empty({
|
|
230
|
+
status: 403,
|
|
231
|
+
headers: Headers.fromInput({
|
|
232
|
+
"Content-Type": "application/json",
|
|
233
|
+
}),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
const { eventQueue, extension } = extensionState.value;
|
|
237
|
+
yield* Effect.logDebug(`Extension ${extension.name} polling for next event`);
|
|
238
|
+
const startTime = Date.now();
|
|
239
|
+
// Poll for the next event with timeout
|
|
240
|
+
let event = null;
|
|
241
|
+
while (event === null) {
|
|
242
|
+
if (Date.now() - startTime > pollTimeoutMs) {
|
|
243
|
+
yield* Effect.logDebug("Extension event poll timeout - returning 503 to trigger exit");
|
|
244
|
+
return HttpServerResponse.empty({
|
|
245
|
+
status: 503,
|
|
246
|
+
headers: Headers.fromInput({
|
|
247
|
+
"Content-Type": "application/json",
|
|
248
|
+
}),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const result = yield* Queue.poll(eventQueue);
|
|
252
|
+
if (Option.isSome(result)) {
|
|
253
|
+
event = result.value;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
yield* Effect.sleep("100 millis");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
yield* Effect.logDebug(`Returning ${event.eventType} event to extension ${extension.name}`);
|
|
260
|
+
return yield* HttpServerResponse.json(event, {
|
|
261
|
+
status: 200,
|
|
262
|
+
headers: Headers.fromInput({
|
|
263
|
+
"Lambda-Extension-Event-Identifier": crypto.randomUUID(),
|
|
264
|
+
}),
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
/**
|
|
268
|
+
* Handle POST /2020-01-01/extension/init/error
|
|
269
|
+
* Extensions call this to report initialization errors.
|
|
270
|
+
*/
|
|
271
|
+
const handleExtensionInitError = (state) => Effect.gen(function* () {
|
|
272
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
273
|
+
const extensionIdHeader = Headers.get(request.headers, "lambda-extension-identifier");
|
|
274
|
+
const extensionId = Option.getOrElse(extensionIdHeader, () => "unknown");
|
|
275
|
+
const errorBody = yield* Effect.orElseSucceed(request.json, () => ({}));
|
|
276
|
+
yield* Effect.logDebug(`Extension ${extensionId} init error: ${errorBody.errorMessage ?? "unknown"}`);
|
|
277
|
+
// Report the error through the response queue
|
|
278
|
+
const initError = {
|
|
279
|
+
errorType: errorBody.errorType ?? "Extension.InitError",
|
|
280
|
+
errorMessage: errorBody.errorMessage ?? "Extension initialization failed",
|
|
281
|
+
};
|
|
282
|
+
yield* Queue.offer(state.responseQueue, initError);
|
|
283
|
+
return HttpServerResponse.empty({ status: 202 });
|
|
284
|
+
});
|
|
285
|
+
/**
|
|
286
|
+
* Handle POST /2020-01-01/extension/exit/error
|
|
287
|
+
* Extensions call this to report errors before exiting.
|
|
288
|
+
*/
|
|
289
|
+
const handleExtensionExitError = () => Effect.gen(function* () {
|
|
290
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
291
|
+
const extensionIdHeader = Headers.get(request.headers, "lambda-extension-identifier");
|
|
292
|
+
const extensionId = Option.getOrElse(extensionIdHeader, () => "unknown");
|
|
293
|
+
const errorBody = yield* Effect.orElseSucceed(request.json, () => ({}));
|
|
294
|
+
yield* Effect.logDebug(`Extension ${extensionId} exit error: ${errorBody.errorMessage ?? "unknown"}`);
|
|
295
|
+
// Just acknowledge - extension is exiting anyway
|
|
296
|
+
return HttpServerResponse.empty({ status: 202 });
|
|
297
|
+
});
|
|
298
|
+
// ============================================================================
|
|
299
|
+
// Router
|
|
300
|
+
// ============================================================================
|
|
301
|
+
/**
|
|
302
|
+
* Create the Runtime API router for a given state.
|
|
303
|
+
*/
|
|
304
|
+
const makeRuntimeApiRouter = (state, pollTimeoutMs) => HttpRouter.empty.pipe(
|
|
305
|
+
// Runtime API (2018-06-01)
|
|
306
|
+
HttpRouter.get("/2018-06-01/runtime/invocation/next", handleInvocationNext(state, pollTimeoutMs)), HttpRouter.post("/2018-06-01/runtime/invocation/:requestId/response", handleInvocationResponse(state)), HttpRouter.post("/2018-06-01/runtime/invocation/:requestId/error", handleInvocationError(state)), HttpRouter.post("/2018-06-01/runtime/init/error", handleInitError(state)),
|
|
307
|
+
// Extensions API (2020-01-01)
|
|
308
|
+
HttpRouter.post("/2020-01-01/extension/register", handleExtensionRegister(state)), HttpRouter.get("/2020-01-01/extension/event/next", handleExtensionEventNext(state, pollTimeoutMs)), HttpRouter.post("/2020-01-01/extension/init/error", handleExtensionInitError(state)), HttpRouter.post("/2020-01-01/extension/exit/error", handleExtensionExitError()));
|
|
309
|
+
const DEFAULT_FUNCTION_METADATA = {
|
|
310
|
+
functionName: "local-function",
|
|
311
|
+
functionVersion: "$LATEST",
|
|
312
|
+
handler: "index.handler",
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Start a Runtime API server on an ephemeral port.
|
|
316
|
+
* Returns the actual port and state for this server instance.
|
|
317
|
+
*
|
|
318
|
+
* The server is scoped - it will be stopped when the scope closes.
|
|
319
|
+
*
|
|
320
|
+
* @param options - Server configuration options
|
|
321
|
+
*/
|
|
322
|
+
export const startRuntimeApiServer = (options = {}) => Effect.gen(function* () {
|
|
323
|
+
const pollTimeoutMs = options.pollTimeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
|
|
324
|
+
const functionMetadata = options.functionMetadata ?? DEFAULT_FUNCTION_METADATA;
|
|
325
|
+
// Create state (queues) for this server
|
|
326
|
+
const state = yield* makeRuntimeApiState(functionMetadata);
|
|
327
|
+
// Create router for this state
|
|
328
|
+
const router = makeRuntimeApiRouter(state, pollTimeoutMs);
|
|
329
|
+
// Create HTTP server on ephemeral port (port: 0)
|
|
330
|
+
const server = yield* BunHttpServer.make({
|
|
331
|
+
port: 0,
|
|
332
|
+
hostname: "0.0.0.0",
|
|
333
|
+
idleTimeout: 255, // Max allowed by Bun (4.25 minutes) for long-polling
|
|
334
|
+
});
|
|
335
|
+
// Start serving the router
|
|
336
|
+
yield* server.serve(router);
|
|
337
|
+
// Get the actual assigned port
|
|
338
|
+
const address = server.address;
|
|
339
|
+
if (address._tag !== "TcpAddress") {
|
|
340
|
+
// This should never happen since we're using TCP
|
|
341
|
+
throw new Error("Expected TCP address");
|
|
342
|
+
}
|
|
343
|
+
yield* Effect.logDebug(`RuntimeAPI server listening on port ${address.port}`);
|
|
344
|
+
return {
|
|
345
|
+
port: address.port,
|
|
346
|
+
state,
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
/**
|
|
350
|
+
* Queue an invocation for the container to process.
|
|
351
|
+
*/
|
|
352
|
+
export const queueInvocation = (state, invocation) => Queue.offer(state.invocationQueue, invocation);
|
|
353
|
+
/**
|
|
354
|
+
* Wait for the response to a specific invocation.
|
|
355
|
+
*/
|
|
356
|
+
export const waitForResponse = (state) => Queue.take(state.responseQueue);
|
|
357
|
+
/**
|
|
358
|
+
* Notify all registered extensions about an invocation.
|
|
359
|
+
* This sends an INVOKE event to all extensions that registered for it.
|
|
360
|
+
*/
|
|
361
|
+
export const notifyExtensionsInvoke = (state, invocation) => Effect.gen(function* () {
|
|
362
|
+
const extensions = yield* Ref.get(state.extensions);
|
|
363
|
+
const invokeEvent = {
|
|
364
|
+
eventType: "INVOKE",
|
|
365
|
+
deadlineMs: invocation.deadlineMs,
|
|
366
|
+
requestId: invocation.requestId,
|
|
367
|
+
invokedFunctionArn: invocation.invokedFunctionArn,
|
|
368
|
+
};
|
|
369
|
+
// Send INVOKE event to all extensions that registered for it
|
|
370
|
+
for (const [, extState] of extensions) {
|
|
371
|
+
if (extState.extension.events.includes("INVOKE")) {
|
|
372
|
+
yield* Queue.offer(extState.eventQueue, invokeEvent);
|
|
373
|
+
yield* Effect.logDebug(`Sent INVOKE event to extension ${extState.extension.name}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
/**
|
|
378
|
+
* Notify all registered extensions about shutdown.
|
|
379
|
+
* This sends a SHUTDOWN event to all extensions that registered for it.
|
|
380
|
+
*/
|
|
381
|
+
export const notifyExtensionsShutdown = (state, reason = "SPINDOWN") => Effect.gen(function* () {
|
|
382
|
+
const extensions = yield* Ref.get(state.extensions);
|
|
383
|
+
const shutdownEvent = {
|
|
384
|
+
eventType: "SHUTDOWN",
|
|
385
|
+
shutdownReason: reason,
|
|
386
|
+
deadlineMs: Date.now() + 2000, // 2 second deadline for shutdown
|
|
387
|
+
};
|
|
388
|
+
// Send SHUTDOWN event to all extensions that registered for it
|
|
389
|
+
for (const [, extState] of extensions) {
|
|
390
|
+
if (extState.extension.events.includes("SHUTDOWN")) {
|
|
391
|
+
yield* Queue.offer(extState.eventQueue, shutdownEvent);
|
|
392
|
+
yield* Effect.logDebug(`Sent SHUTDOWN event to extension ${extState.extension.name}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NsaS9ydW50aW1lLWFwaS9zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUFFSCxPQUFPLEtBQUssT0FBTyxNQUFNLDBCQUEwQixDQUFBO0FBQ25ELE9BQU8sS0FBSyxVQUFVLE1BQU0sNkJBQTZCLENBQUE7QUFDekQsT0FBTyxLQUFLLGlCQUFpQixNQUFNLG9DQUFvQyxDQUFBO0FBQ3ZFLE9BQU8sS0FBSyxrQkFBa0IsTUFBTSxxQ0FBcUMsQ0FBQTtBQUN6RSxPQUFPLEtBQUssYUFBYSxNQUFNLG9DQUFvQyxDQUFBO0FBQ25FLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFjLE1BQU0sUUFBUSxDQUFBO0FBdUR4RTs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxnQkFBa0MsRUFBRSxFQUFFLENBQ3hFLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ2xCLE1BQU0sZUFBZSxHQUFHLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQW9CLENBQUE7SUFDbEUsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFFekMsQ0FBQTtJQUNILE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBMEIsQ0FBQyxDQUFBO0lBRTNFLE9BQU87UUFDTCxlQUFlO1FBQ2YsYUFBYTtRQUNiLFVBQVU7UUFDVixnQkFBZ0I7S0FDUyxDQUFBO0FBQzdCLENBQUMsQ0FBQyxDQUFBO0FBRUo7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sdUJBQXVCLEdBQUcsT0FBTyxDQUFBLENBQUMsWUFBWTtBQUVwRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLG9CQUFvQixHQUFHLENBQUMsS0FBc0IsRUFBRSxhQUFxQixFQUFFLEVBQUUsQ0FDN0UsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7SUFDbEIsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFBO0lBRS9ELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtJQUU1QixxREFBcUQ7SUFDckQsa0ZBQWtGO0lBQ2xGLElBQUksVUFBVSxHQUE0QixJQUFJLENBQUE7SUFFOUMsT0FBTyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDM0Isc0NBQXNDO1FBQ3RDLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFNBQVMsR0FBRyxhQUFhLEVBQUUsQ0FBQztZQUMzQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNwQixtRUFBbUUsQ0FDcEUsQ0FBQTtZQUNELHNFQUFzRTtZQUN0RSxxRUFBcUU7WUFDckUsT0FBTyxrQkFBa0IsQ0FBQyxLQUFLLENBQUM7Z0JBQzlCLE1BQU0sRUFBRSxHQUFHO2dCQUNYLE9BQU8sRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDO29CQUN6QixjQUFjLEVBQUUsa0JBQWtCO2lCQUNuQyxDQUFDO2FBQ0gsQ0FBQyxDQUFBO1FBQ0osQ0FBQztRQUVELDhDQUE4QztRQUM5QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQTtRQUV2RCxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUMxQixVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQTtRQUMzQixDQUFDO2FBQU0sQ0FBQztZQUNOLDZDQUE2QztZQUM3QyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFBO1FBQ25DLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FDcEIsd0JBQXdCLFVBQVUsQ0FBQyxTQUFTLGVBQWUsQ0FDNUQsQ0FBQTtJQUVELE9BQU8sS0FBSyxDQUFDLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUU7UUFDdEQsTUFBTSxFQUFFLEdBQUc7UUFDWCxPQUFPLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUN6QiwrQkFBK0IsRUFBRSxVQUFVLENBQUMsU0FBUztZQUNyRCw0QkFBNEIsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztZQUMzRCxxQ0FBcUMsRUFBRSxVQUFVLENBQUMsa0JBQWtCO1lBQ3BFLCtCQUErQixFQUFFLFVBQVUsQ0FBQyxZQUFZO1lBQ3hELGdDQUFnQyxFQUFFLFVBQVUsQ0FBQyxhQUFhO1NBQzNELENBQUM7S0FDSCxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQTtBQUVKOztHQUVHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLEtBQXNCLEVBQUUsRUFBRSxDQUMxRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztJQUNsQixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFBO0lBQ3ZDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFBO0lBQ3hDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFBO0lBRTFELDREQUE0RDtJQUM1RCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUE7SUFFbEUsTUFBTSxRQUFRLEdBQW1CO1FBQy9CLFNBQVM7UUFDVCxJQUFJO0tBQ0wsQ0FBQTtJQUVELEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMseUJBQXlCLFNBQVMsRUFBRSxDQUFDLENBQUE7SUFDNUQsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0lBRWpELE9BQU8sa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUE7QUFDbEQsQ0FBQyxDQUFDLENBQUE7QUFFSjs7R0FFRztBQUNILE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxLQUFzQixFQUFFLEVBQUUsQ0FDdkQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7SUFDbEIsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQTtJQUN2QyxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQTtJQUN4QyxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQTtJQUUxRCw0REFBNEQ7SUFDNUQsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FDM0MsT0FBTyxDQUFDLElBR1AsRUFDRCxHQUFxRCxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FDN0QsQ0FBQTtJQUVELE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQ2pDLE9BQU8sQ0FBQyxPQUFPLEVBQ2Ysb0NBQW9DLENBQ3JDLENBQUE7SUFDRCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUVsRSxNQUFNLEtBQUssR0FBZ0I7UUFDekIsU0FBUztRQUNULFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQzVCLFlBQVksRUFBRSxTQUFTLENBQUMsWUFBWSxJQUFJLGVBQWU7UUFDdkQsVUFBVSxFQUFFLFNBQVMsQ0FBQyxVQUFVO0tBQ2pDLENBQUE7SUFFRCxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNwQixzQkFBc0IsU0FBUyxLQUFLLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FDekQsQ0FBQTtJQUNELEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUU5QyxPQUFPLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBQ2xELENBQUMsQ0FBQyxDQUFBO0FBRUo7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQXNCLEVBQUUsRUFBRSxDQUNqRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztJQUNsQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQTtJQUUxRCw0REFBNEQ7SUFDNUQsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FDM0MsT0FBTyxDQUFDLElBR1AsRUFDRCxHQUFxRCxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FDN0QsQ0FBQTtJQUVELE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQ2pDLE9BQU8sQ0FBQyxPQUFPLEVBQ2Ysb0NBQW9DLENBQ3JDLENBQUE7SUFDRCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQTtJQUV0RSxNQUFNLEtBQUssR0FBb0I7UUFDN0IsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUM7UUFDNUIsWUFBWSxFQUFFLFNBQVMsQ0FBQyxZQUFZLElBQUksb0JBQW9CO1FBQzVELFVBQVUsRUFBRSxTQUFTLENBQUMsVUFBVTtLQUNqQyxDQUFBO0lBRUQsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUE7SUFDcEUsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBRTlDLE9BQU8sa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUE7QUFDbEQsQ0FBQyxDQUFDLENBQUE7QUFFSiwrRUFBK0U7QUFDL0UsMEJBQTBCO0FBQzFCLGlGQUFpRjtBQUNqRiwrRUFBK0U7QUFFL0U7OztHQUdHO0FBQ0gsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLEtBQXNCLEVBQUUsRUFBRSxDQUN6RCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztJQUNsQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQTtJQUUxRCw0Q0FBNEM7SUFDNUMsTUFBTSxtQkFBbUIsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUNyQyxPQUFPLENBQUMsT0FBTyxFQUNmLHVCQUF1QixDQUN4QixDQUFBO0lBQ0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FDcEMsbUJBQW1CLEVBQ25CLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUMxQixDQUFBO0lBRUQsZ0RBQWdEO0lBQ2hELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQ3RDLE9BQU8sQ0FBQyxJQUFpRSxFQUN6RSxHQUFzQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FDOUMsQ0FBQTtJQUNELE1BQU0sTUFBTSxHQUF5QixJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBRTFFLCtCQUErQjtJQUMvQixNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUE7SUFFdkMsd0NBQXdDO0lBQ3hDLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQWtCLENBQUE7SUFFM0QsTUFBTSxjQUFjLEdBQW1CO1FBQ3JDLFNBQVMsRUFBRTtZQUNULFdBQVc7WUFDWCxJQUFJLEVBQUUsYUFBYTtZQUNuQixNQUFNO1NBQ1A7UUFDRCxVQUFVO0tBQ1gsQ0FBQTtJQUVELHlCQUF5QjtJQUN6QixLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUMzQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQy9DLENBQUE7SUFFRCxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNwQix5QkFBeUIsYUFBYSxLQUFLLFdBQVcsaUJBQWlCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FDM0YsQ0FBQTtJQUVELE9BQU8sS0FBSyxDQUFDLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUNuQztRQUNFLFlBQVksRUFBRSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsWUFBWTtRQUNqRCxlQUFlLEVBQUUsS0FBSyxDQUFDLGdCQUFnQixDQUFDLGVBQWU7UUFDdkQsT0FBTyxFQUFFLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPO0tBQ3hDLEVBQ0Q7UUFDRSxNQUFNLEVBQUUsR0FBRztRQUNYLE9BQU8sRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ3pCLDZCQUE2QixFQUFFLFdBQVc7U0FDM0MsQ0FBQztLQUNILENBQ0YsQ0FBQTtBQUNILENBQUMsQ0FBQyxDQUFBO0FBRUo7OztHQUdHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUMvQixLQUFzQixFQUN0QixhQUFxQixFQUNyQixFQUFFLENBQ0YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7SUFDbEIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsaUJBQWlCLENBQUMsaUJBQWlCLENBQUE7SUFFMUQsMENBQTBDO0lBQzFDLE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FDbkMsT0FBTyxDQUFDLE9BQU8sRUFDZiw2QkFBNkIsQ0FDOUIsQ0FBQTtJQUNELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUE7SUFFakUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pCLE9BQU8sa0JBQWtCLENBQUMsS0FBSyxDQUFDO1lBQzlCLE1BQU0sRUFBRSxHQUFHO1lBQ1gsT0FBTyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUM7Z0JBQ3pCLGNBQWMsRUFBRSxrQkFBa0I7YUFDbkMsQ0FBQztTQUNILENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRCxxQkFBcUI7SUFDckIsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDbkQsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFFM0QsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7UUFDbEMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsV0FBVyxFQUFFLENBQUMsQ0FBQTtRQUM3RCxPQUFPLGtCQUFrQixDQUFDLEtBQUssQ0FBQztZQUM5QixNQUFNLEVBQUUsR0FBRztZQUNYLE9BQU8sRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDO2dCQUN6QixjQUFjLEVBQUUsa0JBQWtCO2FBQ25DLENBQUM7U0FDSCxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQsTUFBTSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFBO0lBRXRELEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsYUFBYSxTQUFTLENBQUMsSUFBSSx5QkFBeUIsQ0FBQyxDQUFBO0lBRTVFLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtJQUU1Qix1Q0FBdUM7SUFDdkMsSUFBSSxLQUFLLEdBQTBCLElBQUksQ0FBQTtJQUV2QyxPQUFPLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUN0QixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLEdBQUcsYUFBYSxFQUFFLENBQUM7WUFDM0MsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FDcEIsOERBQThELENBQy9ELENBQUE7WUFDRCxPQUFPLGtCQUFrQixDQUFDLEtBQUssQ0FBQztnQkFDOUIsTUFBTSxFQUFFLEdBQUc7Z0JBQ1gsT0FBTyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUM7b0JBQ3pCLGNBQWMsRUFBRSxrQkFBa0I7aUJBQ25DLENBQUM7YUFDSCxDQUFDLENBQUE7UUFDSixDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUU1QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUMxQixLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQTtRQUN0QixDQUFDO2FBQU0sQ0FBQztZQUNOLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDbkMsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNwQixhQUFhLEtBQUssQ0FBQyxTQUFTLHVCQUF1QixTQUFTLENBQUMsSUFBSSxFQUFFLENBQ3BFLENBQUE7SUFFRCxPQUFPLEtBQUssQ0FBQyxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUU7UUFDM0MsTUFBTSxFQUFFLEdBQUc7UUFDWCxPQUFPLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUN6QixtQ0FBbUMsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFO1NBQ3pELENBQUM7S0FDSCxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQTtBQUVKOzs7R0FHRztBQUNILE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxLQUFzQixFQUFFLEVBQUUsQ0FDMUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7SUFDbEIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsaUJBQWlCLENBQUMsaUJBQWlCLENBQUE7SUFFMUQsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUNuQyxPQUFPLENBQUMsT0FBTyxFQUNmLDZCQUE2QixDQUM5QixDQUFBO0lBQ0QsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUV4RSxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUMzQyxPQUFPLENBQUMsSUFHUCxFQUNELEdBQWtELEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUMxRCxDQUFBO0lBRUQsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FDcEIsYUFBYSxXQUFXLGdCQUFnQixTQUFTLENBQUMsWUFBWSxJQUFJLFNBQVMsRUFBRSxDQUM5RSxDQUFBO0lBRUQsOENBQThDO0lBQzlDLE1BQU0sU0FBUyxHQUFvQjtRQUNqQyxTQUFTLEVBQUUsU0FBUyxDQUFDLFNBQVMsSUFBSSxxQkFBcUI7UUFDdkQsWUFBWSxFQUFFLFNBQVMsQ0FBQyxZQUFZLElBQUksaUNBQWlDO0tBQzFFLENBQUE7SUFDRCxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDLENBQUE7SUFFbEQsT0FBTyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQTtBQUNsRCxDQUFDLENBQUMsQ0FBQTtBQUVKOzs7R0FHRztBQUNILE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxFQUFFLENBQ3BDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ2xCLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFBO0lBRTFELE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FDbkMsT0FBTyxDQUFDLE9BQU8sRUFDZiw2QkFBNkIsQ0FDOUIsQ0FBQTtJQUNELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFeEUsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FDM0MsT0FBTyxDQUFDLElBR1AsRUFDRCxHQUFrRCxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FDMUQsQ0FBQTtJQUVELEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQ3BCLGFBQWEsV0FBVyxnQkFBZ0IsU0FBUyxDQUFDLFlBQVksSUFBSSxTQUFTLEVBQUUsQ0FDOUUsQ0FBQTtJQUVELGlEQUFpRDtJQUNqRCxPQUFPLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBQ2xELENBQUMsQ0FBQyxDQUFBO0FBRUosK0VBQStFO0FBQy9FLFNBQVM7QUFDVCwrRUFBK0U7QUFFL0U7O0dBRUc7QUFDSCxNQUFNLG9CQUFvQixHQUFHLENBQUMsS0FBc0IsRUFBRSxhQUFxQixFQUFFLEVBQUUsQ0FDN0UsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJO0FBQ25CLDJCQUEyQjtBQUMzQixVQUFVLENBQUMsR0FBRyxDQUNaLHFDQUFxQyxFQUNyQyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQzNDLEVBQ0QsVUFBVSxDQUFDLElBQUksQ0FDYixvREFBb0QsRUFDcEQsd0JBQXdCLENBQUMsS0FBSyxDQUFDLENBQ2hDLEVBQ0QsVUFBVSxDQUFDLElBQUksQ0FDYixpREFBaUQsRUFDakQscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQzdCLEVBQ0QsVUFBVSxDQUFDLElBQUksQ0FBQyxnQ0FBZ0MsRUFBRSxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDekUsOEJBQThCO0FBQzlCLFVBQVUsQ0FBQyxJQUFJLENBQ2IsZ0NBQWdDLEVBQ2hDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUMvQixFQUNELFVBQVUsQ0FBQyxHQUFHLENBQ1osa0NBQWtDLEVBQ2xDLHdCQUF3QixDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FDL0MsRUFDRCxVQUFVLENBQUMsSUFBSSxDQUNiLGtDQUFrQyxFQUNsQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUMsQ0FDaEMsRUFDRCxVQUFVLENBQUMsSUFBSSxDQUNiLGtDQUFrQyxFQUNsQyx3QkFBd0IsRUFBRSxDQUMzQixDQUNGLENBQUE7QUFZSCxNQUFNLHlCQUF5QixHQUFxQjtJQUNsRCxZQUFZLEVBQUUsZ0JBQWdCO0lBQzlCLGVBQWUsRUFBRSxTQUFTO0lBQzFCLE9BQU8sRUFBRSxlQUFlO0NBQ3pCLENBQUE7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsQ0FDbkMsVUFBbUMsRUFBRSxFQUNnQixFQUFFLENBQ3ZELE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ2xCLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxhQUFhLElBQUksdUJBQXVCLENBQUE7SUFDdEUsTUFBTSxnQkFBZ0IsR0FDcEIsT0FBTyxDQUFDLGdCQUFnQixJQUFJLHlCQUF5QixDQUFBO0lBRXZELHdDQUF3QztJQUN4QyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO0lBRTFELCtCQUErQjtJQUMvQixNQUFNLE1BQU0sR0FBRyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUE7SUFFekQsaURBQWlEO0lBQ2pELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUM7UUFDdkMsSUFBSSxFQUFFLENBQUM7UUFDUCxRQUFRLEVBQUUsU0FBUztRQUNuQixXQUFXLEVBQUUsR0FBRyxFQUFFLHFEQUFxRDtLQUN4RSxDQUFDLENBQUE7SUFFRiwyQkFBMkI7SUFDM0IsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUUzQiwrQkFBK0I7SUFDL0IsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQTtJQUM5QixJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7UUFDbEMsaURBQWlEO1FBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtJQUN6QyxDQUFDO0lBRUQsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FDcEIsdUNBQXVDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FDdEQsQ0FBQTtJQUVELE9BQU87UUFDTCxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDbEIsS0FBSztLQUNxQixDQUFBO0FBQzlCLENBQUMsQ0FBQyxDQUFBO0FBRUo7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsQ0FDN0IsS0FBc0IsRUFDdEIsVUFBNEIsRUFDUCxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFLFVBQVUsQ0FBQyxDQUFBO0FBRXhFOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBQzdCLEtBQXNCLEVBQ3lDLEVBQUUsQ0FDakUsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUE7QUFFakM7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FDcEMsS0FBc0IsRUFDdEIsVUFBNEIsRUFDUCxFQUFFLENBQ3ZCLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ2xCLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBRW5ELE1BQU0sV0FBVyxHQUFtQjtRQUNsQyxTQUFTLEVBQUUsUUFBUTtRQUNuQixVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7UUFDakMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxTQUFTO1FBQy9CLGtCQUFrQixFQUFFLFVBQVUsQ0FBQyxrQkFBa0I7S0FDbEQsQ0FBQTtJQUVELDZEQUE2RDtJQUM3RCxLQUFLLE1BQU0sQ0FBQyxFQUFFLFFBQVEsQ0FBQyxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBQ3RDLElBQUksUUFBUSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDakQsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFBO1lBQ3BELEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQ3BCLGtDQUFrQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUM1RCxDQUFBO1FBQ0gsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQTtBQUVKOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLENBQ3RDLEtBQXNCLEVBQ3RCLFNBQTZDLFVBQVUsRUFDbEMsRUFBRSxDQUN2QixNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztJQUNsQixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUVuRCxNQUFNLGFBQWEsR0FBbUI7UUFDcEMsU0FBUyxFQUFFLFVBQVU7UUFDckIsY0FBYyxFQUFFLE1BQU07UUFDdEIsVUFBVSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQUUsaUNBQWlDO0tBQ2pFLENBQUE7SUFFRCwrREFBK0Q7SUFDL0QsS0FBSyxNQUFNLENBQUMsRUFBRSxRQUFRLENBQUMsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUN0QyxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ25ELEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxhQUFhLENBQUMsQ0FBQTtZQUN0RCxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNwQixvQ0FBb0MsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FDOUQsQ0FBQTtRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExhbWJkYSBSdW50aW1lIEFQSSBIVFRQIHNlcnZlciB1c2luZyBFZmZlY3QgSHR0cFNlcnZlci5cbiAqXG4gKiBUaGlzIHNlcnZlciBlbXVsYXRlcyB0aGUgQVdTIExhbWJkYSBSdW50aW1lIEFQSSB0aGF0IERvY2tlciBjb250YWluZXJzXG4gKiB1c2UgdG8gcmVjZWl2ZSBpbnZvY2F0aW9ucyBhbmQgc2VuZCByZXNwb25zZXMuXG4gKlxuICogRWFjaCBMYW1iZGEgZnVuY3Rpb24gZ2V0cyBpdHMgb3duIHNlcnZlciBvbiBhbiBlcGhlbWVyYWwgcG9ydC4gVGhlIHNlcnZlclxuICogbWFpbnRhaW5zIGEgcXVldWUgb2YgcGVuZGluZyBpbnZvY2F0aW9ucy4gV2hlbiBhIGNvbnRhaW5lciBwb2xsc1xuICogL2ludm9jYXRpb24vbmV4dCwgaXQgYmxvY2tzIHVudGlsIGFuIGludm9jYXRpb24gaXMgYXZhaWxhYmxlLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xhbWJkYS9sYXRlc3QvZGcvcnVudGltZXMtYXBpLmh0bWxcbiAqL1xuXG5pbXBvcnQgKiBhcyBIZWFkZXJzIGZyb20gXCJAZWZmZWN0L3BsYXRmb3JtL0hlYWRlcnNcIlxuaW1wb3J0ICogYXMgSHR0cFJvdXRlciBmcm9tIFwiQGVmZmVjdC9wbGF0Zm9ybS9IdHRwUm91dGVyXCJcbmltcG9ydCAqIGFzIEh0dHBTZXJ2ZXJSZXF1ZXN0IGZyb20gXCJAZWZmZWN0L3BsYXRmb3JtL0h0dHBTZXJ2ZXJSZXF1ZXN0XCJcbmltcG9ydCAqIGFzIEh0dHBTZXJ2ZXJSZXNwb25zZSBmcm9tIFwiQGVmZmVjdC9wbGF0Zm9ybS9IdHRwU2VydmVyUmVzcG9uc2VcIlxuaW1wb3J0ICogYXMgQnVuSHR0cFNlcnZlciBmcm9tIFwiQGVmZmVjdC9wbGF0Zm9ybS1idW4vQnVuSHR0cFNlcnZlclwiXG5pbXBvcnQgeyBFZmZlY3QsIEhhc2hNYXAsIE9wdGlvbiwgUXVldWUsIFJlZiwgdHlwZSBTY29wZSB9IGZyb20gXCJlZmZlY3RcIlxuaW1wb3J0IHR5cGUge1xuICBFeHRlbnNpb25FdmVudCxcbiAgRXh0ZW5zaW9uRXZlbnRUeXBlLFxuICBMYW1iZGFFcnJvcixcbiAgTGFtYmRhSW5pdEVycm9yLFxuICBMYW1iZGFJbnZvY2F0aW9uLFxuICBMYW1iZGFSZXNwb25zZSxcbiAgUmVnaXN0ZXJlZEV4dGVuc2lvbixcbn0gZnJvbSBcIi4vdHlwZXMuanNcIlxuXG4vKipcbiAqIFN0YXRlIGZvciBhIHJlZ2lzdGVyZWQgZXh0ZW5zaW9uLlxuICovXG5pbnRlcmZhY2UgRXh0ZW5zaW9uU3RhdGUge1xuICAvKiogRXh0ZW5zaW9uIGluZm8gKi9cbiAgZXh0ZW5zaW9uOiBSZWdpc3RlcmVkRXh0ZW5zaW9uXG4gIC8qKiBRdWV1ZSBvZiBldmVudHMgZm9yIHRoaXMgZXh0ZW5zaW9uICovXG4gIGV2ZW50UXVldWU6IFF1ZXVlLlF1ZXVlPEV4dGVuc2lvbkV2ZW50PlxufVxuXG4vKipcbiAqIEZ1bmN0aW9uIG1ldGFkYXRhIGZvciBleHRlbnNpb24gcmVnaXN0cmF0aW9uIHJlc3BvbnNlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBGdW5jdGlvbk1ldGFkYXRhIHtcbiAgZnVuY3Rpb25OYW1lOiBzdHJpbmdcbiAgZnVuY3Rpb25WZXJzaW9uOiBzdHJpbmdcbiAgaGFuZGxlcjogc3RyaW5nXG59XG5cbi8qKlxuICogU3RhdGUgZm9yIGEgUnVudGltZSBBUEkgc2VydmVyIHNlc3Npb24uXG4gKiBTdXBwb3J0cyBtdWx0aXBsZSBpbnZvY2F0aW9ucyB3aXRoIGEgcXVldWUtYmFzZWQgbW9kZWwuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnVudGltZUFwaVN0YXRlIHtcbiAgLyoqIFF1ZXVlIG9mIHBlbmRpbmcgaW52b2NhdGlvbnMgd2FpdGluZyB0byBiZSBmZXRjaGVkIGJ5IHRoZSBjb250YWluZXIgKi9cbiAgaW52b2NhdGlvblF1ZXVlOiBRdWV1ZS5RdWV1ZTxMYW1iZGFJbnZvY2F0aW9uPlxuICAvKiogUXVldWUgZm9yIHJlc3BvbnNlcy9lcnJvcnMgZnJvbSB0aGUgY29udGFpbmVyICovXG4gIHJlc3BvbnNlUXVldWU6IFF1ZXVlLlF1ZXVlPExhbWJkYVJlc3BvbnNlIHwgTGFtYmRhRXJyb3IgfCBMYW1iZGFJbml0RXJyb3I+XG4gIC8qKiBSZWdpc3RlcmVkIGV4dGVuc2lvbnMgYnkgZXh0ZW5zaW9uIElEICovXG4gIGV4dGVuc2lvbnM6IFJlZi5SZWY8SGFzaE1hcC5IYXNoTWFwPHN0cmluZywgRXh0ZW5zaW9uU3RhdGU+PlxuICAvKiogRnVuY3Rpb24gbWV0YWRhdGEgZm9yIGV4dGVuc2lvbiByZWdpc3RyYXRpb24gKi9cbiAgZnVuY3Rpb25NZXRhZGF0YTogRnVuY3Rpb25NZXRhZGF0YVxufVxuXG4vKipcbiAqIFJlc3VsdCBmcm9tIHN0YXJ0aW5nIGEgUnVudGltZSBBUEkgc2VydmVyLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJ1bnRpbWVBcGlTZXJ2ZXIge1xuICAvKiogVGhlIGFjdHVhbCBwb3J0IHRoZSBzZXJ2ZXIgaXMgbGlzdGVuaW5nIG9uICovXG4gIHBvcnQ6IG51bWJlclxuICAvKiogVGhlIHN0YXRlIGNvbnRhaW5pbmcgdGhlIGludm9jYXRpb24gYW5kIHJlc3BvbnNlIHF1ZXVlcyAqL1xuICBzdGF0ZTogUnVudGltZUFwaVN0YXRlXG59XG5cbi8qKlxuICogQ3JlYXRlIGEgbmV3IFJ1bnRpbWUgQVBJIHN0YXRlIChxdWV1ZXMgb25seSwgbm8gcG9ydCkuXG4gKlxuICogQHBhcmFtIGZ1bmN0aW9uTWV0YWRhdGEgLSBGdW5jdGlvbiBtZXRhZGF0YSBmb3IgZXh0ZW5zaW9uIHJlZ2lzdHJhdGlvbiByZXNwb25zZXNcbiAqL1xuZXhwb3J0IGNvbnN0IG1ha2VSdW50aW1lQXBpU3RhdGUgPSAoZnVuY3Rpb25NZXRhZGF0YTogRnVuY3Rpb25NZXRhZGF0YSkgPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IGludm9jYXRpb25RdWV1ZSA9IHlpZWxkKiBRdWV1ZS51bmJvdW5kZWQ8TGFtYmRhSW52b2NhdGlvbj4oKVxuICAgIGNvbnN0IHJlc3BvbnNlUXVldWUgPSB5aWVsZCogUXVldWUudW5ib3VuZGVkPFxuICAgICAgTGFtYmRhUmVzcG9uc2UgfCBMYW1iZGFFcnJvciB8IExhbWJkYUluaXRFcnJvclxuICAgID4oKVxuICAgIGNvbnN0IGV4dGVuc2lvbnMgPSB5aWVsZCogUmVmLm1ha2UoSGFzaE1hcC5lbXB0eTxzdHJpbmcsIEV4dGVuc2lvblN0YXRlPigpKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGludm9jYXRpb25RdWV1ZSxcbiAgICAgIHJlc3BvbnNlUXVldWUsXG4gICAgICBleHRlbnNpb25zLFxuICAgICAgZnVuY3Rpb25NZXRhZGF0YSxcbiAgICB9IHNhdGlzZmllcyBSdW50aW1lQXBpU3RhdGVcbiAgfSlcblxuLyoqXG4gKiBEZWZhdWx0IHBvbGwgdGltZW91dCAtIHVzZWQgd2hlbiBub3Qgb3ZlcnJpZGRlbi5cbiAqXG4gKiAjIyBXaHkgY29udGFpbmVycyBjYW4ndCBzdGF5IHdhcm0gaW5kZWZpbml0ZWx5IChsaWtlIEFXUyBMYW1iZGEgZG9lcylcbiAqXG4gKiBBV1MgTGFtYmRhIGtlZXBzIGNvbnRhaW5lcnMgd2FybSBmb3IgfjUtMTUgbWludXRlcyBiZXR3ZWVuIGludm9jYXRpb25zLlxuICogVGhlaXIgUnVudGltZSBBUEkgaW1wbGVtZW50YXRpb24gY2FuIGhvbGQgSFRUUCBjb25uZWN0aW9ucyBvcGVuIGluZGVmaW5pdGVseVxuICogYmVjYXVzZSB0aGV5IGNvbnRyb2wgdGhlIGVudGlyZSBpbmZyYXN0cnVjdHVyZSBlbmQtdG8tZW5kLlxuICpcbiAqIEluIGxvY2FsIGRldmVsb3BtZW50LCB3ZSdyZSBjb25zdHJhaW5lZCBieSBIVFRQIHNlcnZlciBsaW1pdGF0aW9uczpcbiAqIC0gQnVuJ3MgbWF4aW11bSBgaWRsZVRpbWVvdXRgIGlzIDI1NSBzZWNvbmRzICh+NC4yNSBtaW51dGVzKVxuICogLSBUaGlzIGlzIGEgcHJhY3RpY2FsIGxpbWl0IHRvIHByZXZlbnQgcmVzb3VyY2UgZXhoYXVzdGlvbiBpbiBIVFRQIHNlcnZlcnNcbiAqIC0gV2hlbiB0aGUgdGltZW91dCBleHBpcmVzLCBCdW4gZm9yY2VmdWxseSBjbG9zZXMgdGhlIGNvbm5lY3Rpb25cbiAqIC0gVGhlIExhbWJkYSBSSUMgaW50ZXJwcmV0cyB0aGlzIGFzIGEgZmF0YWwgXCJObyBSZXNwb25zZSBmcm9tIGVuZHBvaW50XCIgZXJyb3JcbiAqXG4gKiBPdXIgc29sdXRpb246IHRpbWVvdXQgc2xpZ2h0bHkgYmVmb3JlIEJ1biBkb2VzICgyNDBzIHZzIDI1NXMpIGFuZCByZXR1cm5cbiAqIEhUVFAgNTAzLCB3aGljaCBjYXVzZXMgdGhlIFJJQyB0byBleGl0IGdyYWNlZnVsbHkuIFRoZSBjb250YWluZXIgd2lsbCBiZVxuICogYXV0b21hdGljYWxseSByZXN0YXJ0ZWQgb24gdGhlIG5leHQgaW52b2NhdGlvbiAofjIgc2Vjb25kcyBmb3Igd2FybSBpbWFnZXMpLlxuICpcbiAqIFRoaXMgaXMgYW4gaW5oZXJlbnQgbGltaXRhdGlvbiBvZiBsb2NhbCBMYW1iZGEgZW11bGF0aW9uIC0gQVdTJ3MgcHVycG9zZS1idWlsdFxuICogaW5mcmFzdHJ1Y3R1cmUgc2ltcGx5IGRvZXNuJ3QgaGF2ZSB0aGUgc2FtZSB0aW1lb3V0IGNvbnN0cmFpbnRzLlxuICovXG5jb25zdCBERUZBVUxUX1BPTExfVElNRU9VVF9NUyA9IDI0MF8wMDAgLy8gNCBtaW51dGVzXG5cbi8qKlxuICogSGFuZGxlIEdFVCAvMjAxOC0wNi0wMS9ydW50aW1lL2ludm9jYXRpb24vbmV4dFxuICogUG9sbHMgZm9yIGFuIGludm9jYXRpb24gd2l0aCBhIGJvdW5kZWQgdGltZW91dCB0byBoYW5kbGUgaWRsZSBjb250YWluZXJzIGdyYWNlZnVsbHkuXG4gKiBUaGlzIGVuc3VyZXMgdGhhdCBpZiBubyBpbnZvY2F0aW9ucyBhcnJpdmUgd2l0aGluIHRoZSB0aW1lb3V0LCB0aGUgY29udGFpbmVyXG4gKiBleGl0cyBjbGVhbmx5IHJhdGhlciB0aGFuIGJlaW5nIGtpbGxlZCBieSBhbiBIVFRQIHRpbWVvdXQuXG4gKlxuICogV2hlbiB0aGUgdGltZW91dCBleHBpcmVzLCB3ZSByZXR1cm4gYSA1MDMgU2VydmljZSBVbmF2YWlsYWJsZSB3aGljaCBzaWduYWxzXG4gKiB0byB0aGUgTGFtYmRhIFJJQyB0aGF0IGl0IHNob3VsZCBleGl0LiBUaGUgY29udGFpbmVyIHdpbGwgYmUgcmVzdGFydGVkXG4gKiBhdXRvbWF0aWNhbGx5IHdoZW4gdGhlIG5leHQgaW52b2NhdGlvbiBhcnJpdmVzLlxuICovXG5jb25zdCBoYW5kbGVJbnZvY2F0aW9uTmV4dCA9IChzdGF0ZTogUnVudGltZUFwaVN0YXRlLCBwb2xsVGltZW91dE1zOiBudW1iZXIpID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKFwiQ29udGFpbmVyIHBvbGxpbmcgZm9yIG5leHQgaW52b2NhdGlvblwiKVxuXG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKVxuXG4gICAgLy8gUG9sbCB3aXRoIHRpbWVvdXQgaW5zdGVhZCBvZiBibG9ja2luZyBpbmRlZmluaXRlbHlcbiAgICAvLyBUaGlzIGFsbG93cyB1cyB0byBkZXRlY3QgY29ubmVjdGlvbiBpc3N1ZXMgYW5kIGtlZXAgdGhlIGludm9jYXRpb24gaW4gdGhlIHF1ZXVlXG4gICAgbGV0IGludm9jYXRpb246IExhbWJkYUludm9jYXRpb24gfCBudWxsID0gbnVsbFxuXG4gICAgd2hpbGUgKGludm9jYXRpb24gPT09IG51bGwpIHtcbiAgICAgIC8vIENoZWNrIGlmIHdlJ3ZlIGV4Y2VlZGVkIHRoZSB0aW1lb3V0XG4gICAgICBpZiAoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSA+IHBvbGxUaW1lb3V0TXMpIHtcbiAgICAgICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhcbiAgICAgICAgICBcIkludm9jYXRpb24gcG9sbCB0aW1lb3V0IC0gcmV0dXJuaW5nIDUwMyB0byB0cmlnZ2VyIGNvbnRhaW5lciBleGl0XCIsXG4gICAgICAgIClcbiAgICAgICAgLy8gUmV0dXJuIDUwMyBTZXJ2aWNlIFVuYXZhaWxhYmxlIHRvIHNpZ25hbCB0aGUgUklDIHRvIGV4aXQgZ3JhY2VmdWxseVxuICAgICAgICAvLyBUaGlzIGlzIGV4cGVjdGVkIGJlaGF2aW9yIGZvciBpZGxlIGNvbnRhaW5lcnMgaW4gbG9jYWwgZGV2ZWxvcG1lbnRcbiAgICAgICAgcmV0dXJuIEh0dHBTZXJ2ZXJSZXNwb25zZS5lbXB0eSh7XG4gICAgICAgICAgc3RhdHVzOiA1MDMsXG4gICAgICAgICAgaGVhZGVyczogSGVhZGVycy5mcm9tSW5wdXQoe1xuICAgICAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgfSksXG4gICAgICAgIH0pXG4gICAgICB9XG5cbiAgICAgIC8vIFRyeSB0byB0YWtlIGZyb20gcXVldWUgd2l0aCBhIHNob3J0IHRpbWVvdXRcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHlpZWxkKiBRdWV1ZS5wb2xsKHN0YXRlLmludm9jYXRpb25RdWV1ZSlcblxuICAgICAgaWYgKE9wdGlvbi5pc1NvbWUocmVzdWx0KSkge1xuICAgICAgICBpbnZvY2F0aW9uID0gcmVzdWx0LnZhbHVlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBRdWV1ZSBpcyBlbXB0eSwgd2FpdCBhIGJpdCBiZWZvcmUgcmV0cnlpbmdcbiAgICAgICAgeWllbGQqIEVmZmVjdC5zbGVlcChcIjEwMCBtaWxsaXNcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKFxuICAgICAgYFJldHVybmluZyBpbnZvY2F0aW9uICR7aW52b2NhdGlvbi5yZXF1ZXN0SWR9IHRvIGNvbnRhaW5lcmAsXG4gICAgKVxuXG4gICAgcmV0dXJuIHlpZWxkKiBIdHRwU2VydmVyUmVzcG9uc2UuanNvbihpbnZvY2F0aW9uLmV2ZW50LCB7XG4gICAgICBzdGF0dXM6IDIwMCxcbiAgICAgIGhlYWRlcnM6IEhlYWRlcnMuZnJvbUlucHV0KHtcbiAgICAgICAgXCJMYW1iZGEtUnVudGltZS1Bd3MtUmVxdWVzdC1JZFwiOiBpbnZvY2F0aW9uLnJlcXVlc3RJZCxcbiAgICAgICAgXCJMYW1iZGEtUnVudGltZS1EZWFkbGluZS1Nc1wiOiBTdHJpbmcoaW52b2NhdGlvbi5kZWFkbGluZU1zKSxcbiAgICAgICAgXCJMYW1iZGEtUnVudGltZS1JbnZva2VkLUZ1bmN0aW9uLUFyblwiOiBpbnZvY2F0aW9uLmludm9rZWRGdW5jdGlvbkFybixcbiAgICAgICAgXCJMYW1iZGEtUnVudGltZS1Mb2ctR3JvdXAtTmFtZVwiOiBpbnZvY2F0aW9uLmxvZ0dyb3VwTmFtZSxcbiAgICAgICAgXCJMYW1iZGEtUnVudGltZS1Mb2ctU3RyZWFtLU5hbWVcIjogaW52b2NhdGlvbi5sb2dTdHJlYW1OYW1lLFxuICAgICAgfSksXG4gICAgfSlcbiAgfSlcblxuLyoqXG4gKiBIYW5kbGUgUE9TVCAvMjAxOC0wNi0wMS9ydW50aW1lL2ludm9jYXRpb24vOnJlcXVlc3RJZC9yZXNwb25zZVxuICovXG5jb25zdCBoYW5kbGVJbnZvY2F0aW9uUmVzcG9uc2UgPSAoc3RhdGU6IFJ1bnRpbWVBcGlTdGF0ZSkgPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHlpZWxkKiBIdHRwUm91dGVyLnBhcmFtc1xuICAgIGNvbnN0IHJlcXVlc3RJZCA9IHBhcmFtcy5yZXF1ZXN0SWQgPz8gXCJcIlxuICAgIGNvbnN0IHJlcXVlc3QgPSB5aWVsZCogSHR0cFNlcnZlclJlcXVlc3QuSHR0cFNlcnZlclJlcXVlc3RcblxuICAgIC8vIEJvZHkgbWlnaHQgbm90IGJlIEpTT04sIHNvIGdyYWNlZnVsbHkgaGFuZGxlIHBhcnNlIGVycm9yc1xuICAgIGNvbnN0IGJvZHkgPSB5aWVsZCogRWZmZWN0Lm9yRWxzZVN1Y2NlZWQocmVxdWVzdC5qc29uLCAoKSA9PiBudWxsKVxuXG4gICAgY29uc3QgcmVzcG9uc2U6IExhbWJkYVJlc3BvbnNlID0ge1xuICAgICAgcmVxdWVzdElkLFxuICAgICAgYm9keSxcbiAgICB9XG5cbiAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKGBSZWNlaXZlZCByZXNwb25zZSBmb3IgJHtyZXF1ZXN0SWR9YClcbiAgICB5aWVsZCogUXVldWUub2ZmZXIoc3RhdGUucmVzcG9uc2VRdWV1ZSwgcmVzcG9uc2UpXG5cbiAgICByZXR1cm4gSHR0cFNlcnZlclJlc3BvbnNlLmVtcHR5KHsgc3RhdHVzOiAyMDIgfSlcbiAgfSlcblxuLyoqXG4gKiBIYW5kbGUgUE9TVCAvMjAxOC0wNi0wMS9ydW50aW1lL2ludm9jYXRpb24vOnJlcXVlc3RJZC9lcnJvclxuICovXG5jb25zdCBoYW5kbGVJbnZvY2F0aW9uRXJyb3IgPSAoc3RhdGU6IFJ1bnRpbWVBcGlTdGF0ZSkgPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHlpZWxkKiBIdHRwUm91dGVyLnBhcmFtc1xuICAgIGNvbnN0IHJlcXVlc3RJZCA9IHBhcmFtcy5yZXF1ZXN0SWQgPz8gXCJcIlxuICAgIGNvbnN0IHJlcXVlc3QgPSB5aWVsZCogSHR0cFNlcnZlclJlcXVlc3QuSHR0cFNlcnZlclJlcXVlc3RcblxuICAgIC8vIEJvZHkgbWlnaHQgbm90IGJlIEpTT04sIHNvIGdyYWNlZnVsbHkgaGFuZGxlIHBhcnNlIGVycm9yc1xuICAgIGNvbnN0IGVycm9yQm9keSA9IHlpZWxkKiBFZmZlY3Qub3JFbHNlU3VjY2VlZChcbiAgICAgIHJlcXVlc3QuanNvbiBhcyBFZmZlY3QuRWZmZWN0PFxuICAgICAgICB7IGVycm9yTWVzc2FnZT86IHN0cmluZzsgc3RhY2tUcmFjZT86IHN0cmluZ1tdIH0sXG4gICAgICAgIHVua25vd25cbiAgICAgID4sXG4gICAgICAoKTogeyBlcnJvck1lc3NhZ2U/OiBzdHJpbmc7IHN0YWNrVHJhY2U/OiBzdHJpbmdbXSB9ID0+ICh7fSksXG4gICAgKVxuXG4gICAgY29uc3QgZXJyb3JUeXBlSGVhZGVyID0gSGVhZGVycy5nZXQoXG4gICAgICByZXF1ZXN0LmhlYWRlcnMsXG4gICAgICBcImxhbWJkYS1ydW50aW1lLWZ1bmN0aW9uLWVycm9yLXR5cGVcIixcbiAgICApXG4gICAgY29uc3QgZXJyb3JUeXBlID0gT3B0aW9uLmdldE9yRWxzZShlcnJvclR5cGVIZWFkZXIsICgpID0+IFwiRXJyb3JcIilcblxuICAgIGNvbnN0IGVycm9yOiBMYW1iZGFFcnJvciA9IHtcbiAgICAgIHJlcXVlc3RJZCxcbiAgICAgIGVycm9yVHlwZTogU3RyaW5nKGVycm9yVHlwZSksXG4gICAgICBlcnJvck1lc3NhZ2U6IGVycm9yQm9keS5lcnJvck1lc3NhZ2UgPz8gXCJVbmtub3duIGVycm9yXCIsXG4gICAgICBzdGFja1RyYWNlOiBlcnJvckJvZHkuc3RhY2tUcmFjZSxcbiAgICB9XG5cbiAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKFxuICAgICAgYFJlY2VpdmVkIGVycm9yIGZvciAke3JlcXVlc3RJZH06ICR7ZXJyb3IuZXJyb3JNZXNzYWdlfWAsXG4gICAgKVxuICAgIHlpZWxkKiBRdWV1ZS5vZmZlcihzdGF0ZS5yZXNwb25zZVF1ZXVlLCBlcnJvcilcblxuICAgIHJldHVybiBIdHRwU2VydmVyUmVzcG9uc2UuZW1wdHkoeyBzdGF0dXM6IDIwMiB9KVxuICB9KVxuXG4vKipcbiAqIEhhbmRsZSBQT1NUIC8yMDE4LTA2LTAxL3J1bnRpbWUvaW5pdC9lcnJvclxuICovXG5jb25zdCBoYW5kbGVJbml0RXJyb3IgPSAoc3RhdGU6IFJ1bnRpbWVBcGlTdGF0ZSkgPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IHJlcXVlc3QgPSB5aWVsZCogSHR0cFNlcnZlclJlcXVlc3QuSHR0cFNlcnZlclJlcXVlc3RcblxuICAgIC8vIEJvZHkgbWlnaHQgbm90IGJlIEpTT04sIHNvIGdyYWNlZnVsbHkgaGFuZGxlIHBhcnNlIGVycm9yc1xuICAgIGNvbnN0IGVycm9yQm9keSA9IHlpZWxkKiBFZmZlY3Qub3JFbHNlU3VjY2VlZChcbiAgICAgIHJlcXVlc3QuanNvbiBhcyBFZmZlY3QuRWZmZWN0PFxuICAgICAgICB7IGVycm9yTWVzc2FnZT86IHN0cmluZzsgc3RhY2tUcmFjZT86IHN0cmluZ1tdIH0sXG4gICAgICAgIHVua25vd25cbiAgICAgID4sXG4gICAgICAoKTogeyBlcnJvck1lc3NhZ2U/OiBzdHJpbmc7IHN0YWNrVHJhY2U/OiBzdHJpbmdbXSB9ID0+ICh7fSksXG4gICAgKVxuXG4gICAgY29uc3QgZXJyb3JUeXBlSGVhZGVyID0gSGVhZGVycy5nZXQoXG4gICAgICByZXF1ZXN0LmhlYWRlcnMsXG4gICAgICBcImxhbWJkYS1ydW50aW1lLWZ1bmN0aW9uLWVycm9yLXR5cGVcIixcbiAgICApXG4gICAgY29uc3QgZXJyb3JUeXBlID0gT3B0aW9uLmdldE9yRWxzZShlcnJvclR5cGVIZWFkZXIsICgpID0+IFwiSW5pdEVycm9yXCIpXG5cbiAgICBjb25zdCBlcnJvcjogTGFtYmRhSW5pdEVycm9yID0ge1xuICAgICAgZXJyb3JUeXBlOiBTdHJpbmcoZXJyb3JUeXBlKSxcbiAgICAgIGVycm9yTWVzc2FnZTogZXJyb3JCb2R5LmVycm9yTWVzc2FnZSA/PyBcIlVua25vd24gaW5pdCBlcnJvclwiLFxuICAgICAgc3RhY2tUcmFjZTogZXJyb3JCb2R5LnN0YWNrVHJhY2UsXG4gICAgfVxuXG4gICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhgUmVjZWl2ZWQgaW5pdCBlcnJvcjogJHtlcnJvci5lcnJvck1lc3NhZ2V9YClcbiAgICB5aWVsZCogUXVldWUub2ZmZXIoc3RhdGUucmVzcG9uc2VRdWV1ZSwgZXJyb3IpXG5cbiAgICByZXR1cm4gSHR0cFNlcnZlclJlc3BvbnNlLmVtcHR5KHsgc3RhdHVzOiAyMDIgfSlcbiAgfSlcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRXh0ZW5zaW9ucyBBUEkgaGFuZGxlcnNcbi8vIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xhbWJkYS9sYXRlc3QvZGcvcnVudGltZXMtZXh0ZW5zaW9ucy1hcGkuaHRtbFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEhhbmRsZSBQT1NUIC8yMDIwLTAxLTAxL2V4dGVuc2lvbi9yZWdpc3RlclxuICogRXh0ZW5zaW9ucyBjYWxsIHRoaXMgdG8gcmVnaXN0ZXIgZm9yIGxpZmVjeWNsZSBldmVudHMuXG4gKi9cbmNvbnN0IGhhbmRsZUV4dGVuc2lvblJlZ2lzdGVyID0gKHN0YXRlOiBSdW50aW1lQXBpU3RhdGUpID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCByZXF1ZXN0ID0geWllbGQqIEh0dHBTZXJ2ZXJSZXF1ZXN0Lkh0dHBTZXJ2ZXJSZXF1ZXN0XG5cbiAgICAvLyBHZXQgZXh0ZW5zaW9uIG5hbWUgZnJvbSBoZWFkZXIgKHJlcXVpcmVkKVxuICAgIGNvbnN0IGV4dGVuc2lvbk5hbWVIZWFkZXIgPSBIZWFkZXJzLmdldChcbiAgICAgIHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIFwibGFtYmRhLWV4dGVuc2lvbi1uYW1lXCIsXG4gICAgKVxuICAgIGNvbnN0IGV4dGVuc2lvbk5hbWUgPSBPcHRpb24uZ2V0T3JFbHNlKFxuICAgICAgZXh0ZW5zaW9uTmFtZUhlYWRlcixcbiAgICAgICgpID0+IFwidW5rbm93bi1leHRlbnNpb25cIixcbiAgICApXG5cbiAgICAvLyBQYXJzZSByZXF1ZXN0IGJvZHkgZm9yIGV2ZW50cyB0byByZWdpc3RlciBmb3JcbiAgICBjb25zdCBib2R5ID0geWllbGQqIEVmZmVjdC5vckVsc2VTdWNjZWVkKFxuICAgICAgcmVxdWVzdC5qc29uIGFzIEVmZmVjdC5FZmZlY3Q8eyBldmVudHM/OiBFeHRlbnNpb25FdmVudFR5cGVbXSB9LCB1bmtub3duPixcbiAgICAgICgpOiB7IGV2ZW50cz86IEV4dGVuc2lvbkV2ZW50VHlwZVtdIH0gPT4gKHt9KSxcbiAgICApXG4gICAgY29uc3QgZXZlbnRzOiBFeHRlbnNpb25FdmVudFR5cGVbXSA9IGJvZHkuZXZlbnRzID8/IFtcIklOVk9LRVwiLCBcIlNIVVRET1dOXCJdXG5cbiAgICAvLyBHZW5lcmF0ZSB1bmlxdWUgZXh0ZW5zaW9uIElEXG4gICAgY29uc3QgZXh0ZW5zaW9uSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpXG5cbiAgICAvLyBDcmVhdGUgZXZlbnQgcXVldWUgZm9yIHRoaXMgZXh0ZW5zaW9uXG4gICAgY29uc3QgZXZlbnRRdWV1ZSA9IHlpZWxkKiBRdWV1ZS51bmJvdW5kZWQ8RXh0ZW5zaW9uRXZlbnQ+KClcblxuICAgIGNvbnN0IGV4dGVuc2lvblN0YXRlOiBFeHRlbnNpb25TdGF0ZSA9IHtcbiAgICAgIGV4dGVuc2lvbjoge1xuICAgICAgICBleHRlbnNpb25JZCxcbiAgICAgICAgbmFtZTogZXh0ZW5zaW9uTmFtZSxcbiAgICAgICAgZXZlbnRzLFxuICAgICAgfSxcbiAgICAgIGV2ZW50UXVldWUsXG4gICAgfVxuXG4gICAgLy8gUmVnaXN0ZXIgdGhlIGV4dGVuc2lvblxuICAgIHlpZWxkKiBSZWYudXBkYXRlKHN0YXRlLmV4dGVuc2lvbnMsIChleHRzKSA9PlxuICAgICAgSGFzaE1hcC5zZXQoZXh0cywgZXh0ZW5zaW9uSWQsIGV4dGVuc2lvblN0YXRlKSxcbiAgICApXG5cbiAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKFxuICAgICAgYEV4dGVuc2lvbiByZWdpc3RlcmVkOiAke2V4dGVuc2lvbk5hbWV9ICgke2V4dGVuc2lvbklkfSkgZm9yIGV2ZW50czogJHtldmVudHMuam9pbihcIiwgXCIpfWAsXG4gICAgKVxuXG4gICAgcmV0dXJuIHlpZWxkKiBIdHRwU2VydmVyUmVzcG9uc2UuanNvbihcbiAgICAgIHtcbiAgICAgICAgZnVuY3Rpb25OYW1lOiBzdGF0ZS5mdW5jdGlvbk1ldGFkYXRhLmZ1bmN0aW9uTmFtZSxcbiAgICAgICAgZnVuY3Rpb25WZXJzaW9uOiBzdGF0ZS5mdW5jdGlvbk1ldGFkYXRhLmZ1bmN0aW9uVmVyc2lvbixcbiAgICAgICAgaGFuZGxlcjogc3RhdGUuZnVuY3Rpb25NZXRhZGF0YS5oYW5kbGVyLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3RhdHVzOiAyMDAsXG4gICAgICAgIGhlYWRlcnM6IEhlYWRlcnMuZnJvbUlucHV0KHtcbiAgICAgICAgICBcIkxhbWJkYS1FeHRlbnNpb24tSWRlbnRpZmllclwiOiBleHRlbnNpb25JZCxcbiAgICAgICAgfSksXG4gICAgICB9LFxuICAgIClcbiAgfSlcblxuLyoqXG4gKiBIYW5kbGUgR0VUIC8yMDIwLTAxLTAxL2V4dGVuc2lvbi9ldmVudC9uZXh0XG4gKiBFeHRlbnNpb25zIGNhbGwgdGhpcyB0byBwb2xsIGZvciB0aGUgbmV4dCBsaWZlY3ljbGUgZXZlbnQuXG4gKi9cbmNvbnN0IGhhbmRsZUV4dGVuc2lvbkV2ZW50TmV4dCA9IChcbiAgc3RhdGU6IFJ1bnRpbWVBcGlTdGF0ZSxcbiAgcG9sbFRpbWVvdXRNczogbnVtYmVyLFxuKSA9PlxuICBFZmZlY3QuZ2VuKGZ1bmN0aW9uKiAoKSB7XG4gICAgY29uc3QgcmVxdWVzdCA9IHlpZWxkKiBIdHRwU2VydmVyUmVxdWVzdC5IdHRwU2VydmVyUmVxdWVzdFxuXG4gICAgLy8gR2V0IGV4dGVuc2lvbiBJRCBmcm9tIGhlYWRlciAocmVxdWlyZWQpXG4gICAgY29uc3QgZXh0ZW5zaW9uSWRIZWFkZXIgPSBIZWFkZXJzLmdldChcbiAgICAgIHJlcXVlc3QuaGVhZGVycyxcbiAgICAgIFwibGFtYmRhLWV4dGVuc2lvbi1pZGVudGlmaWVyXCIsXG4gICAgKVxuICAgIGNvbnN0IGV4dGVuc2lvbklkID0gT3B0aW9uLmdldE9yRWxzZShleHRlbnNpb25JZEhlYWRlciwgKCkgPT4gXCJcIilcblxuICAgIGlmICghZXh0ZW5zaW9uSWQpIHtcbiAgICAgIHJldHVybiBIdHRwU2VydmVyUmVzcG9uc2UuZW1wdHkoe1xuICAgICAgICBzdGF0dXM6IDQwMyxcbiAgICAgICAgaGVhZGVyczogSGVhZGVycy5mcm9tSW5wdXQoe1xuICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICB9KSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gRmluZCB0aGUgZXh0ZW5zaW9uXG4gICAgY29uc3QgZXh0ZW5zaW9ucyA9IHlpZWxkKiBSZWYuZ2V0KHN0YXRlLmV4dGVuc2lvbnMpXG4gICAgY29uc3QgZXh0ZW5zaW9uU3RhdGUgPSBIYXNoTWFwLmdldChleHRlbnNpb25zLCBleHRlbnNpb25JZClcblxuICAgIGlmIChPcHRpb24uaXNOb25lKGV4dGVuc2lvblN0YXRlKSkge1xuICAgICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhgRXh0ZW5zaW9uIG5vdCBmb3VuZDogJHtleHRlbnNpb25JZH1gKVxuICAgICAgcmV0dXJuIEh0dHBTZXJ2ZXJSZXNwb25zZS5lbXB0eSh7XG4gICAgICAgIHN0YXR1czogNDAzLFxuICAgICAgICBoZWFkZXJzOiBIZWFkZXJzLmZyb21JbnB1dCh7XG4gICAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIH0pLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBjb25zdCB7IGV2ZW50UXVldWUsIGV4dGVuc2lvbiB9ID0gZXh0ZW5zaW9uU3RhdGUudmFsdWVcblxuICAgIHlpZWxkKiBFZmZlY3QubG9nRGVidWcoYEV4dGVuc2lvbiAke2V4dGVuc2lvbi5uYW1lfSBwb2xsaW5nIGZvciBuZXh0IGV2ZW50YClcblxuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KClcblxuICAgIC8vIFBvbGwgZm9yIHRoZSBuZXh0IGV2ZW50IHdpdGggdGltZW91dFxuICAgIGxldCBldmVudDogRXh0ZW5zaW9uRXZlbnQgfCBudWxsID0gbnVsbFxuXG4gICAgd2hpbGUgKGV2ZW50ID09PSBudWxsKSB7XG4gICAgICBpZiAoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSA+IHBvbGxUaW1lb3V0TXMpIHtcbiAgICAgICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhcbiAgICAgICAgICBcIkV4dGVuc2lvbiBldmVudCBwb2xsIHRpbWVvdXQgLSByZXR1cm5pbmcgNTAzIHRvIHRyaWdnZXIgZXhpdFwiLFxuICAgICAgICApXG4gICAgICAgIHJldHVybiBIdHRwU2VydmVyUmVzcG9uc2UuZW1wdHkoe1xuICAgICAgICAgIHN0YXR1czogNTAzLFxuICAgICAgICAgIGhlYWRlcnM6IEhlYWRlcnMuZnJvbUlucHV0KHtcbiAgICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICAgIH0pLFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXN1bHQgPSB5aWVsZCogUXVldWUucG9sbChldmVudFF1ZXVlKVxuXG4gICAgICBpZiAoT3B0aW9uLmlzU29tZShyZXN1bHQpKSB7XG4gICAgICAgIGV2ZW50ID0gcmVzdWx0LnZhbHVlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB5aWVsZCogRWZmZWN0LnNsZWVwKFwiMTAwIG1pbGxpc1wiKVxuICAgICAgfVxuICAgIH1cblxuICAgIHlpZWxkKiBFZmZlY3QubG9nRGVidWcoXG4gICAgICBgUmV0dXJuaW5nICR7ZXZlbnQuZXZlbnRUeXBlfSBldmVudCB0byBleHRlbnNpb24gJHtleHRlbnNpb24ubmFtZX1gLFxuICAgIClcblxuICAgIHJldHVybiB5aWVsZCogSHR0cFNlcnZlclJlc3BvbnNlLmpzb24oZXZlbnQsIHtcbiAgICAgIHN0YXR1czogMjAwLFxuICAgICAgaGVhZGVyczogSGVhZGVycy5mcm9tSW5wdXQoe1xuICAgICAgICBcIkxhbWJkYS1FeHRlbnNpb24tRXZlbnQtSWRlbnRpZmllclwiOiBjcnlwdG8ucmFuZG9tVVVJRCgpLFxuICAgICAgfSksXG4gICAgfSlcbiAgfSlcblxuLyoqXG4gKiBIYW5kbGUgUE9TVCAvMjAyMC0wMS0wMS9leHRlbnNpb24vaW5pdC9lcnJvclxuICogRXh0ZW5zaW9ucyBjYWxsIHRoaXMgdG8gcmVwb3J0IGluaXRpYWxpemF0aW9uIGVycm9ycy5cbiAqL1xuY29uc3QgaGFuZGxlRXh0ZW5zaW9uSW5pdEVycm9yID0gKHN0YXRlOiBSdW50aW1lQXBpU3RhdGUpID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCByZXF1ZXN0ID0geWllbGQqIEh0dHBTZXJ2ZXJSZXF1ZXN0Lkh0dHBTZXJ2ZXJSZXF1ZXN0XG5cbiAgICBjb25zdCBleHRlbnNpb25JZEhlYWRlciA9IEhlYWRlcnMuZ2V0KFxuICAgICAgcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgXCJsYW1iZGEtZXh0ZW5zaW9uLWlkZW50aWZpZXJcIixcbiAgICApXG4gICAgY29uc3QgZXh0ZW5zaW9uSWQgPSBPcHRpb24uZ2V0T3JFbHNlKGV4dGVuc2lvbklkSGVhZGVyLCAoKSA9PiBcInVua25vd25cIilcblxuICAgIGNvbnN0IGVycm9yQm9keSA9IHlpZWxkKiBFZmZlY3Qub3JFbHNlU3VjY2VlZChcbiAgICAgIHJlcXVlc3QuanNvbiBhcyBFZmZlY3QuRWZmZWN0PFxuICAgICAgICB7IGVycm9yTWVzc2FnZT86IHN0cmluZzsgZXJyb3JUeXBlPzogc3RyaW5nIH0sXG4gICAgICAgIHVua25vd25cbiAgICAgID4sXG4gICAgICAoKTogeyBlcnJvck1lc3NhZ2U/OiBzdHJpbmc7IGVycm9yVHlwZT86IHN0cmluZyB9ID0+ICh7fSksXG4gICAgKVxuXG4gICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhcbiAgICAgIGBFeHRlbnNpb24gJHtleHRlbnNpb25JZH0gaW5pdCBlcnJvcjogJHtlcnJvckJvZHkuZXJyb3JNZXNzYWdlID8/IFwidW5rbm93blwifWAsXG4gICAgKVxuXG4gICAgLy8gUmVwb3J0IHRoZSBlcnJvciB0aHJvdWdoIHRoZSByZXNwb25zZSBxdWV1ZVxuICAgIGNvbnN0IGluaXRFcnJvcjogTGFtYmRhSW5pdEVycm9yID0ge1xuICAgICAgZXJyb3JUeXBlOiBlcnJvckJvZHkuZXJyb3JUeXBlID8/IFwiRXh0ZW5zaW9uLkluaXRFcnJvclwiLFxuICAgICAgZXJyb3JNZXNzYWdlOiBlcnJvckJvZHkuZXJyb3JNZXNzYWdlID8/IFwiRXh0ZW5zaW9uIGluaXRpYWxpemF0aW9uIGZhaWxlZFwiLFxuICAgIH1cbiAgICB5aWVsZCogUXVldWUub2ZmZXIoc3RhdGUucmVzcG9uc2VRdWV1ZSwgaW5pdEVycm9yKVxuXG4gICAgcmV0dXJuIEh0dHBTZXJ2ZXJSZXNwb25zZS5lbXB0eSh7IHN0YXR1czogMjAyIH0pXG4gIH0pXG5cbi8qKlxuICogSGFuZGxlIFBPU1QgLzIwMjAtMDEtMDEvZXh0ZW5zaW9uL2V4aXQvZXJyb3JcbiAqIEV4dGVuc2lvbnMgY2FsbCB0aGlzIHRvIHJlcG9ydCBlcnJvcnMgYmVmb3JlIGV4aXRpbmcuXG4gKi9cbmNvbnN0IGhhbmRsZUV4dGVuc2lvbkV4aXRFcnJvciA9ICgpID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCByZXF1ZXN0ID0geWllbGQqIEh0dHBTZXJ2ZXJSZXF1ZXN0Lkh0dHBTZXJ2ZXJSZXF1ZXN0XG5cbiAgICBjb25zdCBleHRlbnNpb25JZEhlYWRlciA9IEhlYWRlcnMuZ2V0KFxuICAgICAgcmVxdWVzdC5oZWFkZXJzLFxuICAgICAgXCJsYW1iZGEtZXh0ZW5zaW9uLWlkZW50aWZpZXJcIixcbiAgICApXG4gICAgY29uc3QgZXh0ZW5zaW9uSWQgPSBPcHRpb24uZ2V0T3JFbHNlKGV4dGVuc2lvbklkSGVhZGVyLCAoKSA9PiBcInVua25vd25cIilcblxuICAgIGNvbnN0IGVycm9yQm9keSA9IHlpZWxkKiBFZmZlY3Qub3JFbHNlU3VjY2VlZChcbiAgICAgIHJlcXVlc3QuanNvbiBhcyBFZmZlY3QuRWZmZWN0PFxuICAgICAgICB7IGVycm9yTWVzc2FnZT86IHN0cmluZzsgZXJyb3JUeXBlPzogc3RyaW5nIH0sXG4gICAgICAgIHVua25vd25cbiAgICAgID4sXG4gICAgICAoKTogeyBlcnJvck1lc3NhZ2U/OiBzdHJpbmc7IGVycm9yVHlwZT86IHN0cmluZyB9ID0+ICh7fSksXG4gICAgKVxuXG4gICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhcbiAgICAgIGBFeHRlbnNpb24gJHtleHRlbnNpb25JZH0gZXhpdCBlcnJvcjogJHtlcnJvckJvZHkuZXJyb3JNZXNzYWdlID8/IFwidW5rbm93blwifWAsXG4gICAgKVxuXG4gICAgLy8gSnVzdCBhY2tub3dsZWRnZSAtIGV4dGVuc2lvbiBpcyBleGl0aW5nIGFueXdheVxuICAgIHJldHVybiBIdHRwU2VydmVyUmVzcG9uc2UuZW1wdHkoeyBzdGF0dXM6IDIwMiB9KVxuICB9KVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBSb3V0ZXJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDcmVhdGUgdGhlIFJ1bnRpbWUgQVBJIHJvdXRlciBmb3IgYSBnaXZlbiBzdGF0ZS5cbiAqL1xuY29uc3QgbWFrZVJ1bnRpbWVBcGlSb3V0ZXIgPSAoc3RhdGU6IFJ1bnRpbWVBcGlTdGF0ZSwgcG9sbFRpbWVvdXRNczogbnVtYmVyKSA9PlxuICBIdHRwUm91dGVyLmVtcHR5LnBpcGUoXG4gICAgLy8gUnVudGltZSBBUEkgKDIwMTgtMDYtMDEpXG4gICAgSHR0cFJvdXRlci5nZXQoXG4gICAgICBcIi8yMDE4LTA2LTAxL3J1bnRpbWUvaW52b2NhdGlvbi9uZXh0XCIsXG4gICAgICBoYW5kbGVJbnZvY2F0aW9uTmV4dChzdGF0ZSwgcG9sbFRpbWVvdXRNcyksXG4gICAgKSxcbiAgICBIdHRwUm91dGVyLnBvc3QoXG4gICAgICBcIi8yMDE4LTA2LTAxL3J1bnRpbWUvaW52b2NhdGlvbi86cmVxdWVzdElkL3Jlc3BvbnNlXCIsXG4gICAgICBoYW5kbGVJbnZvY2F0aW9uUmVzcG9uc2Uoc3RhdGUpLFxuICAgICksXG4gICAgSHR0cFJvdXRlci5wb3N0KFxuICAgICAgXCIvMjAxOC0wNi0wMS9ydW50aW1lL2ludm9jYXRpb24vOnJlcXVlc3RJZC9lcnJvclwiLFxuICAgICAgaGFuZGxlSW52b2NhdGlvbkVycm9yKHN0YXRlKSxcbiAgICApLFxuICAgIEh0dHBSb3V0ZXIucG9zdChcIi8yMDE4LTA2LTAxL3J1bnRpbWUvaW5pdC9lcnJvclwiLCBoYW5kbGVJbml0RXJyb3Ioc3RhdGUpKSxcbiAgICAvLyBFeHRlbnNpb25zIEFQSSAoMjAyMC0wMS0wMSlcbiAgICBIdHRwUm91dGVyLnBvc3QoXG4gICAgICBcIi8yMDIwLTAxLTAxL2V4dGVuc2lvbi9yZWdpc3RlclwiLFxuICAgICAgaGFuZGxlRXh0ZW5zaW9uUmVnaXN0ZXIoc3RhdGUpLFxuICAgICksXG4gICAgSHR0cFJvdXRlci5nZXQoXG4gICAgICBcIi8yMDIwLTAxLTAxL2V4dGVuc2lvbi9ldmVudC9uZXh0XCIsXG4gICAgICBoYW5kbGVFeHRlbnNpb25FdmVudE5leHQoc3RhdGUsIHBvbGxUaW1lb3V0TXMpLFxuICAgICksXG4gICAgSHR0cFJvdXRlci5wb3N0KFxuICAgICAgXCIvMjAyMC0wMS0wMS9leHRlbnNpb24vaW5pdC9lcnJvclwiLFxuICAgICAgaGFuZGxlRXh0ZW5zaW9uSW5pdEVycm9yKHN0YXRlKSxcbiAgICApLFxuICAgIEh0dHBSb3V0ZXIucG9zdChcbiAgICAgIFwiLzIwMjAtMDEtMDEvZXh0ZW5zaW9uL2V4aXQvZXJyb3JcIixcbiAgICAgIGhhbmRsZUV4dGVuc2lvbkV4aXRFcnJvcigpLFxuICAgICksXG4gIClcblxuLyoqXG4gKiBPcHRpb25zIGZvciBzdGFydGluZyBhIFJ1bnRpbWUgQVBJIHNlcnZlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSdW50aW1lQXBpU2VydmVyT3B0aW9ucyB7XG4gIC8qKiBIb3cgbG9uZyB0byB3YWl0IGZvciBhbiBpbnZvY2F0aW9uIGJlZm9yZSByZXR1cm5pbmcgNTAzICovXG4gIHBvbGxUaW1lb3V0TXM/OiBudW1iZXJcbiAgLyoqIEZ1bmN0aW9uIG1ldGFkYXRhIGZvciBleHRlbnNpb24gcmVnaXN0cmF0aW9uICovXG4gIGZ1bmN0aW9uTWV0YWRhdGE/OiBGdW5jdGlvbk1ldGFkYXRhXG59XG5cbmNvbnN0IERFRkFVTFRfRlVOQ1RJT05fTUVUQURBVEE6IEZ1bmN0aW9uTWV0YWRhdGEgPSB7XG4gIGZ1bmN0aW9uTmFtZTogXCJsb2NhbC1mdW5jdGlvblwiLFxuICBmdW5jdGlvblZlcnNpb246IFwiJExBVEVTVFwiLFxuICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbn1cblxuLyoqXG4gKiBTdGFydCBhIFJ1bnRpbWUgQVBJIHNlcnZlciBvbiBhbiBlcGhlbWVyYWwgcG9ydC5cbiAqIFJldHVybnMgdGhlIGFjdHVhbCBwb3J0IGFuZCBzdGF0ZSBmb3IgdGhpcyBzZXJ2ZXIgaW5zdGFuY2UuXG4gKlxuICogVGhlIHNlcnZlciBpcyBzY29wZWQgLSBpdCB3aWxsIGJlIHN0b3BwZWQgd2hlbiB0aGUgc2NvcGUgY2xvc2VzLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gU2VydmVyIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICovXG5leHBvcnQgY29uc3Qgc3RhcnRSdW50aW1lQXBpU2VydmVyID0gKFxuICBvcHRpb25zOiBSdW50aW1lQXBpU2VydmVyT3B0aW9ucyA9IHt9LFxuKTogRWZmZWN0LkVmZmVjdDxSdW50aW1lQXBpU2VydmVyLCBuZXZlciwgU2NvcGUuU2NvcGU+ID0+XG4gIEVmZmVjdC5nZW4oZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCBwb2xsVGltZW91dE1zID0gb3B0aW9ucy5wb2xsVGltZW91dE1zID8/IERFRkFVTFRfUE9MTF9USU1FT1VUX01TXG4gICAgY29uc3QgZnVuY3Rpb25NZXRhZGF0YSA9XG4gICAgICBvcHRpb25zLmZ1bmN0aW9uTWV0YWRhdGEgPz8gREVGQVVMVF9GVU5DVElPTl9NRVRBREFUQVxuXG4gICAgLy8gQ3JlYXRlIHN0YXRlIChxdWV1ZXMpIGZvciB0aGlzIHNlcnZlclxuICAgIGNvbnN0IHN0YXRlID0geWllbGQqIG1ha2VSdW50aW1lQXBpU3RhdGUoZnVuY3Rpb25NZXRhZGF0YSlcblxuICAgIC8vIENyZWF0ZSByb3V0ZXIgZm9yIHRoaXMgc3RhdGVcbiAgICBjb25zdCByb3V0ZXIgPSBtYWtlUnVudGltZUFwaVJvdXRlcihzdGF0ZSwgcG9sbFRpbWVvdXRNcylcblxuICAgIC8vIENyZWF0ZSBIVFRQIHNlcnZlciBvbiBlcGhlbWVyYWwgcG9ydCAocG9ydDogMClcbiAgICBjb25zdCBzZXJ2ZXIgPSB5aWVsZCogQnVuSHR0cFNlcnZlci5tYWtlKHtcbiAgICAgIHBvcnQ6IDAsXG4gICAgICBob3N0bmFtZTogXCIwLjAuMC4wXCIsXG4gICAgICBpZGxlVGltZW91dDogMjU1LCAvLyBNYXggYWxsb3dlZCBieSBCdW4gKDQuMjUgbWludXRlcykgZm9yIGxvbmctcG9sbGluZ1xuICAgIH0pXG5cbiAgICAvLyBTdGFydCBzZXJ2aW5nIHRoZSByb3V0ZXJcbiAgICB5aWVsZCogc2VydmVyLnNlcnZlKHJvdXRlcilcblxuICAgIC8vIEdldCB0aGUgYWN0dWFsIGFzc2lnbmVkIHBvcnRcbiAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3NcbiAgICBpZiAoYWRkcmVzcy5fdGFnICE9PSBcIlRjcEFkZHJlc3NcIikge1xuICAgICAgLy8gVGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuIHNpbmNlIHdlJ3JlIHVzaW5nIFRDUFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRXhwZWN0ZWQgVENQIGFkZHJlc3NcIilcbiAgICB9XG5cbiAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKFxuICAgICAgYFJ1bnRpbWVBUEkgc2VydmVyIGxpc3RlbmluZyBvbiBwb3J0ICR7YWRkcmVzcy5wb3J0fWAsXG4gICAgKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHBvcnQ6IGFkZHJlc3MucG9ydCxcbiAgICAgIHN0YXRlLFxuICAgIH0gc2F0aXNmaWVzIFJ1bnRpbWVBcGlTZXJ2ZXJcbiAgfSlcblxuLyoqXG4gKiBRdWV1ZSBhbiBpbnZvY2F0aW9uIGZvciB0aGUgY29udGFpbmVyIHRvIHByb2Nlc3MuXG4gKi9cbmV4cG9ydCBjb25zdCBxdWV1ZUludm9jYXRpb24gPSAoXG4gIHN0YXRlOiBSdW50aW1lQXBpU3RhdGUsXG4gIGludm9jYXRpb246IExhbWJkYUludm9jYXRpb24sXG4pOiBFZmZlY3QuRWZmZWN0PHZvaWQ+ID0+IFF1ZXVlLm9mZmVyKHN0YXRlLmludm9jYXRpb25RdWV1ZSwgaW52b2NhdGlvbilcblxuLyoqXG4gKiBXYWl0IGZvciB0aGUgcmVzcG9uc2UgdG8gYSBzcGVjaWZpYyBpbnZvY2F0aW9uLlxuICovXG5leHBvcnQgY29uc3Qgd2FpdEZvclJlc3BvbnNlID0gKFxuICBzdGF0ZTogUnVudGltZUFwaVN0YXRlLFxuKTogRWZmZWN0LkVmZmVjdDxMYW1iZGFSZXNwb25zZSB8IExhbWJkYUVycm9yIHwgTGFtYmRhSW5pdEVycm9yPiA9PlxuICBRdWV1ZS50YWtlKHN0YXRlLnJlc3BvbnNlUXVldWUpXG5cbi8qKlxuICogTm90aWZ5IGFsbCByZWdpc3RlcmVkIGV4dGVuc2lvbnMgYWJvdXQgYW4gaW52b2NhdGlvbi5cbiAqIFRoaXMgc2VuZHMgYW4gSU5WT0tFIGV2ZW50IHRvIGFsbCBleHRlbnNpb25zIHRoYXQgcmVnaXN0ZXJlZCBmb3IgaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBub3RpZnlFeHRlbnNpb25zSW52b2tlID0gKFxuICBzdGF0ZTogUnVudGltZUFwaVN0YXRlLFxuICBpbnZvY2F0aW9uOiBMYW1iZGFJbnZvY2F0aW9uLFxuKTogRWZmZWN0LkVmZmVjdDx2b2lkPiA9PlxuICBFZmZlY3QuZ2VuKGZ1bmN0aW9uKiAoKSB7XG4gICAgY29uc3QgZXh0ZW5zaW9ucyA9IHlpZWxkKiBSZWYuZ2V0KHN0YXRlLmV4dGVuc2lvbnMpXG5cbiAgICBjb25zdCBpbnZva2VFdmVudDogRXh0ZW5zaW9uRXZlbnQgPSB7XG4gICAgICBldmVudFR5cGU6IFwiSU5WT0tFXCIsXG4gICAgICBkZWFkbGluZU1zOiBpbnZvY2F0aW9uLmRlYWRsaW5lTXMsXG4gICAgICByZXF1ZXN0SWQ6IGludm9jYXRpb24ucmVxdWVzdElkLFxuICAgICAgaW52b2tlZEZ1bmN0aW9uQXJuOiBpbnZvY2F0aW9uLmludm9rZWRGdW5jdGlvbkFybixcbiAgICB9XG5cbiAgICAvLyBTZW5kIElOVk9LRSBldmVudCB0byBhbGwgZXh0ZW5zaW9ucyB0aGF0IHJlZ2lzdGVyZWQgZm9yIGl0XG4gICAgZm9yIChjb25zdCBbLCBleHRTdGF0ZV0gb2YgZXh0ZW5zaW9ucykge1xuICAgICAgaWYgKGV4dFN0YXRlLmV4dGVuc2lvbi5ldmVudHMuaW5jbHVkZXMoXCJJTlZPS0VcIikpIHtcbiAgICAgICAgeWllbGQqIFF1ZXVlLm9mZmVyKGV4dFN0YXRlLmV2ZW50UXVldWUsIGludm9rZUV2ZW50KVxuICAgICAgICB5aWVsZCogRWZmZWN0LmxvZ0RlYnVnKFxuICAgICAgICAgIGBTZW50IElOVk9LRSBldmVudCB0byBleHRlbnNpb24gJHtleHRTdGF0ZS5leHRlbnNpb24ubmFtZX1gLFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4vKipcbiAqIE5vdGlmeSBhbGwgcmVnaXN0ZXJlZCBleHRlbnNpb25zIGFib3V0IHNodXRkb3duLlxuICogVGhpcyBzZW5kcyBhIFNIVVRET1dOIGV2ZW50IHRvIGFsbCBleHRlbnNpb25zIHRoYXQgcmVnaXN0ZXJlZCBmb3IgaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBub3RpZnlFeHRlbnNpb25zU2h1dGRvd24gPSAoXG4gIHN0YXRlOiBSdW50aW1lQXBpU3RhdGUsXG4gIHJlYXNvbjogXCJTUElORE9XTlwiIHwgXCJUSU1FT1VUXCIgfCBcIkZBSUxVUkVcIiA9IFwiU1BJTkRPV05cIixcbik6IEVmZmVjdC5FZmZlY3Q8dm9pZD4gPT5cbiAgRWZmZWN0LmdlbihmdW5jdGlvbiogKCkge1xuICAgIGNvbnN0IGV4dGVuc2lvbnMgPSB5aWVsZCogUmVmLmdldChzdGF0ZS5leHRlbnNpb25zKVxuXG4gICAgY29uc3Qgc2h1dGRvd25FdmVudDogRXh0ZW5zaW9uRXZlbnQgPSB7XG4gICAgICBldmVudFR5cGU6IFwiU0hVVERPV05cIixcbiAgICAgIHNodXRkb3duUmVhc29uOiByZWFzb24sXG4gICAgICBkZWFkbGluZU1zOiBEYXRlLm5vdygpICsgMjAwMCwgLy8gMiBzZWNvbmQgZGVhZGxpbmUgZm9yIHNodXRkb3duXG4gICAgfVxuXG4gICAgLy8gU2VuZCBTSFVURE9XTiBldmVudCB0byBhbGwgZXh0ZW5zaW9ucyB0aGF0IHJlZ2lzdGVyZWQgZm9yIGl0XG4gICAgZm9yIChjb25zdCBbLCBleHRTdGF0ZV0gb2YgZXh0ZW5zaW9ucykge1xuICAgICAgaWYgKGV4dFN0YXRlLmV4dGVuc2lvbi5ldmVudHMuaW5jbHVkZXMoXCJTSFVURE9XTlwiKSkge1xuICAgICAgICB5aWVsZCogUXVldWUub2ZmZXIoZXh0U3RhdGUuZXZlbnRRdWV1ZSwgc2h1dGRvd25FdmVudClcbiAgICAgICAgeWllbGQqIEVmZmVjdC5sb2dEZWJ1ZyhcbiAgICAgICAgICBgU2VudCBTSFVURE9XTiBldmVudCB0byBleHRlbnNpb24gJHtleHRTdGF0ZS5leHRlbnNpb24ubmFtZX1gLFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9KVxuIl19
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for Lambda Runtime API implementation.
|
|
3
|
+
*
|
|
4
|
+
* This implements the AWS Lambda Runtime API that Docker containers use
|
|
5
|
+
* to communicate with the Lambda runtime environment.
|
|
6
|
+
*
|
|
7
|
+
* @see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Lambda invocation context passed via headers and body
|
|
11
|
+
*/
|
|
12
|
+
export interface LambdaInvocation {
|
|
13
|
+
/** Unique request ID for this invocation */
|
|
14
|
+
requestId: string;
|
|
15
|
+
/** Event payload */
|
|
16
|
+
event: unknown;
|
|
17
|
+
/** Function ARN */
|
|
18
|
+
invokedFunctionArn: string;
|
|
19
|
+
/** Deadline timestamp in milliseconds since epoch */
|
|
20
|
+
deadlineMs: number;
|
|
21
|
+
/** Function name */
|
|
22
|
+
functionName: string;
|
|
23
|
+
/** Function version */
|
|
24
|
+
functionVersion: string;
|
|
25
|
+
/** Memory limit in MB */
|
|
26
|
+
memoryLimitMB: number;
|
|
27
|
+
/** Log group name */
|
|
28
|
+
logGroupName: string;
|
|
29
|
+
/** Log stream name */
|
|
30
|
+
logStreamName: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Response from the Lambda handler
|
|
34
|
+
*/
|
|
35
|
+
export interface LambdaResponse {
|
|
36
|
+
/** Request ID this response is for */
|
|
37
|
+
requestId: string;
|
|
38
|
+
/** Response body (JSON) */
|
|
39
|
+
body: unknown;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Error response from the Lambda handler
|
|
43
|
+
*/
|
|
44
|
+
export interface LambdaError {
|
|
45
|
+
/** Request ID this error is for */
|
|
46
|
+
requestId: string;
|
|
47
|
+
/** Error type (e.g., "Runtime.UnhandledPromiseRejection") */
|
|
48
|
+
errorType: string;
|
|
49
|
+
/** Error message */
|
|
50
|
+
errorMessage: string;
|
|
51
|
+
/** Stack trace lines */
|
|
52
|
+
stackTrace?: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Init error (error during handler initialization)
|
|
56
|
+
*/
|
|
57
|
+
export interface LambdaInitError {
|
|
58
|
+
/** Error type */
|
|
59
|
+
errorType: string;
|
|
60
|
+
/** Error message */
|
|
61
|
+
errorMessage: string;
|
|
62
|
+
/** Stack trace lines */
|
|
63
|
+
stackTrace?: string[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Runtime API server configuration
|
|
67
|
+
*/
|
|
68
|
+
export interface RuntimeApiConfig {
|
|
69
|
+
/** Port to listen on (0 for ephemeral) */
|
|
70
|
+
port: number;
|
|
71
|
+
/** Host to bind to */
|
|
72
|
+
host: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* State of a pending invocation
|
|
76
|
+
*/
|
|
77
|
+
export type InvocationState = {
|
|
78
|
+
type: "pending";
|
|
79
|
+
invocation: LambdaInvocation;
|
|
80
|
+
} | {
|
|
81
|
+
type: "completed";
|
|
82
|
+
response: LambdaResponse;
|
|
83
|
+
} | {
|
|
84
|
+
type: "error";
|
|
85
|
+
error: LambdaError;
|
|
86
|
+
} | {
|
|
87
|
+
type: "init-error";
|
|
88
|
+
error: LambdaInitError;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Headers returned by GET /invocation/next
|
|
92
|
+
*/
|
|
93
|
+
export interface InvocationNextHeaders {
|
|
94
|
+
"Lambda-Runtime-Aws-Request-Id": string;
|
|
95
|
+
"Lambda-Runtime-Deadline-Ms": string;
|
|
96
|
+
"Lambda-Runtime-Invoked-Function-Arn": string;
|
|
97
|
+
"Lambda-Runtime-Log-Group-Name"?: string;
|
|
98
|
+
"Lambda-Runtime-Log-Stream-Name"?: string;
|
|
99
|
+
"Lambda-Runtime-Trace-Id"?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Event types that extensions can register for.
|
|
103
|
+
* @see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html
|
|
104
|
+
*/
|
|
105
|
+
export type ExtensionEventType = "INVOKE" | "SHUTDOWN";
|
|
106
|
+
/**
|
|
107
|
+
* Registered extension information.
|
|
108
|
+
*/
|
|
109
|
+
export interface RegisteredExtension {
|
|
110
|
+
/** Unique identifier for the extension (UUID) */
|
|
111
|
+
extensionId: string;
|
|
112
|
+
/** Name of the extension (from Lambda-Extension-Name header) */
|
|
113
|
+
name: string;
|
|
114
|
+
/** Events this extension is registered for */
|
|
115
|
+
events: ExtensionEventType[];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Extension INVOKE event payload.
|
|
119
|
+
*/
|
|
120
|
+
export interface ExtensionInvokeEvent {
|
|
121
|
+
eventType: "INVOKE";
|
|
122
|
+
deadlineMs: number;
|
|
123
|
+
requestId: string;
|
|
124
|
+
invokedFunctionArn: string;
|
|
125
|
+
tracing?: {
|
|
126
|
+
type: string;
|
|
127
|
+
value: string;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Extension SHUTDOWN event payload.
|
|
132
|
+
*/
|
|
133
|
+
export interface ExtensionShutdownEvent {
|
|
134
|
+
eventType: "SHUTDOWN";
|
|
135
|
+
shutdownReason: "SPINDOWN" | "TIMEOUT" | "FAILURE";
|
|
136
|
+
deadlineMs: number;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Extension event (either INVOKE or SHUTDOWN).
|
|
140
|
+
*/
|
|
141
|
+
export type ExtensionEvent = ExtensionInvokeEvent | ExtensionShutdownEvent;
|
|
142
|
+
/**
|
|
143
|
+
* Response body for extension registration.
|
|
144
|
+
*/
|
|
145
|
+
export interface ExtensionRegisterResponse {
|
|
146
|
+
functionName: string;
|
|
147
|
+
functionVersion: string;
|
|
148
|
+
handler: string;
|
|
149
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for Lambda Runtime API implementation.
|
|
3
|
+
*
|
|
4
|
+
* This implements the AWS Lambda Runtime API that Docker containers use
|
|
5
|
+
* to communicate with the Lambda runtime environment.
|
|
6
|
+
*
|
|
7
|
+
* @see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2xpL3J1bnRpbWUtYXBpL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O0dBT0ciLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFR5cGVzIGZvciBMYW1iZGEgUnVudGltZSBBUEkgaW1wbGVtZW50YXRpb24uXG4gKlxuICogVGhpcyBpbXBsZW1lbnRzIHRoZSBBV1MgTGFtYmRhIFJ1bnRpbWUgQVBJIHRoYXQgRG9ja2VyIGNvbnRhaW5lcnMgdXNlXG4gKiB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBMYW1iZGEgcnVudGltZSBlbnZpcm9ubWVudC5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sYW1iZGEvbGF0ZXN0L2RnL3J1bnRpbWVzLWFwaS5odG1sXG4gKi9cblxuLyoqXG4gKiBMYW1iZGEgaW52b2NhdGlvbiBjb250ZXh0IHBhc3NlZCB2aWEgaGVhZGVycyBhbmQgYm9keVxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUludm9jYXRpb24ge1xuICAvKiogVW5pcXVlIHJlcXVlc3QgSUQgZm9yIHRoaXMgaW52b2NhdGlvbiAqL1xuICByZXF1ZXN0SWQ6IHN0cmluZ1xuICAvKiogRXZlbnQgcGF5bG9hZCAqL1xuICBldmVudDogdW5rbm93blxuICAvKiogRnVuY3Rpb24gQVJOICovXG4gIGludm9rZWRGdW5jdGlvbkFybjogc3RyaW5nXG4gIC8qKiBEZWFkbGluZSB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzIHNpbmNlIGVwb2NoICovXG4gIGRlYWRsaW5lTXM6IG51bWJlclxuICAvKiogRnVuY3Rpb24gbmFtZSAqL1xuICBmdW5jdGlvbk5hbWU6IHN0cmluZ1xuICAvKiogRnVuY3Rpb24gdmVyc2lvbiAqL1xuICBmdW5jdGlvblZlcnNpb246IHN0cmluZ1xuICAvKiogTWVtb3J5IGxpbWl0IGluIE1CICovXG4gIG1lbW9yeUxpbWl0TUI6IG51bWJlclxuICAvKiogTG9nIGdyb3VwIG5hbWUgKi9cbiAgbG9nR3JvdXBOYW1lOiBzdHJpbmdcbiAgLyoqIExvZyBzdHJlYW0gbmFtZSAqL1xuICBsb2dTdHJlYW1OYW1lOiBzdHJpbmdcbn1cblxuLyoqXG4gKiBSZXNwb25zZSBmcm9tIHRoZSBMYW1iZGEgaGFuZGxlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYVJlc3BvbnNlIHtcbiAgLyoqIFJlcXVlc3QgSUQgdGhpcyByZXNwb25zZSBpcyBmb3IgKi9cbiAgcmVxdWVzdElkOiBzdHJpbmdcbiAgLyoqIFJlc3BvbnNlIGJvZHkgKEpTT04pICovXG4gIGJvZHk6IHVua25vd25cbn1cblxuLyoqXG4gKiBFcnJvciByZXNwb25zZSBmcm9tIHRoZSBMYW1iZGEgaGFuZGxlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIExhbWJkYUVycm9yIHtcbiAgLyoqIFJlcXVlc3QgSUQgdGhpcyBlcnJvciBpcyBmb3IgKi9cbiAgcmVxdWVzdElkOiBzdHJpbmdcbiAgLyoqIEVycm9yIHR5cGUgKGUuZy4sIFwiUnVudGltZS5VbmhhbmRsZWRQcm9taXNlUmVqZWN0aW9uXCIpICovXG4gIGVycm9yVHlwZTogc3RyaW5nXG4gIC8qKiBFcnJvciBtZXNzYWdlICovXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nXG4gIC8qKiBTdGFjayB0cmFjZSBsaW5lcyAqL1xuICBzdGFja1RyYWNlPzogc3RyaW5nW11cbn1cblxuLyoqXG4gKiBJbml0IGVycm9yIChlcnJvciBkdXJpbmcgaGFuZGxlciBpbml0aWFsaXphdGlvbilcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFJbml0RXJyb3Ige1xuICAvKiogRXJyb3IgdHlwZSAqL1xuICBlcnJvclR5cGU6IHN0cmluZ1xuICAvKiogRXJyb3IgbWVzc2FnZSAqL1xuICBlcnJvck1lc3NhZ2U6IHN0cmluZ1xuICAvKiogU3RhY2sgdHJhY2UgbGluZXMgKi9cbiAgc3RhY2tUcmFjZT86IHN0cmluZ1tdXG59XG5cbi8qKlxuICogUnVudGltZSBBUEkgc2VydmVyIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSdW50aW1lQXBpQ29uZmlnIHtcbiAgLyoqIFBvcnQgdG8gbGlzdGVuIG9uICgwIGZvciBlcGhlbWVyYWwpICovXG4gIHBvcnQ6IG51bWJlclxuICAvKiogSG9zdCB0byBiaW5kIHRvICovXG4gIGhvc3Q6IHN0cmluZ1xufVxuXG4vKipcbiAqIFN0YXRlIG9mIGEgcGVuZGluZyBpbnZvY2F0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIEludm9jYXRpb25TdGF0ZSA9XG4gIHwgeyB0eXBlOiBcInBlbmRpbmdcIjsgaW52b2NhdGlvbjogTGFtYmRhSW52b2NhdGlvbiB9XG4gIHwgeyB0eXBlOiBcImNvbXBsZXRlZFwiOyByZXNwb25zZTogTGFtYmRhUmVzcG9uc2UgfVxuICB8IHsgdHlwZTogXCJlcnJvclwiOyBlcnJvcjogTGFtYmRhRXJyb3IgfVxuICB8IHsgdHlwZTogXCJpbml0LWVycm9yXCI7IGVycm9yOiBMYW1iZGFJbml0RXJyb3IgfVxuXG4vKipcbiAqIEhlYWRlcnMgcmV0dXJuZWQgYnkgR0VUIC9pbnZvY2F0aW9uL25leHRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnZvY2F0aW9uTmV4dEhlYWRlcnMge1xuICBcIkxhbWJkYS1SdW50aW1lLUF3cy1SZXF1ZXN0LUlkXCI6IHN0cmluZ1xuICBcIkxhbWJkYS1SdW50aW1lLURlYWRsaW5lLU1zXCI6IHN0cmluZ1xuICBcIkxhbWJkYS1SdW50aW1lLUludm9rZWQtRnVuY3Rpb24tQXJuXCI6IHN0cmluZ1xuICBcIkxhbWJkYS1SdW50aW1lLUxvZy1Hcm91cC1OYW1lXCI/OiBzdHJpbmdcbiAgXCJMYW1iZGEtUnVudGltZS1Mb2ctU3RyZWFtLU5hbWVcIj86IHN0cmluZ1xuICBcIkxhbWJkYS1SdW50aW1lLVRyYWNlLUlkXCI/OiBzdHJpbmdcbn1cblxuLyoqXG4gKiBFdmVudCB0eXBlcyB0aGF0IGV4dGVuc2lvbnMgY2FuIHJlZ2lzdGVyIGZvci5cbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2xhbWJkYS9sYXRlc3QvZGcvcnVudGltZXMtZXh0ZW5zaW9ucy1hcGkuaHRtbFxuICovXG5leHBvcnQgdHlwZSBFeHRlbnNpb25FdmVudFR5cGUgPSBcIklOVk9LRVwiIHwgXCJTSFVURE9XTlwiXG5cbi8qKlxuICogUmVnaXN0ZXJlZCBleHRlbnNpb24gaW5mb3JtYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaXN0ZXJlZEV4dGVuc2lvbiB7XG4gIC8qKiBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGV4dGVuc2lvbiAoVVVJRCkgKi9cbiAgZXh0ZW5zaW9uSWQ6IHN0cmluZ1xuICAvKiogTmFtZSBvZiB0aGUgZXh0ZW5zaW9uIChmcm9tIExhbWJkYS1FeHRlbnNpb24tTmFtZSBoZWFkZXIpICovXG4gIG5hbWU6IHN0cmluZ1xuICAvKiogRXZlbnRzIHRoaXMgZXh0ZW5zaW9uIGlzIHJlZ2lzdGVyZWQgZm9yICovXG4gIGV2ZW50czogRXh0ZW5zaW9uRXZlbnRUeXBlW11cbn1cblxuLyoqXG4gKiBFeHRlbnNpb24gSU5WT0tFIGV2ZW50IHBheWxvYWQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXh0ZW5zaW9uSW52b2tlRXZlbnQge1xuICBldmVudFR5cGU6IFwiSU5WT0tFXCJcbiAgZGVhZGxpbmVNczogbnVtYmVyXG4gIHJlcXVlc3RJZDogc3RyaW5nXG4gIGludm9rZWRGdW5jdGlvbkFybjogc3RyaW5nXG4gIHRyYWNpbmc/OiB7XG4gICAgdHlwZTogc3RyaW5nXG4gICAgdmFsdWU6IHN0cmluZ1xuICB9XG59XG5cbi8qKlxuICogRXh0ZW5zaW9uIFNIVVRET1dOIGV2ZW50IHBheWxvYWQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXh0ZW5zaW9uU2h1dGRvd25FdmVudCB7XG4gIGV2ZW50VHlwZTogXCJTSFVURE9XTlwiXG4gIHNodXRkb3duUmVhc29uOiBcIlNQSU5ET1dOXCIgfCBcIlRJTUVPVVRcIiB8IFwiRkFJTFVSRVwiXG4gIGRlYWRsaW5lTXM6IG51bWJlclxufVxuXG4vKipcbiAqIEV4dGVuc2lvbiBldmVudCAoZWl0aGVyIElOVk9LRSBvciBTSFVURE9XTikuXG4gKi9cbmV4cG9ydCB0eXBlIEV4dGVuc2lvbkV2ZW50ID0gRXh0ZW5zaW9uSW52b2tlRXZlbnQgfCBFeHRlbnNpb25TaHV0ZG93bkV2ZW50XG5cbi8qKlxuICogUmVzcG9uc2UgYm9keSBmb3IgZXh0ZW5zaW9uIHJlZ2lzdHJhdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFeHRlbnNpb25SZWdpc3RlclJlc3BvbnNlIHtcbiAgZnVuY3Rpb25OYW1lOiBzdHJpbmdcbiAgZnVuY3Rpb25WZXJzaW9uOiBzdHJpbmdcbiAgaGFuZGxlcjogc3RyaW5nXG59XG4iXX0=
|