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.
Files changed (53) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +94 -0
  3. package/lib/aspect/docker-function-hook.d.ts +18 -0
  4. package/lib/aspect/docker-function-hook.js +31 -0
  5. package/lib/aspect/live-lambda-aspect.d.ts +85 -0
  6. package/lib/aspect/live-lambda-aspect.js +277 -0
  7. package/lib/aspect/live-lambda-bootstrap.d.ts +17 -0
  8. package/lib/aspect/live-lambda-bootstrap.js +260 -0
  9. package/lib/aspect/nodejs-function-hook.d.ts +20 -0
  10. package/lib/aspect/nodejs-function-hook.js +27 -0
  11. package/lib/bootstrap-stack/bootstrap-stack.d.ts +60 -0
  12. package/lib/bootstrap-stack/bootstrap-stack.js +338 -0
  13. package/lib/cli/appsync/client.d.ts +30 -0
  14. package/lib/cli/appsync/client.js +227 -0
  15. package/lib/cli/cdk-app.d.ts +7 -0
  16. package/lib/cli/cdk-app.js +25 -0
  17. package/lib/cli/commands/bootstrap.d.ts +9 -0
  18. package/lib/cli/commands/bootstrap.js +50 -0
  19. package/lib/cli/commands/local.d.ts +40 -0
  20. package/lib/cli/commands/local.js +1172 -0
  21. package/lib/cli/daemon.d.ts +22 -0
  22. package/lib/cli/daemon.js +18 -0
  23. package/lib/cli/docker/container.d.ts +116 -0
  24. package/lib/cli/docker/container.js +414 -0
  25. package/lib/cli/docker/types.d.ts +71 -0
  26. package/lib/cli/docker/types.js +5 -0
  27. package/lib/cli/docker/watcher.d.ts +44 -0
  28. package/lib/cli/docker/watcher.js +115 -0
  29. package/lib/cli/index.d.ts +9 -0
  30. package/lib/cli/index.js +26 -0
  31. package/lib/cli/runtime-api/server.d.ts +102 -0
  32. package/lib/cli/runtime-api/server.js +396 -0
  33. package/lib/cli/runtime-api/types.d.ts +149 -0
  34. package/lib/cli/runtime-api/types.js +10 -0
  35. package/lib/cli/runtime-wrapper/nodejs-runtime.d.ts +16 -0
  36. package/lib/cli/runtime-wrapper/nodejs-runtime.js +248 -0
  37. package/lib/cli/watcher/file-watcher.d.ts +32 -0
  38. package/lib/cli/watcher/file-watcher.js +57 -0
  39. package/lib/functions/bridge/appsync-client.d.ts +73 -0
  40. package/lib/functions/bridge/appsync-client.js +345 -0
  41. package/lib/functions/bridge/handler.d.ts +17 -0
  42. package/lib/functions/bridge/handler.js +79 -0
  43. package/lib/functions/bridge/ssm-config.d.ts +19 -0
  44. package/lib/functions/bridge/ssm-config.js +45 -0
  45. package/lib/functions/bridge-builder/handler.d.ts +12 -0
  46. package/lib/functions/bridge-builder/handler.js +181 -0
  47. package/lib/functions/bridge-docker/runtime.d.ts +9 -0
  48. package/lib/functions/bridge-docker/runtime.js +127 -0
  49. package/lib/index.d.ts +24 -0
  50. package/lib/index.js +28 -0
  51. package/lib/shared/types.d.ts +102 -0
  52. package/lib/shared/types.js +125 -0
  53. package/package.json +111 -0
@@ -0,0 +1,345 @@
1
+ /**
2
+ * AppSync Events client with AWS SigV4 signing.
3
+ *
4
+ * This client handles:
5
+ * - HTTP requests to publish events (with IAM signing)
6
+ * - WebSocket connections for real-time subscriptions (with IAM signing)
7
+ */
8
+ import { Sha256 } from "@aws-crypto/sha256-js";
9
+ import { defaultProvider } from "@aws-sdk/credential-provider-node";
10
+ import { HttpRequest } from "@aws-sdk/protocol-http";
11
+ import { SignatureV4 } from "@aws-sdk/signature-v4";
12
+ import WebSocket from "ws";
13
+ /**
14
+ * Client for AppSync Events API
15
+ */
16
+ export class AppSyncEventsClient {
17
+ httpEndpoint;
18
+ realtimeEndpoint;
19
+ region;
20
+ ws = null;
21
+ constructor(config) {
22
+ this.httpEndpoint = config.httpEndpoint;
23
+ this.realtimeEndpoint = config.realtimeEndpoint;
24
+ // Extract region from endpoint URL
25
+ // Format: https://{api-id}.appsync-api.{region}.amazonaws.com/event
26
+ const match = config.httpEndpoint.match(/\.([a-z0-9-]+)\.amazonaws\.com/);
27
+ this.region =
28
+ config.region ?? match?.[1] ?? process.env.AWS_REGION ?? "us-east-1";
29
+ }
30
+ /**
31
+ * Publish a message to a channel and wait for a response on another channel.
32
+ */
33
+ async publishAndWaitForResponse(options) {
34
+ const { publishChannel, subscribeChannel, message, timeoutMs, matchResponse, } = options;
35
+ return new Promise((resolve, reject) => {
36
+ const timeoutId = setTimeout(() => {
37
+ this.close();
38
+ reject(new Error(`Timeout waiting for response after ${timeoutMs}ms`));
39
+ }, timeoutMs);
40
+ // Set up WebSocket connection first
41
+ this.connectAndSubscribe(subscribeChannel, (receivedMessage) => {
42
+ if (matchResponse(receivedMessage)) {
43
+ clearTimeout(timeoutId);
44
+ resolve(receivedMessage);
45
+ return true; // Signal to stop listening
46
+ }
47
+ return false;
48
+ })
49
+ .then(() => {
50
+ // Once subscribed, publish the message
51
+ return this.publish(publishChannel, message);
52
+ })
53
+ .catch((err) => {
54
+ clearTimeout(timeoutId);
55
+ reject(err);
56
+ });
57
+ });
58
+ }
59
+ /**
60
+ * Publish a message to a channel via HTTP
61
+ */
62
+ async publish(channel, message) {
63
+ const url = new URL(this.httpEndpoint);
64
+ const body = JSON.stringify({
65
+ channel,
66
+ events: [JSON.stringify(message)],
67
+ });
68
+ // AppSync Events requires /event path for publishing
69
+ const path = url.pathname.endsWith("/event") ? url.pathname : "/event";
70
+ const request = new HttpRequest({
71
+ method: "POST",
72
+ protocol: url.protocol,
73
+ hostname: url.hostname,
74
+ path,
75
+ headers: {
76
+ "Content-Type": "application/json",
77
+ host: url.hostname,
78
+ },
79
+ body,
80
+ });
81
+ // Sign the request
82
+ const signer = new SignatureV4({
83
+ credentials: defaultProvider(),
84
+ region: this.region,
85
+ service: "appsync",
86
+ sha256: Sha256,
87
+ });
88
+ const signedRequest = await signer.sign(request);
89
+ // Make the HTTP request - use the correct endpoint with /event path
90
+ const publishUrl = `${url.protocol}//${url.hostname}${path}`;
91
+ const response = await fetch(publishUrl, {
92
+ method: "POST",
93
+ headers: signedRequest.headers,
94
+ body,
95
+ });
96
+ if (!response.ok) {
97
+ const text = await response.text();
98
+ throw new Error(`Failed to publish event: ${response.status} ${text}`);
99
+ }
100
+ }
101
+ /**
102
+ * Subscribe to a channel and receive messages continuously.
103
+ * Returns an unsubscribe function.
104
+ */
105
+ async subscribe(options) {
106
+ const { channel, onMessage, onError } = options;
107
+ await this.connectAndSubscribeContinuous(channel, onMessage, onError);
108
+ return () => {
109
+ this.close();
110
+ };
111
+ }
112
+ /**
113
+ * Check if WebSocket is connected
114
+ */
115
+ isConnected() {
116
+ return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
117
+ }
118
+ /**
119
+ * Connect to WebSocket and subscribe to a channel
120
+ */
121
+ async connectAndSubscribe(channel, onMessage) {
122
+ // Build signed WebSocket connection
123
+ const [wsUrl, subprotocols] = await this.buildSignedWebSocketConnection();
124
+ return new Promise((resolve, reject) => {
125
+ this.ws = new WebSocket(wsUrl, subprotocols);
126
+ this.ws.on("open", () => {
127
+ console.log("[Bridge] WebSocket connected");
128
+ // Send connection init
129
+ this.ws?.send(JSON.stringify({ type: "connection_init" }));
130
+ });
131
+ this.ws.on("message", (data) => {
132
+ const message = JSON.parse(data.toString());
133
+ if (message.type === "connection_ack") {
134
+ console.log("[Bridge] Connection acknowledged");
135
+ // Subscribe to channel with authorization
136
+ this.createSubscribeAuthorization(channel).then((auth) => {
137
+ this.ws?.send(JSON.stringify({
138
+ type: "subscribe",
139
+ id: "sub-1",
140
+ channel,
141
+ authorization: auth,
142
+ }));
143
+ });
144
+ }
145
+ else if (message.type === "subscribe_success") {
146
+ console.log(`[Bridge] Subscribed to ${channel}`);
147
+ resolve();
148
+ }
149
+ else if (message.type === "data" && message.id === "sub-1") {
150
+ // Parse the event data
151
+ try {
152
+ const eventData = JSON.parse(message.event);
153
+ const shouldStop = onMessage(eventData);
154
+ if (shouldStop) {
155
+ this.close();
156
+ }
157
+ }
158
+ catch (err) {
159
+ console.error("[Bridge] Failed to parse event data:", err);
160
+ }
161
+ }
162
+ else if (message.type === "error") {
163
+ console.error("[Bridge] WebSocket error:", message);
164
+ reject(new Error(message.errors
165
+ ?.map((e) => e.message)
166
+ .join(", ") ?? "Unknown error"));
167
+ }
168
+ });
169
+ this.ws.on("error", (err) => {
170
+ console.error("[Bridge] WebSocket error:", err);
171
+ reject(err);
172
+ });
173
+ this.ws.on("close", () => {
174
+ console.log("[Bridge] WebSocket closed");
175
+ });
176
+ });
177
+ }
178
+ /**
179
+ * Connect to WebSocket and subscribe to a channel with continuous message handling.
180
+ * Unlike connectAndSubscribe, this doesn't close after receiving a message.
181
+ */
182
+ async connectAndSubscribeContinuous(channel, onMessage, onError) {
183
+ // Build signed WebSocket connection
184
+ const [wsUrl, subprotocols] = await this.buildSignedWebSocketConnection();
185
+ return new Promise((resolve, reject) => {
186
+ this.ws = new WebSocket(wsUrl, subprotocols);
187
+ this.ws.on("open", () => {
188
+ console.log("[AppSync] WebSocket connected");
189
+ // Send connection init
190
+ this.ws?.send(JSON.stringify({ type: "connection_init" }));
191
+ });
192
+ this.ws.on("message", async (data) => {
193
+ const message = JSON.parse(data.toString());
194
+ if (message.type === "connection_ack") {
195
+ console.log("[AppSync] Connection acknowledged");
196
+ // Subscribe to channel with authorization
197
+ this.createSubscribeAuthorization(channel).then((auth) => {
198
+ this.ws?.send(JSON.stringify({
199
+ type: "subscribe",
200
+ id: "sub-1",
201
+ channel,
202
+ authorization: auth,
203
+ }));
204
+ });
205
+ }
206
+ else if (message.type === "subscribe_success") {
207
+ console.log(`[AppSync] Subscribed to ${channel}`);
208
+ resolve();
209
+ }
210
+ else if (message.type === "data" && message.id === "sub-1") {
211
+ // Parse the event data
212
+ try {
213
+ const eventData = JSON.parse(message.event);
214
+ await onMessage(eventData);
215
+ }
216
+ catch (err) {
217
+ console.error("[AppSync] Failed to parse event data:", err);
218
+ onError?.(err instanceof Error ? err : new Error(String(err)));
219
+ }
220
+ }
221
+ else if (message.type === "error") {
222
+ console.error("[AppSync] WebSocket error:", message);
223
+ const error = new Error(message.errors
224
+ ?.map((e) => e.message)
225
+ .join(", ") ?? "Unknown error");
226
+ onError?.(error);
227
+ reject(error);
228
+ }
229
+ });
230
+ this.ws.on("error", (err) => {
231
+ console.error("[AppSync] WebSocket error:", err);
232
+ onError?.(err);
233
+ reject(err);
234
+ });
235
+ this.ws.on("close", () => {
236
+ console.log("[AppSync] WebSocket closed");
237
+ });
238
+ });
239
+ }
240
+ /**
241
+ * Create authorization headers for subscribe operation
242
+ */
243
+ async createSubscribeAuthorization(channel) {
244
+ const httpUrl = new URL(this.httpEndpoint);
245
+ const payload = JSON.stringify({ channel });
246
+ const request = new HttpRequest({
247
+ method: "POST",
248
+ protocol: "https:",
249
+ hostname: httpUrl.hostname,
250
+ path: "/event",
251
+ headers: {
252
+ accept: "application/json, text/javascript",
253
+ "content-encoding": "amz-1.0",
254
+ "content-type": "application/json; charset=UTF-8",
255
+ host: httpUrl.hostname,
256
+ },
257
+ body: payload,
258
+ });
259
+ const signer = new SignatureV4({
260
+ credentials: defaultProvider(),
261
+ region: this.region,
262
+ service: "appsync",
263
+ sha256: Sha256,
264
+ });
265
+ const signedRequest = await signer.sign(request);
266
+ const auth = {
267
+ accept: "application/json, text/javascript",
268
+ "content-encoding": "amz-1.0",
269
+ "content-type": "application/json; charset=UTF-8",
270
+ host: httpUrl.hostname,
271
+ "x-amz-date": signedRequest.headers["x-amz-date"],
272
+ "x-amz-content-sha256": signedRequest.headers["x-amz-content-sha256"],
273
+ Authorization: signedRequest.headers["authorization"],
274
+ };
275
+ if (signedRequest.headers["x-amz-security-token"]) {
276
+ auth["x-amz-security-token"] =
277
+ signedRequest.headers["x-amz-security-token"];
278
+ }
279
+ return auth;
280
+ }
281
+ /**
282
+ * Build signed WebSocket connection info for AppSync Events
283
+ * Returns [url, subprotocols] for WebSocket constructor
284
+ */
285
+ async buildSignedWebSocketConnection() {
286
+ const realtimeUrl = new URL(this.realtimeEndpoint);
287
+ realtimeUrl.pathname = "/event/realtime";
288
+ const httpUrl = new URL(this.httpEndpoint);
289
+ // For IAM auth, sign a POST request to the HTTP endpoint
290
+ const request = new HttpRequest({
291
+ method: "POST",
292
+ protocol: "https:",
293
+ hostname: httpUrl.hostname,
294
+ path: "/event",
295
+ headers: {
296
+ accept: "application/json, text/javascript",
297
+ "content-encoding": "amz-1.0",
298
+ "content-type": "application/json; charset=UTF-8",
299
+ host: httpUrl.hostname,
300
+ },
301
+ body: "{}",
302
+ });
303
+ const signer = new SignatureV4({
304
+ credentials: defaultProvider(),
305
+ region: this.region,
306
+ service: "appsync",
307
+ sha256: Sha256,
308
+ });
309
+ const signedRequest = await signer.sign(request);
310
+ // Build header payload for subprotocol - include all signed headers
311
+ const headerPayload = {
312
+ accept: "application/json, text/javascript",
313
+ "content-encoding": "amz-1.0",
314
+ "content-type": "application/json; charset=UTF-8",
315
+ host: httpUrl.hostname,
316
+ "x-amz-date": signedRequest.headers["x-amz-date"],
317
+ "x-amz-content-sha256": signedRequest.headers["x-amz-content-sha256"],
318
+ Authorization: signedRequest.headers["authorization"],
319
+ };
320
+ // Add session token if present
321
+ if (signedRequest.headers["x-amz-security-token"]) {
322
+ headerPayload["x-amz-security-token"] =
323
+ signedRequest.headers["x-amz-security-token"];
324
+ }
325
+ // Base64url encode (no padding, URL-safe)
326
+ const encodedHeader = Buffer.from(JSON.stringify(headerPayload))
327
+ .toString("base64")
328
+ .replace(/\+/g, "-")
329
+ .replace(/\//g, "_")
330
+ .replace(/=+$/, "");
331
+ // Auth is passed as header-{base64url} subprotocol
332
+ const authSubprotocol = `header-${encodedHeader}`;
333
+ return [realtimeUrl.toString(), ["aws-appsync-event-ws", authSubprotocol]];
334
+ }
335
+ /**
336
+ * Close the WebSocket connection
337
+ */
338
+ async close() {
339
+ if (this.ws) {
340
+ this.ws.close();
341
+ this.ws = null;
342
+ }
343
+ }
344
+ }
345
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwc3luYy1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZnVuY3Rpb25zL2JyaWRnZS9hcHBzeW5jLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFDOUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1DQUFtQyxDQUFBO0FBQ25FLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFDbkQsT0FBTyxTQUFTLE1BQU0sSUFBSSxDQUFBO0FBc0IxQjs7R0FFRztBQUNILE1BQU0sT0FBTyxtQkFBbUI7SUFDYixZQUFZLENBQVE7SUFDcEIsZ0JBQWdCLENBQVE7SUFDeEIsTUFBTSxDQUFRO0lBQ3ZCLEVBQUUsR0FBcUIsSUFBSSxDQUFBO0lBRW5DLFlBQVksTUFBaUM7UUFDM0MsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFBO1FBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUE7UUFDL0MsbUNBQW1DO1FBQ25DLG9FQUFvRTtRQUNwRSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFBO1FBQ3pFLElBQUksQ0FBQyxNQUFNO1lBQ1QsTUFBTSxDQUFDLE1BQU0sSUFBSSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxXQUFXLENBQUE7SUFDeEUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLHlCQUF5QixDQUM3QixPQUFpQztRQUVqQyxNQUFNLEVBQ0osY0FBYyxFQUNkLGdCQUFnQixFQUNoQixPQUFPLEVBQ1AsU0FBUyxFQUNULGFBQWEsR0FDZCxHQUFHLE9BQU8sQ0FBQTtRQUVYLE9BQU8sSUFBSSxPQUFPLENBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDeEMsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFDaEMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFBO2dCQUNaLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsU0FBUyxJQUFJLENBQUMsQ0FBQyxDQUFBO1lBQ3hFLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQTtZQUViLG9DQUFvQztZQUNwQyxJQUFJLENBQUMsbUJBQW1CLENBQUksZ0JBQWdCLEVBQUUsQ0FBQyxlQUFlLEVBQUUsRUFBRTtnQkFDaEUsSUFBSSxhQUFhLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQztvQkFDbkMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFBO29CQUN2QixPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7b0JBQ3hCLE9BQU8sSUFBSSxDQUFBLENBQUMsMkJBQTJCO2dCQUN6QyxDQUFDO2dCQUNELE9BQU8sS0FBSyxDQUFBO1lBQ2QsQ0FBQyxDQUFDO2lCQUNDLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ1QsdUNBQXVDO2dCQUN2QyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1lBQzlDLENBQUMsQ0FBQztpQkFDRCxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDYixZQUFZLENBQUMsU0FBUyxDQUFDLENBQUE7Z0JBQ3ZCLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNiLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQWUsRUFBRSxPQUFnQjtRQUM3QyxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDdEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUMxQixPQUFPO1lBQ1AsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNsQyxDQUFDLENBQUE7UUFFRixxREFBcUQ7UUFDckQsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtRQUV0RSxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsQ0FBQztZQUM5QixNQUFNLEVBQUUsTUFBTTtZQUNkLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUTtZQUN0QixRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVE7WUFDdEIsSUFBSTtZQUNKLE9BQU8sRUFBRTtnQkFDUCxjQUFjLEVBQUUsa0JBQWtCO2dCQUNsQyxJQUFJLEVBQUUsR0FBRyxDQUFDLFFBQVE7YUFDbkI7WUFDRCxJQUFJO1NBQ0wsQ0FBQyxDQUFBO1FBRUYsbUJBQW1CO1FBQ25CLE1BQU0sTUFBTSxHQUFHLElBQUksV0FBVyxDQUFDO1lBQzdCLFdBQVcsRUFBRSxlQUFlLEVBQUU7WUFDOUIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLE9BQU8sRUFBRSxTQUFTO1lBQ2xCLE1BQU0sRUFBRSxNQUFNO1NBQ2YsQ0FBQyxDQUFBO1FBRUYsTUFBTSxhQUFhLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBRWhELG9FQUFvRTtRQUNwRSxNQUFNLFVBQVUsR0FBRyxHQUFHLEdBQUcsQ0FBQyxRQUFRLEtBQUssR0FBRyxDQUFDLFFBQVEsR0FBRyxJQUFJLEVBQUUsQ0FBQTtRQUM1RCxNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxVQUFVLEVBQUU7WUFDdkMsTUFBTSxFQUFFLE1BQU07WUFDZCxPQUFPLEVBQUUsYUFBYSxDQUFDLE9BQWlDO1lBQ3hELElBQUk7U0FDTCxDQUFDLENBQUE7UUFFRixJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFBO1lBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLFFBQVEsQ0FBQyxNQUFNLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUN4RSxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxTQUFTLENBQUksT0FBK0I7UUFDaEQsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFBO1FBRS9DLE1BQU0sSUFBSSxDQUFDLDZCQUE2QixDQUFJLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFFeEUsT0FBTyxHQUFHLEVBQUU7WUFDVixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDZCxDQUFDLENBQUE7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsRUFBRSxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxDQUFBO0lBQ2xFLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxtQkFBbUIsQ0FDL0IsT0FBZSxFQUNmLFNBQWtDO1FBRWxDLG9DQUFvQztRQUNwQyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLDhCQUE4QixFQUFFLENBQUE7UUFFekUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksU0FBUyxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQTtZQUU1QyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO2dCQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixDQUFDLENBQUE7Z0JBQzNDLHVCQUF1QjtnQkFDdkIsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQTtZQUM1RCxDQUFDLENBQUMsQ0FBQTtZQUVGLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUM3QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFBO2dCQUUzQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztvQkFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFBO29CQUMvQywwQ0FBMEM7b0JBQzFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTt3QkFDdkQsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQ1gsSUFBSSxDQUFDLFNBQVMsQ0FBQzs0QkFDYixJQUFJLEVBQUUsV0FBVzs0QkFDakIsRUFBRSxFQUFFLE9BQU87NEJBQ1gsT0FBTzs0QkFDUCxhQUFhLEVBQUUsSUFBSTt5QkFDcEIsQ0FBQyxDQUNILENBQUE7b0JBQ0gsQ0FBQyxDQUFDLENBQUE7Z0JBQ0osQ0FBQztxQkFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssbUJBQW1CLEVBQUUsQ0FBQztvQkFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsT0FBTyxFQUFFLENBQUMsQ0FBQTtvQkFDaEQsT0FBTyxFQUFFLENBQUE7Z0JBQ1gsQ0FBQztxQkFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssT0FBTyxFQUFFLENBQUM7b0JBQzdELHVCQUF1QjtvQkFDdkIsSUFBSSxDQUFDO3dCQUNILE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBTSxDQUFBO3dCQUNoRCxNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUE7d0JBQ3ZDLElBQUksVUFBVSxFQUFFLENBQUM7NEJBQ2YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFBO3dCQUNkLENBQUM7b0JBQ0gsQ0FBQztvQkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO3dCQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0NBQXNDLEVBQUUsR0FBRyxDQUFDLENBQUE7b0JBQzVELENBQUM7Z0JBQ0gsQ0FBQztxQkFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFLENBQUM7b0JBQ3BDLE9BQU8sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEVBQUUsT0FBTyxDQUFDLENBQUE7b0JBQ25ELE1BQU0sQ0FDSixJQUFJLEtBQUssQ0FDUCxPQUFPLENBQUMsTUFBTTt3QkFDWixFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQXNCLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7eUJBQzNDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxlQUFlLENBQ2pDLENBQ0YsQ0FBQTtnQkFDSCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUE7WUFFRixJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDMUIsT0FBTyxDQUFDLEtBQUssQ0FBQywyQkFBMkIsRUFBRSxHQUFHLENBQUMsQ0FBQTtnQkFDL0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQ2IsQ0FBQyxDQUFDLENBQUE7WUFFRixJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFO2dCQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLDJCQUEyQixDQUFDLENBQUE7WUFDMUMsQ0FBQyxDQUFDLENBQUE7UUFDSixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSyxLQUFLLENBQUMsNkJBQTZCLENBQ3pDLE9BQWUsRUFDZixTQUErQyxFQUMvQyxPQUFnQztRQUVoQyxvQ0FBb0M7UUFDcEMsTUFBTSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFBO1FBRXpFLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUE7WUFFNUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtnQkFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFBO2dCQUM1Qyx1QkFBdUI7Z0JBQ3ZCLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFDNUQsQ0FBQyxDQUFDLENBQUE7WUFFRixJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO2dCQUNuQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFBO2dCQUUzQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztvQkFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFBO29CQUNoRCwwQ0FBMEM7b0JBQzFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTt3QkFDdkQsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQ1gsSUFBSSxDQUFDLFNBQVMsQ0FBQzs0QkFDYixJQUFJLEVBQUUsV0FBVzs0QkFDakIsRUFBRSxFQUFFLE9BQU87NEJBQ1gsT0FBTzs0QkFDUCxhQUFhLEVBQUUsSUFBSTt5QkFDcEIsQ0FBQyxDQUNILENBQUE7b0JBQ0gsQ0FBQyxDQUFDLENBQUE7Z0JBQ0osQ0FBQztxQkFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssbUJBQW1CLEVBQUUsQ0FBQztvQkFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsT0FBTyxFQUFFLENBQUMsQ0FBQTtvQkFDakQsT0FBTyxFQUFFLENBQUE7Z0JBQ1gsQ0FBQztxQkFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLE9BQU8sQ0FBQyxFQUFFLEtBQUssT0FBTyxFQUFFLENBQUM7b0JBQzdELHVCQUF1QjtvQkFDdkIsSUFBSSxDQUFDO3dCQUNILE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBTSxDQUFBO3dCQUNoRCxNQUFNLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtvQkFDNUIsQ0FBQztvQkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO3dCQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUNBQXVDLEVBQUUsR0FBRyxDQUFDLENBQUE7d0JBQzNELE9BQU8sRUFBRSxDQUFDLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtvQkFDaEUsQ0FBQztnQkFDSCxDQUFDO3FCQUFNLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztvQkFDcEMsT0FBTyxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsRUFBRSxPQUFPLENBQUMsQ0FBQTtvQkFDcEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQ3JCLE9BQU8sQ0FBQyxNQUFNO3dCQUNaLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBc0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQzt5QkFDM0MsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLGVBQWUsQ0FDakMsQ0FBQTtvQkFDRCxPQUFPLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQTtvQkFDaEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO2dCQUNmLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQTtZQUVGLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUMxQixPQUFPLENBQUMsS0FBSyxDQUFDLDRCQUE0QixFQUFFLEdBQUcsQ0FBQyxDQUFBO2dCQUNoRCxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQTtnQkFDZCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7WUFDYixDQUFDLENBQUMsQ0FBQTtZQUVGLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7Z0JBQ3ZCLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLENBQUMsQ0FBQTtZQUMzQyxDQUFDLENBQUMsQ0FBQTtRQUNKLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLDRCQUE0QixDQUN4QyxPQUFlO1FBRWYsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO1FBQzFDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBRTNDLE1BQU0sT0FBTyxHQUFHLElBQUksV0FBVyxDQUFDO1lBQzlCLE1BQU0sRUFBRSxNQUFNO1lBQ2QsUUFBUSxFQUFFLFFBQVE7WUFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQzFCLElBQUksRUFBRSxRQUFRO1lBQ2QsT0FBTyxFQUFFO2dCQUNQLE1BQU0sRUFBRSxtQ0FBbUM7Z0JBQzNDLGtCQUFrQixFQUFFLFNBQVM7Z0JBQzdCLGNBQWMsRUFBRSxpQ0FBaUM7Z0JBQ2pELElBQUksRUFBRSxPQUFPLENBQUMsUUFBUTthQUN2QjtZQUNELElBQUksRUFBRSxPQUFPO1NBQ2QsQ0FBQyxDQUFBO1FBRUYsTUFBTSxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUM7WUFDN0IsV0FBVyxFQUFFLGVBQWUsRUFBRTtZQUM5QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsT0FBTyxFQUFFLFNBQVM7WUFDbEIsTUFBTSxFQUFFLE1BQU07U0FDZixDQUFDLENBQUE7UUFFRixNQUFNLGFBQWEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFaEQsTUFBTSxJQUFJLEdBQTJCO1lBQ25DLE1BQU0sRUFBRSxtQ0FBbUM7WUFDM0Msa0JBQWtCLEVBQUUsU0FBUztZQUM3QixjQUFjLEVBQUUsaUNBQWlDO1lBQ2pELElBQUksRUFBRSxPQUFPLENBQUMsUUFBUTtZQUN0QixZQUFZLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFDakQsc0JBQXNCLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQztZQUNyRSxhQUFhLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7U0FDdEQsQ0FBQTtRQUVELElBQUksYUFBYSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLENBQUM7WUFDbEQsSUFBSSxDQUFDLHNCQUFzQixDQUFDO2dCQUMxQixhQUFhLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLENBQUE7UUFDakQsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVEOzs7T0FHRztJQUNLLEtBQUssQ0FBQyw4QkFBOEI7UUFDMUMsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUE7UUFDbEQsV0FBVyxDQUFDLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQTtRQUN4QyxNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUE7UUFFMUMseURBQXlEO1FBQ3pELE1BQU0sT0FBTyxHQUFHLElBQUksV0FBVyxDQUFDO1lBQzlCLE1BQU0sRUFBRSxNQUFNO1lBQ2QsUUFBUSxFQUFFLFFBQVE7WUFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQzFCLElBQUksRUFBRSxRQUFRO1lBQ2QsT0FBTyxFQUFFO2dCQUNQLE1BQU0sRUFBRSxtQ0FBbUM7Z0JBQzNDLGtCQUFrQixFQUFFLFNBQVM7Z0JBQzdCLGNBQWMsRUFBRSxpQ0FBaUM7Z0JBQ2pELElBQUksRUFBRSxPQUFPLENBQUMsUUFBUTthQUN2QjtZQUNELElBQUksRUFBRSxJQUFJO1NBQ1gsQ0FBQyxDQUFBO1FBRUYsTUFBTSxNQUFNLEdBQUcsSUFBSSxXQUFXLENBQUM7WUFDN0IsV0FBVyxFQUFFLGVBQWUsRUFBRTtZQUM5QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsT0FBTyxFQUFFLFNBQVM7WUFDbEIsTUFBTSxFQUFFLE1BQU07U0FDZixDQUFDLENBQUE7UUFFRixNQUFNLGFBQWEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFaEQsb0VBQW9FO1FBQ3BFLE1BQU0sYUFBYSxHQUEyQjtZQUM1QyxNQUFNLEVBQUUsbUNBQW1DO1lBQzNDLGtCQUFrQixFQUFFLFNBQVM7WUFDN0IsY0FBYyxFQUFFLGlDQUFpQztZQUNqRCxJQUFJLEVBQUUsT0FBTyxDQUFDLFFBQVE7WUFDdEIsWUFBWSxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDO1lBQ2pELHNCQUFzQixFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUM7WUFDckUsYUFBYSxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO1NBQ3RELENBQUE7UUFFRCwrQkFBK0I7UUFDL0IsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLEVBQUUsQ0FBQztZQUNsRCxhQUFhLENBQUMsc0JBQXNCLENBQUM7Z0JBQ25DLGFBQWEsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtRQUNqRCxDQUFDO1FBRUQsMENBQTBDO1FBQzFDLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQzthQUM3RCxRQUFRLENBQUMsUUFBUSxDQUFDO2FBQ2xCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDO2FBQ25CLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDO2FBQ25CLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFFckIsbURBQW1EO1FBQ25ELE1BQU0sZUFBZSxHQUFHLFVBQVUsYUFBYSxFQUFFLENBQUE7UUFFakQsT0FBTyxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLHNCQUFzQixFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUE7SUFDNUUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLEtBQUs7UUFDVCxJQUFJLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNaLElBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUE7WUFDZixJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQTtRQUNoQixDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBcHBTeW5jIEV2ZW50cyBjbGllbnQgd2l0aCBBV1MgU2lnVjQgc2lnbmluZy5cbiAqXG4gKiBUaGlzIGNsaWVudCBoYW5kbGVzOlxuICogLSBIVFRQIHJlcXVlc3RzIHRvIHB1Ymxpc2ggZXZlbnRzICh3aXRoIElBTSBzaWduaW5nKVxuICogLSBXZWJTb2NrZXQgY29ubmVjdGlvbnMgZm9yIHJlYWwtdGltZSBzdWJzY3JpcHRpb25zICh3aXRoIElBTSBzaWduaW5nKVxuICovXG5cbmltcG9ydCB7IFNoYTI1NiB9IGZyb20gXCJAYXdzLWNyeXB0by9zaGEyNTYtanNcIlxuaW1wb3J0IHsgZGVmYXVsdFByb3ZpZGVyIH0gZnJvbSBcIkBhd3Mtc2RrL2NyZWRlbnRpYWwtcHJvdmlkZXItbm9kZVwiXG5pbXBvcnQgeyBIdHRwUmVxdWVzdCB9IGZyb20gXCJAYXdzLXNkay9wcm90b2NvbC1odHRwXCJcbmltcG9ydCB7IFNpZ25hdHVyZVY0IH0gZnJvbSBcIkBhd3Mtc2RrL3NpZ25hdHVyZS12NFwiXG5pbXBvcnQgV2ViU29ja2V0IGZyb20gXCJ3c1wiXG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwU3luY0V2ZW50c0NsaWVudENvbmZpZyB7XG4gIGh0dHBFbmRwb2ludDogc3RyaW5nXG4gIHJlYWx0aW1lRW5kcG9pbnQ6IHN0cmluZ1xuICByZWdpb24/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQdWJsaXNoQW5kV2FpdE9wdGlvbnM8VD4ge1xuICBwdWJsaXNoQ2hhbm5lbDogc3RyaW5nXG4gIHN1YnNjcmliZUNoYW5uZWw6IHN0cmluZ1xuICBtZXNzYWdlOiB1bmtub3duXG4gIHRpbWVvdXRNczogbnVtYmVyXG4gIG1hdGNoUmVzcG9uc2U6IChtZXNzYWdlOiBUKSA9PiBib29sZWFuXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3Vic2NyaXB0aW9uT3B0aW9uczxUPiB7XG4gIGNoYW5uZWw6IHN0cmluZ1xuICBvbk1lc3NhZ2U6IChtZXNzYWdlOiBUKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPlxuICBvbkVycm9yPzogKGVycm9yOiBFcnJvcikgPT4gdm9pZFxufVxuXG4vKipcbiAqIENsaWVudCBmb3IgQXBwU3luYyBFdmVudHMgQVBJXG4gKi9cbmV4cG9ydCBjbGFzcyBBcHBTeW5jRXZlbnRzQ2xpZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBodHRwRW5kcG9pbnQ6IHN0cmluZ1xuICBwcml2YXRlIHJlYWRvbmx5IHJlYWx0aW1lRW5kcG9pbnQ6IHN0cmluZ1xuICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lvbjogc3RyaW5nXG4gIHByaXZhdGUgd3M6IFdlYlNvY2tldCB8IG51bGwgPSBudWxsXG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBBcHBTeW5jRXZlbnRzQ2xpZW50Q29uZmlnKSB7XG4gICAgdGhpcy5odHRwRW5kcG9pbnQgPSBjb25maWcuaHR0cEVuZHBvaW50XG4gICAgdGhpcy5yZWFsdGltZUVuZHBvaW50ID0gY29uZmlnLnJlYWx0aW1lRW5kcG9pbnRcbiAgICAvLyBFeHRyYWN0IHJlZ2lvbiBmcm9tIGVuZHBvaW50IFVSTFxuICAgIC8vIEZvcm1hdDogaHR0cHM6Ly97YXBpLWlkfS5hcHBzeW5jLWFwaS57cmVnaW9ufS5hbWF6b25hd3MuY29tL2V2ZW50XG4gICAgY29uc3QgbWF0Y2ggPSBjb25maWcuaHR0cEVuZHBvaW50Lm1hdGNoKC9cXC4oW2EtejAtOS1dKylcXC5hbWF6b25hd3NcXC5jb20vKVxuICAgIHRoaXMucmVnaW9uID1cbiAgICAgIGNvbmZpZy5yZWdpb24gPz8gbWF0Y2g/LlsxXSA/PyBwcm9jZXNzLmVudi5BV1NfUkVHSU9OID8/IFwidXMtZWFzdC0xXCJcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaXNoIGEgbWVzc2FnZSB0byBhIGNoYW5uZWwgYW5kIHdhaXQgZm9yIGEgcmVzcG9uc2Ugb24gYW5vdGhlciBjaGFubmVsLlxuICAgKi9cbiAgYXN5bmMgcHVibGlzaEFuZFdhaXRGb3JSZXNwb25zZTxUPihcbiAgICBvcHRpb25zOiBQdWJsaXNoQW5kV2FpdE9wdGlvbnM8VD4sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IHtcbiAgICAgIHB1Ymxpc2hDaGFubmVsLFxuICAgICAgc3Vic2NyaWJlQ2hhbm5lbCxcbiAgICAgIG1lc3NhZ2UsXG4gICAgICB0aW1lb3V0TXMsXG4gICAgICBtYXRjaFJlc3BvbnNlLFxuICAgIH0gPSBvcHRpb25zXG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgdGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xvc2UoKVxuICAgICAgICByZWplY3QobmV3IEVycm9yKGBUaW1lb3V0IHdhaXRpbmcgZm9yIHJlc3BvbnNlIGFmdGVyICR7dGltZW91dE1zfW1zYCkpXG4gICAgICB9LCB0aW1lb3V0TXMpXG5cbiAgICAgIC8vIFNldCB1cCBXZWJTb2NrZXQgY29ubmVjdGlvbiBmaXJzdFxuICAgICAgdGhpcy5jb25uZWN0QW5kU3Vic2NyaWJlPFQ+KHN1YnNjcmliZUNoYW5uZWwsIChyZWNlaXZlZE1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKG1hdGNoUmVzcG9uc2UocmVjZWl2ZWRNZXNzYWdlKSkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpXG4gICAgICAgICAgcmVzb2x2ZShyZWNlaXZlZE1lc3NhZ2UpXG4gICAgICAgICAgcmV0dXJuIHRydWUgLy8gU2lnbmFsIHRvIHN0b3AgbGlzdGVuaW5nXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgLy8gT25jZSBzdWJzY3JpYmVkLCBwdWJsaXNoIHRoZSBtZXNzYWdlXG4gICAgICAgICAgcmV0dXJuIHRoaXMucHVibGlzaChwdWJsaXNoQ2hhbm5lbCwgbWVzc2FnZSlcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKVxuICAgICAgICAgIHJlamVjdChlcnIpXG4gICAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaXNoIGEgbWVzc2FnZSB0byBhIGNoYW5uZWwgdmlhIEhUVFBcbiAgICovXG4gIGFzeW5jIHB1Ymxpc2goY2hhbm5lbDogc3RyaW5nLCBtZXNzYWdlOiB1bmtub3duKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdXJsID0gbmV3IFVSTCh0aGlzLmh0dHBFbmRwb2ludClcbiAgICBjb25zdCBib2R5ID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgY2hhbm5lbCxcbiAgICAgIGV2ZW50czogW0pTT04uc3RyaW5naWZ5KG1lc3NhZ2UpXSxcbiAgICB9KVxuXG4gICAgLy8gQXBwU3luYyBFdmVudHMgcmVxdWlyZXMgL2V2ZW50IHBhdGggZm9yIHB1Ymxpc2hpbmdcbiAgICBjb25zdCBwYXRoID0gdXJsLnBhdGhuYW1lLmVuZHNXaXRoKFwiL2V2ZW50XCIpID8gdXJsLnBhdGhuYW1lIDogXCIvZXZlbnRcIlxuXG4gICAgY29uc3QgcmVxdWVzdCA9IG5ldyBIdHRwUmVxdWVzdCh7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgcHJvdG9jb2w6IHVybC5wcm90b2NvbCxcbiAgICAgIGhvc3RuYW1lOiB1cmwuaG9zdG5hbWUsXG4gICAgICBwYXRoLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgaG9zdDogdXJsLmhvc3RuYW1lLFxuICAgICAgfSxcbiAgICAgIGJvZHksXG4gICAgfSlcblxuICAgIC8vIFNpZ24gdGhlIHJlcXVlc3RcbiAgICBjb25zdCBzaWduZXIgPSBuZXcgU2lnbmF0dXJlVjQoe1xuICAgICAgY3JlZGVudGlhbHM6IGRlZmF1bHRQcm92aWRlcigpLFxuICAgICAgcmVnaW9uOiB0aGlzLnJlZ2lvbixcbiAgICAgIHNlcnZpY2U6IFwiYXBwc3luY1wiLFxuICAgICAgc2hhMjU2OiBTaGEyNTYsXG4gICAgfSlcblxuICAgIGNvbnN0IHNpZ25lZFJlcXVlc3QgPSBhd2FpdCBzaWduZXIuc2lnbihyZXF1ZXN0KVxuXG4gICAgLy8gTWFrZSB0aGUgSFRUUCByZXF1ZXN0IC0gdXNlIHRoZSBjb3JyZWN0IGVuZHBvaW50IHdpdGggL2V2ZW50IHBhdGhcbiAgICBjb25zdCBwdWJsaXNoVXJsID0gYCR7dXJsLnByb3RvY29sfS8vJHt1cmwuaG9zdG5hbWV9JHtwYXRofWBcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHB1Ymxpc2hVcmwsIHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBoZWFkZXJzOiBzaWduZWRSZXF1ZXN0LmhlYWRlcnMgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPixcbiAgICAgIGJvZHksXG4gICAgfSlcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KClcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHB1Ymxpc2ggZXZlbnQ6ICR7cmVzcG9uc2Uuc3RhdHVzfSAke3RleHR9YClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlIHRvIGEgY2hhbm5lbCBhbmQgcmVjZWl2ZSBtZXNzYWdlcyBjb250aW51b3VzbHkuXG4gICAqIFJldHVybnMgYW4gdW5zdWJzY3JpYmUgZnVuY3Rpb24uXG4gICAqL1xuICBhc3luYyBzdWJzY3JpYmU8VD4ob3B0aW9uczogU3Vic2NyaXB0aW9uT3B0aW9uczxUPik6IFByb21pc2U8KCkgPT4gdm9pZD4ge1xuICAgIGNvbnN0IHsgY2hhbm5lbCwgb25NZXNzYWdlLCBvbkVycm9yIH0gPSBvcHRpb25zXG5cbiAgICBhd2FpdCB0aGlzLmNvbm5lY3RBbmRTdWJzY3JpYmVDb250aW51b3VzPFQ+KGNoYW5uZWwsIG9uTWVzc2FnZSwgb25FcnJvcilcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB0aGlzLmNsb3NlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgV2ViU29ja2V0IGlzIGNvbm5lY3RlZFxuICAgKi9cbiAgaXNDb25uZWN0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMud3MgIT09IG51bGwgJiYgdGhpcy53cy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTlxuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3QgdG8gV2ViU29ja2V0IGFuZCBzdWJzY3JpYmUgdG8gYSBjaGFubmVsXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNvbm5lY3RBbmRTdWJzY3JpYmU8VD4oXG4gICAgY2hhbm5lbDogc3RyaW5nLFxuICAgIG9uTWVzc2FnZTogKG1lc3NhZ2U6IFQpID0+IGJvb2xlYW4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIEJ1aWxkIHNpZ25lZCBXZWJTb2NrZXQgY29ubmVjdGlvblxuICAgIGNvbnN0IFt3c1VybCwgc3VicHJvdG9jb2xzXSA9IGF3YWl0IHRoaXMuYnVpbGRTaWduZWRXZWJTb2NrZXRDb25uZWN0aW9uKClcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLndzID0gbmV3IFdlYlNvY2tldCh3c1VybCwgc3VicHJvdG9jb2xzKVxuXG4gICAgICB0aGlzLndzLm9uKFwib3BlblwiLCAoKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiW0JyaWRnZV0gV2ViU29ja2V0IGNvbm5lY3RlZFwiKVxuICAgICAgICAvLyBTZW5kIGNvbm5lY3Rpb24gaW5pdFxuICAgICAgICB0aGlzLndzPy5zZW5kKEpTT04uc3RyaW5naWZ5KHsgdHlwZTogXCJjb25uZWN0aW9uX2luaXRcIiB9KSlcbiAgICAgIH0pXG5cbiAgICAgIHRoaXMud3Mub24oXCJtZXNzYWdlXCIsIChkYXRhKSA9PiB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBKU09OLnBhcnNlKGRhdGEudG9TdHJpbmcoKSlcblxuICAgICAgICBpZiAobWVzc2FnZS50eXBlID09PSBcImNvbm5lY3Rpb25fYWNrXCIpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIltCcmlkZ2VdIENvbm5lY3Rpb24gYWNrbm93bGVkZ2VkXCIpXG4gICAgICAgICAgLy8gU3Vic2NyaWJlIHRvIGNoYW5uZWwgd2l0aCBhdXRob3JpemF0aW9uXG4gICAgICAgICAgdGhpcy5jcmVhdGVTdWJzY3JpYmVBdXRob3JpemF0aW9uKGNoYW5uZWwpLnRoZW4oKGF1dGgpID0+IHtcbiAgICAgICAgICAgIHRoaXMud3M/LnNlbmQoXG4gICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInN1YnNjcmliZVwiLFxuICAgICAgICAgICAgICAgIGlkOiBcInN1Yi0xXCIsXG4gICAgICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgICAgICBhdXRob3JpemF0aW9uOiBhdXRoLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9KVxuICAgICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gXCJzdWJzY3JpYmVfc3VjY2Vzc1wiKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYFtCcmlkZ2VdIFN1YnNjcmliZWQgdG8gJHtjaGFubmVsfWApXG4gICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBcImRhdGFcIiAmJiBtZXNzYWdlLmlkID09PSBcInN1Yi0xXCIpIHtcbiAgICAgICAgICAvLyBQYXJzZSB0aGUgZXZlbnQgZGF0YVxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBldmVudERhdGEgPSBKU09OLnBhcnNlKG1lc3NhZ2UuZXZlbnQpIGFzIFRcbiAgICAgICAgICAgIGNvbnN0IHNob3VsZFN0b3AgPSBvbk1lc3NhZ2UoZXZlbnREYXRhKVxuICAgICAgICAgICAgaWYgKHNob3VsZFN0b3ApIHtcbiAgICAgICAgICAgICAgdGhpcy5jbG9zZSgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW0JyaWRnZV0gRmFpbGVkIHRvIHBhcnNlIGV2ZW50IGRhdGE6XCIsIGVycilcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBcImVycm9yXCIpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW0JyaWRnZV0gV2ViU29ja2V0IGVycm9yOlwiLCBtZXNzYWdlKVxuICAgICAgICAgIHJlamVjdChcbiAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgbWVzc2FnZS5lcnJvcnNcbiAgICAgICAgICAgICAgICA/Lm1hcCgoZTogeyBtZXNzYWdlOiBzdHJpbmcgfSkgPT4gZS5tZXNzYWdlKVxuICAgICAgICAgICAgICAgIC5qb2luKFwiLCBcIikgPz8gXCJVbmtub3duIGVycm9yXCIsXG4gICAgICAgICAgICApLFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgdGhpcy53cy5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIltCcmlkZ2VdIFdlYlNvY2tldCBlcnJvcjpcIiwgZXJyKVxuICAgICAgICByZWplY3QoZXJyKVxuICAgICAgfSlcblxuICAgICAgdGhpcy53cy5vbihcImNsb3NlXCIsICgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coXCJbQnJpZGdlXSBXZWJTb2NrZXQgY2xvc2VkXCIpXG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQ29ubmVjdCB0byBXZWJTb2NrZXQgYW5kIHN1YnNjcmliZSB0byBhIGNoYW5uZWwgd2l0aCBjb250aW51b3VzIG1lc3NhZ2UgaGFuZGxpbmcuXG4gICAqIFVubGlrZSBjb25uZWN0QW5kU3Vic2NyaWJlLCB0aGlzIGRvZXNuJ3QgY2xvc2UgYWZ0ZXIgcmVjZWl2aW5nIGEgbWVzc2FnZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY29ubmVjdEFuZFN1YnNjcmliZUNvbnRpbnVvdXM8VD4oXG4gICAgY2hhbm5lbDogc3RyaW5nLFxuICAgIG9uTWVzc2FnZTogKG1lc3NhZ2U6IFQpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICAgIG9uRXJyb3I/OiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBCdWlsZCBzaWduZWQgV2ViU29ja2V0IGNvbm5lY3Rpb25cbiAgICBjb25zdCBbd3NVcmwsIHN1YnByb3RvY29sc10gPSBhd2FpdCB0aGlzLmJ1aWxkU2lnbmVkV2ViU29ja2V0Q29ubmVjdGlvbigpXG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy53cyA9IG5ldyBXZWJTb2NrZXQod3NVcmwsIHN1YnByb3RvY29scylcblxuICAgICAgdGhpcy53cy5vbihcIm9wZW5cIiwgKCkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhcIltBcHBTeW5jXSBXZWJTb2NrZXQgY29ubmVjdGVkXCIpXG4gICAgICAgIC8vIFNlbmQgY29ubmVjdGlvbiBpbml0XG4gICAgICAgIHRoaXMud3M/LnNlbmQoSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiBcImNvbm5lY3Rpb25faW5pdFwiIH0pKVxuICAgICAgfSlcblxuICAgICAgdGhpcy53cy5vbihcIm1lc3NhZ2VcIiwgYXN5bmMgKGRhdGEpID0+IHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IEpTT04ucGFyc2UoZGF0YS50b1N0cmluZygpKVxuXG4gICAgICAgIGlmIChtZXNzYWdlLnR5cGUgPT09IFwiY29ubmVjdGlvbl9hY2tcIikge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiW0FwcFN5bmNdIENvbm5lY3Rpb24gYWNrbm93bGVkZ2VkXCIpXG4gICAgICAgICAgLy8gU3Vic2NyaWJlIHRvIGNoYW5uZWwgd2l0aCBhdXRob3JpemF0aW9uXG4gICAgICAgICAgdGhpcy5jcmVhdGVTdWJzY3JpYmVBdXRob3JpemF0aW9uKGNoYW5uZWwpLnRoZW4oKGF1dGgpID0+IHtcbiAgICAgICAgICAgIHRoaXMud3M/LnNlbmQoXG4gICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInN1YnNjcmliZVwiLFxuICAgICAgICAgICAgICAgIGlkOiBcInN1Yi0xXCIsXG4gICAgICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgICAgICBhdXRob3JpemF0aW9uOiBhdXRoLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9KVxuICAgICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gXCJzdWJzY3JpYmVfc3VjY2Vzc1wiKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYFtBcHBTeW5jXSBTdWJzY3JpYmVkIHRvICR7Y2hhbm5lbH1gKVxuICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gXCJkYXRhXCIgJiYgbWVzc2FnZS5pZCA9PT0gXCJzdWItMVwiKSB7XG4gICAgICAgICAgLy8gUGFyc2UgdGhlIGV2ZW50IGRhdGFcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZXZlbnREYXRhID0gSlNPTi5wYXJzZShtZXNzYWdlLmV2ZW50KSBhcyBUXG4gICAgICAgICAgICBhd2FpdCBvbk1lc3NhZ2UoZXZlbnREYXRhKVxuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIltBcHBTeW5jXSBGYWlsZWQgdG8gcGFyc2UgZXZlbnQgZGF0YTpcIiwgZXJyKVxuICAgICAgICAgICAgb25FcnJvcj8uKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFN0cmluZyhlcnIpKSlcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBcImVycm9yXCIpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW0FwcFN5bmNdIFdlYlNvY2tldCBlcnJvcjpcIiwgbWVzc2FnZSlcbiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihcbiAgICAgICAgICAgIG1lc3NhZ2UuZXJyb3JzXG4gICAgICAgICAgICAgID8ubWFwKChlOiB7IG1lc3NhZ2U6IHN0cmluZyB9KSA9PiBlLm1lc3NhZ2UpXG4gICAgICAgICAgICAgIC5qb2luKFwiLCBcIikgPz8gXCJVbmtub3duIGVycm9yXCIsXG4gICAgICAgICAgKVxuICAgICAgICAgIG9uRXJyb3I/LihlcnJvcilcbiAgICAgICAgICByZWplY3QoZXJyb3IpXG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIHRoaXMud3Mub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJbQXBwU3luY10gV2ViU29ja2V0IGVycm9yOlwiLCBlcnIpXG4gICAgICAgIG9uRXJyb3I/LihlcnIpXG4gICAgICAgIHJlamVjdChlcnIpXG4gICAgICB9KVxuXG4gICAgICB0aGlzLndzLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhcIltBcHBTeW5jXSBXZWJTb2NrZXQgY2xvc2VkXCIpXG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGF1dGhvcml6YXRpb24gaGVhZGVycyBmb3Igc3Vic2NyaWJlIG9wZXJhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjcmVhdGVTdWJzY3JpYmVBdXRob3JpemF0aW9uKFxuICAgIGNoYW5uZWw6IHN0cmluZyxcbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB7XG4gICAgY29uc3QgaHR0cFVybCA9IG5ldyBVUkwodGhpcy5odHRwRW5kcG9pbnQpXG4gICAgY29uc3QgcGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KHsgY2hhbm5lbCB9KVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IG5ldyBIdHRwUmVxdWVzdCh7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgcHJvdG9jb2w6IFwiaHR0cHM6XCIsXG4gICAgICBob3N0bmFtZTogaHR0cFVybC5ob3N0bmFtZSxcbiAgICAgIHBhdGg6IFwiL2V2ZW50XCIsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIGFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIixcbiAgICAgICAgXCJjb250ZW50LWVuY29kaW5nXCI6IFwiYW16LTEuMFwiLFxuICAgICAgICBcImNvbnRlbnQtdHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLThcIixcbiAgICAgICAgaG9zdDogaHR0cFVybC5ob3N0bmFtZSxcbiAgICAgIH0sXG4gICAgICBib2R5OiBwYXlsb2FkLFxuICAgIH0pXG5cbiAgICBjb25zdCBzaWduZXIgPSBuZXcgU2lnbmF0dXJlVjQoe1xuICAgICAgY3JlZGVudGlhbHM6IGRlZmF1bHRQcm92aWRlcigpLFxuICAgICAgcmVnaW9uOiB0aGlzLnJlZ2lvbixcbiAgICAgIHNlcnZpY2U6IFwiYXBwc3luY1wiLFxuICAgICAgc2hhMjU2OiBTaGEyNTYsXG4gICAgfSlcblxuICAgIGNvbnN0IHNpZ25lZFJlcXVlc3QgPSBhd2FpdCBzaWduZXIuc2lnbihyZXF1ZXN0KVxuXG4gICAgY29uc3QgYXV0aDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIGFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIixcbiAgICAgIFwiY29udGVudC1lbmNvZGluZ1wiOiBcImFtei0xLjBcIixcbiAgICAgIFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOFwiLFxuICAgICAgaG9zdDogaHR0cFVybC5ob3N0bmFtZSxcbiAgICAgIFwieC1hbXotZGF0ZVwiOiBzaWduZWRSZXF1ZXN0LmhlYWRlcnNbXCJ4LWFtei1kYXRlXCJdLFxuICAgICAgXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiOiBzaWduZWRSZXF1ZXN0LmhlYWRlcnNbXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiXSxcbiAgICAgIEF1dGhvcml6YXRpb246IHNpZ25lZFJlcXVlc3QuaGVhZGVyc1tcImF1dGhvcml6YXRpb25cIl0sXG4gICAgfVxuXG4gICAgaWYgKHNpZ25lZFJlcXVlc3QuaGVhZGVyc1tcIngtYW16LXNlY3VyaXR5LXRva2VuXCJdKSB7XG4gICAgICBhdXRoW1wieC1hbXotc2VjdXJpdHktdG9rZW5cIl0gPVxuICAgICAgICBzaWduZWRSZXF1ZXN0LmhlYWRlcnNbXCJ4LWFtei1zZWN1cml0eS10b2tlblwiXVxuICAgIH1cblxuICAgIHJldHVybiBhdXRoXG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgc2lnbmVkIFdlYlNvY2tldCBjb25uZWN0aW9uIGluZm8gZm9yIEFwcFN5bmMgRXZlbnRzXG4gICAqIFJldHVybnMgW3VybCwgc3VicHJvdG9jb2xzXSBmb3IgV2ViU29ja2V0IGNvbnN0cnVjdG9yXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJ1aWxkU2lnbmVkV2ViU29ja2V0Q29ubmVjdGlvbigpOiBQcm9taXNlPFtzdHJpbmcsIHN0cmluZ1tdXT4ge1xuICAgIGNvbnN0IHJlYWx0aW1lVXJsID0gbmV3IFVSTCh0aGlzLnJlYWx0aW1lRW5kcG9pbnQpXG4gICAgcmVhbHRpbWVVcmwucGF0aG5hbWUgPSBcIi9ldmVudC9yZWFsdGltZVwiXG4gICAgY29uc3QgaHR0cFVybCA9IG5ldyBVUkwodGhpcy5odHRwRW5kcG9pbnQpXG5cbiAgICAvLyBGb3IgSUFNIGF1dGgsIHNpZ24gYSBQT1NUIHJlcXVlc3QgdG8gdGhlIEhUVFAgZW5kcG9pbnRcbiAgICBjb25zdCByZXF1ZXN0ID0gbmV3IEh0dHBSZXF1ZXN0KHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBwcm90b2NvbDogXCJodHRwczpcIixcbiAgICAgIGhvc3RuYW1lOiBodHRwVXJsLmhvc3RuYW1lLFxuICAgICAgcGF0aDogXCIvZXZlbnRcIixcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYWNjZXB0OiBcImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdFwiLFxuICAgICAgICBcImNvbnRlbnQtZW5jb2RpbmdcIjogXCJhbXotMS4wXCIsXG4gICAgICAgIFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOFwiLFxuICAgICAgICBob3N0OiBodHRwVXJsLmhvc3RuYW1lLFxuICAgICAgfSxcbiAgICAgIGJvZHk6IFwie31cIixcbiAgICB9KVxuXG4gICAgY29uc3Qgc2lnbmVyID0gbmV3IFNpZ25hdHVyZVY0KHtcbiAgICAgIGNyZWRlbnRpYWxzOiBkZWZhdWx0UHJvdmlkZXIoKSxcbiAgICAgIHJlZ2lvbjogdGhpcy5yZWdpb24sXG4gICAgICBzZXJ2aWNlOiBcImFwcHN5bmNcIixcbiAgICAgIHNoYTI1NjogU2hhMjU2LFxuICAgIH0pXG5cbiAgICBjb25zdCBzaWduZWRSZXF1ZXN0ID0gYXdhaXQgc2lnbmVyLnNpZ24ocmVxdWVzdClcblxuICAgIC8vIEJ1aWxkIGhlYWRlciBwYXlsb2FkIGZvciBzdWJwcm90b2NvbCAtIGluY2x1ZGUgYWxsIHNpZ25lZCBoZWFkZXJzXG4gICAgY29uc3QgaGVhZGVyUGF5bG9hZDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIGFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIixcbiAgICAgIFwiY29udGVudC1lbmNvZGluZ1wiOiBcImFtei0xLjBcIixcbiAgICAgIFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOFwiLFxuICAgICAgaG9zdDogaHR0cFVybC5ob3N0bmFtZSxcbiAgICAgIFwieC1hbXotZGF0ZVwiOiBzaWduZWRSZXF1ZXN0LmhlYWRlcnNbXCJ4LWFtei1kYXRlXCJdLFxuICAgICAgXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiOiBzaWduZWRSZXF1ZXN0LmhlYWRlcnNbXCJ4LWFtei1jb250ZW50LXNoYTI1NlwiXSxcbiAgICAgIEF1dGhvcml6YXRpb246IHNpZ25lZFJlcXVlc3QuaGVhZGVyc1tcImF1dGhvcml6YXRpb25cIl0sXG4gICAgfVxuXG4gICAgLy8gQWRkIHNlc3Npb24gdG9rZW4gaWYgcHJlc2VudFxuICAgIGlmIChzaWduZWRSZXF1ZXN0LmhlYWRlcnNbXCJ4LWFtei1zZWN1cml0eS10b2tlblwiXSkge1xuICAgICAgaGVhZGVyUGF5bG9hZFtcIngtYW16LXNlY3VyaXR5LXRva2VuXCJdID1cbiAgICAgICAgc2lnbmVkUmVxdWVzdC5oZWFkZXJzW1wieC1hbXotc2VjdXJpdHktdG9rZW5cIl1cbiAgICB9XG5cbiAgICAvLyBCYXNlNjR1cmwgZW5jb2RlIChubyBwYWRkaW5nLCBVUkwtc2FmZSlcbiAgICBjb25zdCBlbmNvZGVkSGVhZGVyID0gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoaGVhZGVyUGF5bG9hZCkpXG4gICAgICAudG9TdHJpbmcoXCJiYXNlNjRcIilcbiAgICAgIC5yZXBsYWNlKC9cXCsvZywgXCItXCIpXG4gICAgICAucmVwbGFjZSgvXFwvL2csIFwiX1wiKVxuICAgICAgLnJlcGxhY2UoLz0rJC8sIFwiXCIpXG5cbiAgICAvLyBBdXRoIGlzIHBhc3NlZCBhcyBoZWFkZXIte2Jhc2U2NHVybH0gc3VicHJvdG9jb2xcbiAgICBjb25zdCBhdXRoU3VicHJvdG9jb2wgPSBgaGVhZGVyLSR7ZW5jb2RlZEhlYWRlcn1gXG5cbiAgICByZXR1cm4gW3JlYWx0aW1lVXJsLnRvU3RyaW5nKCksIFtcImF3cy1hcHBzeW5jLWV2ZW50LXdzXCIsIGF1dGhTdWJwcm90b2NvbF1dXG4gIH1cblxuICAvKipcbiAgICogQ2xvc2UgdGhlIFdlYlNvY2tldCBjb25uZWN0aW9uXG4gICAqL1xuICBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy53cykge1xuICAgICAgdGhpcy53cy5jbG9zZSgpXG4gICAgICB0aGlzLndzID0gbnVsbFxuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Bridge Lambda handler that forwards invocations to the local daemon via AppSync Events.
3
+ *
4
+ * This handler:
5
+ * 1. Receives Lambda invocations from AWS
6
+ * 2. Publishes the invocation to AppSync Events channel
7
+ * 3. Subscribes to response channel
8
+ * 4. Waits for the daemon to process and respond
9
+ * 5. Returns the response or throws an error
10
+ *
11
+ * AppSync endpoints are read from SSM Parameter Store at runtime.
12
+ */
13
+ import type { Context } from "aws-lambda";
14
+ /**
15
+ * Main Lambda handler - forwards all invocations to the local daemon
16
+ */
17
+ export declare function handler(event: unknown, context: Context): Promise<unknown>;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Bridge Lambda handler that forwards invocations to the local daemon via AppSync Events.
3
+ *
4
+ * This handler:
5
+ * 1. Receives Lambda invocations from AWS
6
+ * 2. Publishes the invocation to AppSync Events channel
7
+ * 3. Subscribes to response channel
8
+ * 4. Waits for the daemon to process and respond
9
+ * 5. Returns the response or throws an error
10
+ *
11
+ * AppSync endpoints are read from SSM Parameter Store at runtime.
12
+ */
13
+ import { buildChannelName, filterEnvVars, } from "../../shared/types.js";
14
+ import { AppSyncEventsClient } from "./appsync-client.js";
15
+ import { getAppSyncEndpoints } from "./ssm-config.js";
16
+ // Timeout waiting for daemon response (ms)
17
+ const RESPONSE_TIMEOUT_MS = 290_000; // 4:50 to leave buffer for 5 min Lambda timeout
18
+ /**
19
+ * Main Lambda handler - forwards all invocations to the local daemon
20
+ */
21
+ export async function handler(event, context) {
22
+ const functionName = context.functionName;
23
+ const requestId = context.awsRequestId;
24
+ console.log(`[Bridge] Processing invocation for ${functionName}`);
25
+ console.log(`[Bridge] Request ID: ${requestId}`);
26
+ // Get AppSync endpoints from SSM
27
+ const { httpEndpoint, realtimeEndpoint } = await getAppSyncEndpoints();
28
+ // Create AppSync client
29
+ const client = new AppSyncEventsClient({
30
+ httpEndpoint,
31
+ realtimeEndpoint,
32
+ });
33
+ // Build channel names
34
+ const invocationChannel = buildChannelName.invocation(functionName);
35
+ const responseChannel = buildChannelName.response(functionName);
36
+ try {
37
+ // Create the invocation message with filtered env vars
38
+ const invocationMessage = {
39
+ type: "invocation",
40
+ requestId,
41
+ event,
42
+ context: {
43
+ functionName: context.functionName,
44
+ functionVersion: context.functionVersion,
45
+ invokedFunctionArn: context.invokedFunctionArn,
46
+ memoryLimitInMB: context.memoryLimitInMB,
47
+ awsRequestId: context.awsRequestId,
48
+ logGroupName: context.logGroupName,
49
+ logStreamName: context.logStreamName,
50
+ getRemainingTimeInMillis: context.getRemainingTimeInMillis(),
51
+ },
52
+ env: filterEnvVars(process.env),
53
+ };
54
+ // Subscribe to response channel first, then publish invocation
55
+ const response = await client.publishAndWaitForResponse({
56
+ publishChannel: invocationChannel,
57
+ subscribeChannel: responseChannel,
58
+ message: invocationMessage,
59
+ timeoutMs: RESPONSE_TIMEOUT_MS,
60
+ matchResponse: (msg) => msg.requestId === requestId,
61
+ });
62
+ console.log(`[Bridge] Received response for ${requestId}`);
63
+ // Check for error response
64
+ if (response.error) {
65
+ const error = new Error(response.error.errorMessage);
66
+ error.name = response.error.errorType;
67
+ if (response.error.stackTrace) {
68
+ error.stack = response.error.stackTrace.join("\n");
69
+ }
70
+ throw error;
71
+ }
72
+ return response.result;
73
+ }
74
+ finally {
75
+ // Clean up client connection
76
+ await client.close();
77
+ }
78
+ }
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mdW5jdGlvbnMvYnJpZGdlL2hhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUFHSCxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLGFBQWEsR0FHZCxNQUFNLHVCQUF1QixDQUFBO0FBQzlCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBQ3pELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBRXJELDJDQUEyQztBQUMzQyxNQUFNLG1CQUFtQixHQUFHLE9BQU8sQ0FBQSxDQUFDLGdEQUFnRDtBQUVwRjs7R0FFRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsT0FBTyxDQUMzQixLQUFjLEVBQ2QsT0FBZ0I7SUFFaEIsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQTtJQUN6QyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFBO0lBRXRDLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLFlBQVksRUFBRSxDQUFDLENBQUE7SUFDakUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUVoRCxpQ0FBaUM7SUFDakMsTUFBTSxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLE1BQU0sbUJBQW1CLEVBQUUsQ0FBQTtJQUV0RSx3QkFBd0I7SUFDeEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxtQkFBbUIsQ0FBQztRQUNyQyxZQUFZO1FBQ1osZ0JBQWdCO0tBQ2pCLENBQUMsQ0FBQTtJQUVGLHNCQUFzQjtJQUN0QixNQUFNLGlCQUFpQixHQUFHLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUNuRSxNQUFNLGVBQWUsR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUE7SUFFL0QsSUFBSSxDQUFDO1FBQ0gsdURBQXVEO1FBQ3ZELE1BQU0saUJBQWlCLEdBQXNCO1lBQzNDLElBQUksRUFBRSxZQUFZO1lBQ2xCLFNBQVM7WUFDVCxLQUFLO1lBQ0wsT0FBTyxFQUFFO2dCQUNQLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtnQkFDbEMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlO2dCQUN4QyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCO2dCQUM5QyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7Z0JBQ3hDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtnQkFDbEMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO2dCQUNsQyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWE7Z0JBQ3BDLHdCQUF3QixFQUFFLE9BQU8sQ0FBQyx3QkFBd0IsRUFBRTthQUM3RDtZQUNELEdBQUcsRUFBRSxhQUFhLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztTQUNoQyxDQUFBO1FBRUQsK0RBQStEO1FBQy9ELE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLHlCQUF5QixDQUFrQjtZQUN2RSxjQUFjLEVBQUUsaUJBQWlCO1lBQ2pDLGdCQUFnQixFQUFFLGVBQWU7WUFDakMsT0FBTyxFQUFFLGlCQUFpQjtZQUMxQixTQUFTLEVBQUUsbUJBQW1CO1lBQzlCLGFBQWEsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFNBQVMsS0FBSyxTQUFTO1NBQ3BELENBQUMsQ0FBQTtRQUVGLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0NBQWtDLFNBQVMsRUFBRSxDQUFDLENBQUE7UUFFMUQsMkJBQTJCO1FBQzNCLElBQUksUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ25CLE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUE7WUFDcEQsS0FBSyxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQTtZQUNyQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQzlCLEtBQUssQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1lBQ3BELENBQUM7WUFDRCxNQUFNLEtBQUssQ0FBQTtRQUNiLENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUE7SUFDeEIsQ0FBQztZQUFTLENBQUM7UUFDVCw2QkFBNkI7UUFDN0IsTUFBTSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUE7SUFDdEIsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEJyaWRnZSBMYW1iZGEgaGFuZGxlciB0aGF0IGZvcndhcmRzIGludm9jYXRpb25zIHRvIHRoZSBsb2NhbCBkYWVtb24gdmlhIEFwcFN5bmMgRXZlbnRzLlxuICpcbiAqIFRoaXMgaGFuZGxlcjpcbiAqIDEuIFJlY2VpdmVzIExhbWJkYSBpbnZvY2F0aW9ucyBmcm9tIEFXU1xuICogMi4gUHVibGlzaGVzIHRoZSBpbnZvY2F0aW9uIHRvIEFwcFN5bmMgRXZlbnRzIGNoYW5uZWxcbiAqIDMuIFN1YnNjcmliZXMgdG8gcmVzcG9uc2UgY2hhbm5lbFxuICogNC4gV2FpdHMgZm9yIHRoZSBkYWVtb24gdG8gcHJvY2VzcyBhbmQgcmVzcG9uZFxuICogNS4gUmV0dXJucyB0aGUgcmVzcG9uc2Ugb3IgdGhyb3dzIGFuIGVycm9yXG4gKlxuICogQXBwU3luYyBlbmRwb2ludHMgYXJlIHJlYWQgZnJvbSBTU00gUGFyYW1ldGVyIFN0b3JlIGF0IHJ1bnRpbWUuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBDb250ZXh0IH0gZnJvbSBcImF3cy1sYW1iZGFcIlxuaW1wb3J0IHtcbiAgYnVpbGRDaGFubmVsTmFtZSxcbiAgZmlsdGVyRW52VmFycyxcbiAgdHlwZSBJbnZvY2F0aW9uTWVzc2FnZSxcbiAgdHlwZSBSZXNwb25zZU1lc3NhZ2UsXG59IGZyb20gXCIuLi8uLi9zaGFyZWQvdHlwZXMuanNcIlxuaW1wb3J0IHsgQXBwU3luY0V2ZW50c0NsaWVudCB9IGZyb20gXCIuL2FwcHN5bmMtY2xpZW50LmpzXCJcbmltcG9ydCB7IGdldEFwcFN5bmNFbmRwb2ludHMgfSBmcm9tIFwiLi9zc20tY29uZmlnLmpzXCJcblxuLy8gVGltZW91dCB3YWl0aW5nIGZvciBkYWVtb24gcmVzcG9uc2UgKG1zKVxuY29uc3QgUkVTUE9OU0VfVElNRU9VVF9NUyA9IDI5MF8wMDAgLy8gNDo1MCB0byBsZWF2ZSBidWZmZXIgZm9yIDUgbWluIExhbWJkYSB0aW1lb3V0XG5cbi8qKlxuICogTWFpbiBMYW1iZGEgaGFuZGxlciAtIGZvcndhcmRzIGFsbCBpbnZvY2F0aW9ucyB0byB0aGUgbG9jYWwgZGFlbW9uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKFxuICBldmVudDogdW5rbm93bixcbiAgY29udGV4dDogQ29udGV4dCxcbik6IFByb21pc2U8dW5rbm93bj4ge1xuICBjb25zdCBmdW5jdGlvbk5hbWUgPSBjb250ZXh0LmZ1bmN0aW9uTmFtZVxuICBjb25zdCByZXF1ZXN0SWQgPSBjb250ZXh0LmF3c1JlcXVlc3RJZFxuXG4gIGNvbnNvbGUubG9nKGBbQnJpZGdlXSBQcm9jZXNzaW5nIGludm9jYXRpb24gZm9yICR7ZnVuY3Rpb25OYW1lfWApXG4gIGNvbnNvbGUubG9nKGBbQnJpZGdlXSBSZXF1ZXN0IElEOiAke3JlcXVlc3RJZH1gKVxuXG4gIC8vIEdldCBBcHBTeW5jIGVuZHBvaW50cyBmcm9tIFNTTVxuICBjb25zdCB7IGh0dHBFbmRwb2ludCwgcmVhbHRpbWVFbmRwb2ludCB9ID0gYXdhaXQgZ2V0QXBwU3luY0VuZHBvaW50cygpXG5cbiAgLy8gQ3JlYXRlIEFwcFN5bmMgY2xpZW50XG4gIGNvbnN0IGNsaWVudCA9IG5ldyBBcHBTeW5jRXZlbnRzQ2xpZW50KHtcbiAgICBodHRwRW5kcG9pbnQsXG4gICAgcmVhbHRpbWVFbmRwb2ludCxcbiAgfSlcblxuICAvLyBCdWlsZCBjaGFubmVsIG5hbWVzXG4gIGNvbnN0IGludm9jYXRpb25DaGFubmVsID0gYnVpbGRDaGFubmVsTmFtZS5pbnZvY2F0aW9uKGZ1bmN0aW9uTmFtZSlcbiAgY29uc3QgcmVzcG9uc2VDaGFubmVsID0gYnVpbGRDaGFubmVsTmFtZS5yZXNwb25zZShmdW5jdGlvbk5hbWUpXG5cbiAgdHJ5IHtcbiAgICAvLyBDcmVhdGUgdGhlIGludm9jYXRpb24gbWVzc2FnZSB3aXRoIGZpbHRlcmVkIGVudiB2YXJzXG4gICAgY29uc3QgaW52b2NhdGlvbk1lc3NhZ2U6IEludm9jYXRpb25NZXNzYWdlID0ge1xuICAgICAgdHlwZTogXCJpbnZvY2F0aW9uXCIsXG4gICAgICByZXF1ZXN0SWQsXG4gICAgICBldmVudCxcbiAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgZnVuY3Rpb25OYW1lOiBjb250ZXh0LmZ1bmN0aW9uTmFtZSxcbiAgICAgICAgZnVuY3Rpb25WZXJzaW9uOiBjb250ZXh0LmZ1bmN0aW9uVmVyc2lvbixcbiAgICAgICAgaW52b2tlZEZ1bmN0aW9uQXJuOiBjb250ZXh0Lmludm9rZWRGdW5jdGlvbkFybixcbiAgICAgICAgbWVtb3J5TGltaXRJbk1COiBjb250ZXh0Lm1lbW9yeUxpbWl0SW5NQixcbiAgICAgICAgYXdzUmVxdWVzdElkOiBjb250ZXh0LmF3c1JlcXVlc3RJZCxcbiAgICAgICAgbG9nR3JvdXBOYW1lOiBjb250ZXh0LmxvZ0dyb3VwTmFtZSxcbiAgICAgICAgbG9nU3RyZWFtTmFtZTogY29udGV4dC5sb2dTdHJlYW1OYW1lLFxuICAgICAgICBnZXRSZW1haW5pbmdUaW1lSW5NaWxsaXM6IGNvbnRleHQuZ2V0UmVtYWluaW5nVGltZUluTWlsbGlzKCksXG4gICAgICB9LFxuICAgICAgZW52OiBmaWx0ZXJFbnZWYXJzKHByb2Nlc3MuZW52KSxcbiAgICB9XG5cbiAgICAvLyBTdWJzY3JpYmUgdG8gcmVzcG9uc2UgY2hhbm5lbCBmaXJzdCwgdGhlbiBwdWJsaXNoIGludm9jYXRpb25cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5wdWJsaXNoQW5kV2FpdEZvclJlc3BvbnNlPFJlc3BvbnNlTWVzc2FnZT4oe1xuICAgICAgcHVibGlzaENoYW5uZWw6IGludm9jYXRpb25DaGFubmVsLFxuICAgICAgc3Vic2NyaWJlQ2hhbm5lbDogcmVzcG9uc2VDaGFubmVsLFxuICAgICAgbWVzc2FnZTogaW52b2NhdGlvbk1lc3NhZ2UsXG4gICAgICB0aW1lb3V0TXM6IFJFU1BPTlNFX1RJTUVPVVRfTVMsXG4gICAgICBtYXRjaFJlc3BvbnNlOiAobXNnKSA9PiBtc2cucmVxdWVzdElkID09PSByZXF1ZXN0SWQsXG4gICAgfSlcblxuICAgIGNvbnNvbGUubG9nKGBbQnJpZGdlXSBSZWNlaXZlZCByZXNwb25zZSBmb3IgJHtyZXF1ZXN0SWR9YClcblxuICAgIC8vIENoZWNrIGZvciBlcnJvciByZXNwb25zZVxuICAgIGlmIChyZXNwb25zZS5lcnJvcikge1xuICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IocmVzcG9uc2UuZXJyb3IuZXJyb3JNZXNzYWdlKVxuICAgICAgZXJyb3IubmFtZSA9IHJlc3BvbnNlLmVycm9yLmVycm9yVHlwZVxuICAgICAgaWYgKHJlc3BvbnNlLmVycm9yLnN0YWNrVHJhY2UpIHtcbiAgICAgICAgZXJyb3Iuc3RhY2sgPSByZXNwb25zZS5lcnJvci5zdGFja1RyYWNlLmpvaW4oXCJcXG5cIilcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlLnJlc3VsdFxuICB9IGZpbmFsbHkge1xuICAgIC8vIENsZWFuIHVwIGNsaWVudCBjb25uZWN0aW9uXG4gICAgYXdhaXQgY2xpZW50LmNsb3NlKClcbiAgfVxufVxuIl19
@@ -0,0 +1,19 @@
1
+ /**
2
+ * SSM parameter reader for AppSync endpoints.
3
+ *
4
+ * Reads the AppSync HTTP and realtime endpoints from SSM Parameter Store
5
+ * and caches them to avoid repeated SSM calls during Lambda warm starts.
6
+ */
7
+ export interface AppSyncEndpoints {
8
+ httpEndpoint: string;
9
+ realtimeEndpoint: string;
10
+ }
11
+ /**
12
+ * Get AppSync endpoints from SSM Parameter Store.
13
+ * Results are cached after the first call.
14
+ */
15
+ export declare function getAppSyncEndpoints(): Promise<AppSyncEndpoints>;
16
+ /**
17
+ * Clear the cached endpoints. Useful for testing.
18
+ */
19
+ export declare function clearEndpointCache(): void;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * SSM parameter reader for AppSync endpoints.
3
+ *
4
+ * Reads the AppSync HTTP and realtime endpoints from SSM Parameter Store
5
+ * and caches them to avoid repeated SSM calls during Lambda warm starts.
6
+ */
7
+ import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
8
+ import { SSM_BASE_PATH } from "../../shared/types.js";
9
+ // Cache endpoints to avoid repeated SSM calls
10
+ let cachedEndpoints = null;
11
+ /**
12
+ * Get AppSync endpoints from SSM Parameter Store.
13
+ * Results are cached after the first call.
14
+ */
15
+ export async function getAppSyncEndpoints() {
16
+ if (cachedEndpoints)
17
+ return cachedEndpoints;
18
+ const client = new SSMClient({});
19
+ const qualifier = process.env.CDK_BOOTSTRAP_QUALIFIER ?? "hnb659fds";
20
+ const basePath = `${SSM_BASE_PATH}/${qualifier}`;
21
+ const [httpResponse, realtimeResponse] = await Promise.all([
22
+ client.send(new GetParameterCommand({
23
+ Name: `${basePath}/http-endpoint`,
24
+ })),
25
+ client.send(new GetParameterCommand({
26
+ Name: `${basePath}/realtime-endpoint`,
27
+ })),
28
+ ]);
29
+ if (!httpResponse.Parameter?.Value || !realtimeResponse.Parameter?.Value) {
30
+ throw new Error(`[LiveLambda] SSM parameters not found at ${basePath}. ` +
31
+ "Ensure the bootstrap stack is deployed.");
32
+ }
33
+ cachedEndpoints = {
34
+ httpEndpoint: httpResponse.Parameter.Value,
35
+ realtimeEndpoint: realtimeResponse.Parameter.Value,
36
+ };
37
+ return cachedEndpoints;
38
+ }
39
+ /**
40
+ * Clear the cached endpoints. Useful for testing.
41
+ */
42
+ export function clearEndpointCache() {
43
+ cachedEndpoints = null;
44
+ }
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3NtLWNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mdW5jdGlvbnMvYnJpZGdlL3NzbS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHVCQUF1QixDQUFBO0FBT3JELDhDQUE4QztBQUM5QyxJQUFJLGVBQWUsR0FBNEIsSUFBSSxDQUFBO0FBRW5EOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CO0lBQ3ZDLElBQUksZUFBZTtRQUFFLE9BQU8sZUFBZSxDQUFBO0lBRTNDLE1BQU0sTUFBTSxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ2hDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLElBQUksV0FBVyxDQUFBO0lBQ3BFLE1BQU0sUUFBUSxHQUFHLEdBQUcsYUFBYSxJQUFJLFNBQVMsRUFBRSxDQUFBO0lBRWhELE1BQU0sQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7UUFDekQsTUFBTSxDQUFDLElBQUksQ0FDVCxJQUFJLG1CQUFtQixDQUFDO1lBQ3RCLElBQUksRUFBRSxHQUFHLFFBQVEsZ0JBQWdCO1NBQ2xDLENBQUMsQ0FDSDtRQUNELE1BQU0sQ0FBQyxJQUFJLENBQ1QsSUFBSSxtQkFBbUIsQ0FBQztZQUN0QixJQUFJLEVBQUUsR0FBRyxRQUFRLG9CQUFvQjtTQUN0QyxDQUFDLENBQ0g7S0FDRixDQUFDLENBQUE7SUFFRixJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxLQUFLLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDekUsTUFBTSxJQUFJLEtBQUssQ0FDYiw0Q0FBNEMsUUFBUSxJQUFJO1lBQ3RELHlDQUF5QyxDQUM1QyxDQUFBO0lBQ0gsQ0FBQztJQUVELGVBQWUsR0FBRztRQUNoQixZQUFZLEVBQUUsWUFBWSxDQUFDLFNBQVMsQ0FBQyxLQUFLO1FBQzFDLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxLQUFLO0tBQ25ELENBQUE7SUFFRCxPQUFPLGVBQWUsQ0FBQTtBQUN4QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCO0lBQ2hDLGVBQWUsR0FBRyxJQUFJLENBQUE7QUFDeEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU1NNIHBhcmFtZXRlciByZWFkZXIgZm9yIEFwcFN5bmMgZW5kcG9pbnRzLlxuICpcbiAqIFJlYWRzIHRoZSBBcHBTeW5jIEhUVFAgYW5kIHJlYWx0aW1lIGVuZHBvaW50cyBmcm9tIFNTTSBQYXJhbWV0ZXIgU3RvcmVcbiAqIGFuZCBjYWNoZXMgdGhlbSB0byBhdm9pZCByZXBlYXRlZCBTU00gY2FsbHMgZHVyaW5nIExhbWJkYSB3YXJtIHN0YXJ0cy5cbiAqL1xuXG5pbXBvcnQgeyBHZXRQYXJhbWV0ZXJDb21tYW5kLCBTU01DbGllbnQgfSBmcm9tIFwiQGF3cy1zZGsvY2xpZW50LXNzbVwiXG5pbXBvcnQgeyBTU01fQkFTRV9QQVRIIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC90eXBlcy5qc1wiXG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwU3luY0VuZHBvaW50cyB7XG4gIGh0dHBFbmRwb2ludDogc3RyaW5nXG4gIHJlYWx0aW1lRW5kcG9pbnQ6IHN0cmluZ1xufVxuXG4vLyBDYWNoZSBlbmRwb2ludHMgdG8gYXZvaWQgcmVwZWF0ZWQgU1NNIGNhbGxzXG5sZXQgY2FjaGVkRW5kcG9pbnRzOiBBcHBTeW5jRW5kcG9pbnRzIHwgbnVsbCA9IG51bGxcblxuLyoqXG4gKiBHZXQgQXBwU3luYyBlbmRwb2ludHMgZnJvbSBTU00gUGFyYW1ldGVyIFN0b3JlLlxuICogUmVzdWx0cyBhcmUgY2FjaGVkIGFmdGVyIHRoZSBmaXJzdCBjYWxsLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QXBwU3luY0VuZHBvaW50cygpOiBQcm9taXNlPEFwcFN5bmNFbmRwb2ludHM+IHtcbiAgaWYgKGNhY2hlZEVuZHBvaW50cykgcmV0dXJuIGNhY2hlZEVuZHBvaW50c1xuXG4gIGNvbnN0IGNsaWVudCA9IG5ldyBTU01DbGllbnQoe30pXG4gIGNvbnN0IHF1YWxpZmllciA9IHByb2Nlc3MuZW52LkNES19CT09UU1RSQVBfUVVBTElGSUVSID8/IFwiaG5iNjU5ZmRzXCJcbiAgY29uc3QgYmFzZVBhdGggPSBgJHtTU01fQkFTRV9QQVRIfS8ke3F1YWxpZmllcn1gXG5cbiAgY29uc3QgW2h0dHBSZXNwb25zZSwgcmVhbHRpbWVSZXNwb25zZV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgY2xpZW50LnNlbmQoXG4gICAgICBuZXcgR2V0UGFyYW1ldGVyQ29tbWFuZCh7XG4gICAgICAgIE5hbWU6IGAke2Jhc2VQYXRofS9odHRwLWVuZHBvaW50YCxcbiAgICAgIH0pLFxuICAgICksXG4gICAgY2xpZW50LnNlbmQoXG4gICAgICBuZXcgR2V0UGFyYW1ldGVyQ29tbWFuZCh7XG4gICAgICAgIE5hbWU6IGAke2Jhc2VQYXRofS9yZWFsdGltZS1lbmRwb2ludGAsXG4gICAgICB9KSxcbiAgICApLFxuICBdKVxuXG4gIGlmICghaHR0cFJlc3BvbnNlLlBhcmFtZXRlcj8uVmFsdWUgfHwgIXJlYWx0aW1lUmVzcG9uc2UuUGFyYW1ldGVyPy5WYWx1ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBbTGl2ZUxhbWJkYV0gU1NNIHBhcmFtZXRlcnMgbm90IGZvdW5kIGF0ICR7YmFzZVBhdGh9LiBgICtcbiAgICAgICAgXCJFbnN1cmUgdGhlIGJvb3RzdHJhcCBzdGFjayBpcyBkZXBsb3llZC5cIixcbiAgICApXG4gIH1cblxuICBjYWNoZWRFbmRwb2ludHMgPSB7XG4gICAgaHR0cEVuZHBvaW50OiBodHRwUmVzcG9uc2UuUGFyYW1ldGVyLlZhbHVlLFxuICAgIHJlYWx0aW1lRW5kcG9pbnQ6IHJlYWx0aW1lUmVzcG9uc2UuUGFyYW1ldGVyLlZhbHVlLFxuICB9XG5cbiAgcmV0dXJuIGNhY2hlZEVuZHBvaW50c1xufVxuXG4vKipcbiAqIENsZWFyIHRoZSBjYWNoZWQgZW5kcG9pbnRzLiBVc2VmdWwgZm9yIHRlc3RpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhckVuZHBvaW50Q2FjaGUoKTogdm9pZCB7XG4gIGNhY2hlZEVuZHBvaW50cyA9IG51bGxcbn1cbiJdfQ==
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Custom resource handler that builds and uploads the bridge Lambda code.
3
+ *
4
+ * This handler:
5
+ * 1. Receives the bridge source code (base64 encoded) and AppSync endpoints
6
+ * 2. Replaces endpoint placeholders with actual values
7
+ * 3. Creates a zip file with the code
8
+ * 4. Uploads the zip to S3
9
+ * 5. Returns the S3 location for Lambda functions to use
10
+ */
11
+ import type { CloudFormationCustomResourceEvent, CloudFormationCustomResourceResponse } from "aws-lambda";
12
+ export declare function handler(event: CloudFormationCustomResourceEvent): Promise<CloudFormationCustomResourceResponse>;