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,338 @@
1
+ import { execSync } from "node:child_process";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import * as cdk from "aws-cdk-lib";
6
+ import * as appsync from "aws-cdk-lib/aws-appsync";
7
+ import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets";
8
+ import * as iam from "aws-cdk-lib/aws-iam";
9
+ import * as lambda from "aws-cdk-lib/aws-lambda";
10
+ import * as logs from "aws-cdk-lib/aws-logs";
11
+ import * as s3 from "aws-cdk-lib/aws-s3";
12
+ import * as ssm from "aws-cdk-lib/aws-ssm";
13
+ import * as cr from "aws-cdk-lib/custom-resources";
14
+ import { BOOTSTRAP_VERSION, SSM_BASE_PATH } from "../shared/types.js";
15
+ // ESM equivalent of __dirname
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+ /**
19
+ * Bootstrap stack that creates the shared AppSync Events API infrastructure
20
+ * for live lambda debugging. This stack should be deployed once per account/region.
21
+ */
22
+ export class CdkLocalLambdaBootstrapStack extends cdk.Stack {
23
+ /**
24
+ * The AppSync Events API for WebSocket communication
25
+ */
26
+ api;
27
+ /**
28
+ * The channel namespace for live debugging channels
29
+ */
30
+ channelNamespace;
31
+ /**
32
+ * The HTTP endpoint for publishing events
33
+ */
34
+ httpEndpoint;
35
+ /**
36
+ * The WebSocket endpoint for real-time subscriptions
37
+ */
38
+ realtimeEndpoint;
39
+ /**
40
+ * IAM role for publishing to the Events API
41
+ */
42
+ publishRole;
43
+ /**
44
+ * S3 bucket for storing the bridge Lambda code
45
+ */
46
+ bridgeBucket;
47
+ constructor(scope, id, props) {
48
+ super(scope, id, props);
49
+ const apiName = props?.apiName ?? "LiveLambdaEventsApi";
50
+ // Create S3 bucket for bridge code
51
+ this.bridgeBucket = new s3.Bucket(this, "BridgeBucket", {
52
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
53
+ autoDeleteObjects: true,
54
+ blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
55
+ });
56
+ // Create AppSync Events API with IAM authentication
57
+ this.api = new appsync.CfnApi(this, "EventsApi", {
58
+ name: apiName,
59
+ eventConfig: {
60
+ authProviders: [
61
+ {
62
+ authType: "AWS_IAM",
63
+ },
64
+ ],
65
+ connectionAuthModes: [
66
+ {
67
+ authType: "AWS_IAM",
68
+ },
69
+ ],
70
+ defaultPublishAuthModes: [
71
+ {
72
+ authType: "AWS_IAM",
73
+ },
74
+ ],
75
+ defaultSubscribeAuthModes: [
76
+ {
77
+ authType: "AWS_IAM",
78
+ },
79
+ ],
80
+ },
81
+ });
82
+ // Create channel namespace for live debugging
83
+ // Channels will be: /live/{stackName}/{functionId}/in and /live/{stackName}/{functionId}/out
84
+ this.channelNamespace = new appsync.CfnChannelNamespace(this, "LiveNamespace", {
85
+ apiId: this.api.attrApiId,
86
+ name: "live",
87
+ });
88
+ // Store endpoints - using getAtt since attrDns is typed as IResolvable
89
+ // Prepend protocols since AppSync only returns hostnames
90
+ this.httpEndpoint = cdk.Fn.join("", [
91
+ "https://",
92
+ cdk.Token.asString(this.api.getAtt("Dns.Http")),
93
+ ]);
94
+ this.realtimeEndpoint = cdk.Fn.join("", [
95
+ "wss://",
96
+ cdk.Token.asString(this.api.getAtt("Dns.Realtime")),
97
+ ]);
98
+ // Create IAM role for Lambda functions to publish/subscribe
99
+ this.publishRole = new iam.Role(this, "PublishRole", {
100
+ assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
101
+ description: "Role for Lambda functions to publish/subscribe to Live Lambda Events API",
102
+ });
103
+ // Grant permissions to publish and subscribe to the Events API
104
+ this.publishRole.addToPolicy(new iam.PolicyStatement({
105
+ effect: iam.Effect.ALLOW,
106
+ actions: [
107
+ "appsync:EventConnect",
108
+ "appsync:EventPublish",
109
+ "appsync:EventSubscribe",
110
+ ],
111
+ resources: [`${this.api.attrApiArn}/*`, this.api.attrApiArn],
112
+ }));
113
+ // Create SSM parameters for the endpoints
114
+ // These are used by the live-lambda-aspect to configure Lambda functions
115
+ // Use the CDK bootstrap qualifier for proper scoping
116
+ const bootstrapQualifier = this.node.tryGetContext("@aws-cdk/core:bootstrapQualifier") || "hnb659fds";
117
+ const ssmBasePath = `${SSM_BASE_PATH}/${bootstrapQualifier}`;
118
+ new ssm.StringParameter(this, "HttpEndpointParam", {
119
+ parameterName: `${ssmBasePath}/http-endpoint`,
120
+ stringValue: this.httpEndpoint,
121
+ description: "AppSync Events HTTP endpoint for Live Lambda",
122
+ });
123
+ new ssm.StringParameter(this, "RealtimeEndpointParam", {
124
+ parameterName: `${ssmBasePath}/realtime-endpoint`,
125
+ stringValue: this.realtimeEndpoint,
126
+ description: "AppSync Events WebSocket endpoint for Live Lambda",
127
+ });
128
+ new ssm.StringParameter(this, "ApiArnParam", {
129
+ parameterName: `${ssmBasePath}/api-arn`,
130
+ stringValue: this.api.attrApiArn,
131
+ description: "AppSync Events API ARN for Live Lambda",
132
+ });
133
+ new ssm.StringParameter(this, "ApiIdParam", {
134
+ parameterName: `${ssmBasePath}/api-id`,
135
+ stringValue: this.api.attrApiId,
136
+ description: "AppSync Events API ID for Live Lambda",
137
+ });
138
+ // Build bridge handler and upload to S3
139
+ const { bucketName, s3Key, bridgeSource } = this.buildAndUploadBridge();
140
+ const bridgeS3Location = { bucketName, s3Key };
141
+ // Store bridge S3 location in SSM
142
+ new ssm.StringParameter(this, "BridgeBucketParam", {
143
+ parameterName: `${ssmBasePath}/bridge-bucket`,
144
+ stringValue: bridgeS3Location.bucketName,
145
+ description: "S3 bucket containing Live Lambda bridge code",
146
+ });
147
+ new ssm.StringParameter(this, "BridgeKeyParam", {
148
+ parameterName: `${ssmBasePath}/bridge-key`,
149
+ stringValue: bridgeS3Location.s3Key,
150
+ description: "S3 key for Live Lambda bridge code",
151
+ });
152
+ // Build and store Docker bridge images for DockerImageFunction support
153
+ const dockerBridgeImages = this.buildDockerBridgeImages(bridgeSource);
154
+ new ssm.StringParameter(this, "BridgeImageArm64Param", {
155
+ parameterName: `${ssmBasePath}/bridge-image-arm64`,
156
+ stringValue: dockerBridgeImages.arm64ImageUri,
157
+ description: "ECR image URI for ARM64 bridge Docker image",
158
+ });
159
+ new ssm.StringParameter(this, "BridgeImageX86Param", {
160
+ parameterName: `${ssmBasePath}/bridge-image-x86_64`,
161
+ stringValue: dockerBridgeImages.x86ImageUri,
162
+ description: "ECR image URI for x86_64 bridge Docker image",
163
+ });
164
+ // Store the bootstrap version for compatibility checking
165
+ new ssm.StringParameter(this, "VersionParam", {
166
+ parameterName: `${ssmBasePath}/version`,
167
+ stringValue: BOOTSTRAP_VERSION,
168
+ description: "Bootstrap stack version for Live Lambda",
169
+ });
170
+ // Output the endpoints (for CLI and debugging)
171
+ new cdk.CfnOutput(this, "HttpEndpoint", {
172
+ value: this.httpEndpoint,
173
+ description: "AppSync Events HTTP endpoint",
174
+ });
175
+ new cdk.CfnOutput(this, "RealtimeEndpoint", {
176
+ value: this.realtimeEndpoint,
177
+ description: "AppSync Events WebSocket endpoint",
178
+ });
179
+ new cdk.CfnOutput(this, "ApiId", {
180
+ value: this.api.attrApiId,
181
+ description: "AppSync Events API ID",
182
+ });
183
+ new cdk.CfnOutput(this, "ApiArn", {
184
+ value: this.api.attrApiArn,
185
+ description: "AppSync Events API ARN",
186
+ });
187
+ new cdk.CfnOutput(this, "PublishRoleArn", {
188
+ value: this.publishRole.roleArn,
189
+ description: "IAM Role ARN for publishing to Events API",
190
+ });
191
+ }
192
+ /**
193
+ * Grant a Lambda function permission to publish and subscribe to the Events API
194
+ */
195
+ grantPublishSubscribe(grantee) {
196
+ return iam.Grant.addToPrincipal({
197
+ grantee,
198
+ actions: [
199
+ "appsync:EventConnect",
200
+ "appsync:EventPublish",
201
+ "appsync:EventSubscribe",
202
+ ],
203
+ resourceArns: [`${this.api.attrApiArn}/*`, this.api.attrApiArn],
204
+ });
205
+ }
206
+ /**
207
+ * Build the bridge handler and upload to S3 using a custom resource.
208
+ * The bridge code has AppSync endpoints baked in at deploy time.
209
+ */
210
+ buildAndUploadBridge() {
211
+ // Build the bridge source code at synth time (with placeholders)
212
+ const bridgePath = path.join(__dirname, "..", "functions", "bridge");
213
+ const outputPath = path.join(__dirname, "..", "out-tsc", "bridge-bundle.js");
214
+ // Bundle the bridge handler
215
+ // Note: We use .js since TypeScript compiles src/ to lib/
216
+ try {
217
+ execSync(`bun build ${bridgePath}/handler.js --outfile=${outputPath} --target=node --format=cjs --bundle --external=@aws-sdk/*`, { stdio: "pipe" });
218
+ }
219
+ catch (err) {
220
+ console.error("Failed to bundle bridge handler:", err);
221
+ throw err;
222
+ }
223
+ // Read the bundled code
224
+ const bridgeSource = fs.readFileSync(outputPath, "utf-8");
225
+ // Create the bridge builder Lambda that will replace placeholders and upload
226
+ const bridgeBuilderPath = path.join(__dirname, "..", "functions", "bridge-builder");
227
+ const bridgeBuilder = new lambda.Function(this, "BridgeBuilder", {
228
+ runtime: lambda.Runtime.NODEJS_24_X,
229
+ handler: "index.handler",
230
+ code: lambda.Code.fromAsset(bridgeBuilderPath, {
231
+ bundling: {
232
+ image: lambda.Runtime.NODEJS_24_X.bundlingImage,
233
+ command: [
234
+ "bash",
235
+ "-c",
236
+ [
237
+ "npm install --prefix /tmp esbuild",
238
+ "/tmp/node_modules/.bin/esbuild handler.ts --bundle --platform=node --target=node24 --format=cjs --outfile=/asset-output/index.js --external:@aws-sdk/*",
239
+ ].join(" && "),
240
+ ],
241
+ local: {
242
+ tryBundle(outputDir) {
243
+ try {
244
+ execSync(`bun build ${bridgeBuilderPath}/handler.js --outfile=${outputDir}/index.js --target=node --format=cjs --bundle --external=@aws-sdk/*`, { stdio: "pipe" });
245
+ return true;
246
+ }
247
+ catch {
248
+ return false;
249
+ }
250
+ },
251
+ },
252
+ },
253
+ }),
254
+ timeout: cdk.Duration.minutes(1),
255
+ memorySize: 256,
256
+ logRetention: logs.RetentionDays.ONE_WEEK,
257
+ });
258
+ // Grant the builder Lambda permission to write to the bridge bucket
259
+ this.bridgeBucket.grantWrite(bridgeBuilder);
260
+ // Create custom resource provider
261
+ const provider = new cr.Provider(this, "BridgeBuilderProvider", {
262
+ onEventHandler: bridgeBuilder,
263
+ logRetention: logs.RetentionDays.ONE_WEEK,
264
+ });
265
+ // Create custom resource that builds and uploads the bridge
266
+ const bridgeResource = new cdk.CustomResource(this, "BridgeResource", {
267
+ serviceToken: provider.serviceToken,
268
+ properties: {
269
+ HttpEndpoint: this.httpEndpoint,
270
+ RealtimeEndpoint: this.realtimeEndpoint,
271
+ BucketName: this.bridgeBucket.bucketName,
272
+ BridgeSource: Buffer.from(bridgeSource).toString("base64"),
273
+ // Force update when source changes
274
+ SourceHash: cdk.Fn.base64(bridgeSource.substring(0, 100)),
275
+ },
276
+ });
277
+ // Ensure the bridge is built after the bucket exists
278
+ bridgeResource.node.addDependency(this.bridgeBucket);
279
+ return {
280
+ bucketName: bridgeResource.getAttString("BucketName"),
281
+ s3Key: bridgeResource.getAttString("S3Key"),
282
+ bridgeSource,
283
+ };
284
+ }
285
+ /**
286
+ * Build Docker bridge images for ARM64 and x86_64 architectures.
287
+ * Uses CDK Docker image assets to build and push to ECR.
288
+ */
289
+ buildDockerBridgeImages(_bridgeSource) {
290
+ const projectRoot = path.join(__dirname, "..", "..");
291
+ const bridgeDockerPath = path.join(projectRoot, "src", "functions", "bridge-docker");
292
+ // Create a temporary directory for Docker build context
293
+ const buildContextPath = path.join(projectRoot, "src", "out-tsc", "docker-ctx");
294
+ fs.mkdirSync(buildContextPath, { recursive: true });
295
+ // Build the runtime wrapper that implements the Lambda Runtime API
296
+ // This bundle INCLUDES all dependencies (AWS SDK, ws, etc.) since
297
+ // Docker images using provided:al2023 don't have them pre-installed
298
+ const runtimePath = path.join(bridgeDockerPath, "runtime.ts");
299
+ const runtimeBundlePath = path.join(buildContextPath, "runtime.js");
300
+ try {
301
+ execSync(`bun build ${runtimePath} --outfile=${runtimeBundlePath} --target=node --format=cjs --bundle`, { stdio: "pipe" });
302
+ }
303
+ catch (err) {
304
+ console.error("Failed to bundle runtime wrapper for Docker:", err);
305
+ throw err;
306
+ }
307
+ // Copy Dockerfile and bootstrap script
308
+ fs.copyFileSync(path.join(bridgeDockerPath, "Dockerfile.arm64"), path.join(buildContextPath, "Dockerfile.arm64"));
309
+ fs.copyFileSync(path.join(bridgeDockerPath, "Dockerfile.x86_64"), path.join(buildContextPath, "Dockerfile.x86_64"));
310
+ fs.copyFileSync(path.join(bridgeDockerPath, "bootstrap.sh"), path.join(buildContextPath, "bootstrap.sh"));
311
+ // Build ARM64 image using CDK Docker image asset
312
+ const arm64Image = new ecrAssets.DockerImageAsset(this, "BridgeImageArm64", {
313
+ directory: buildContextPath,
314
+ file: "Dockerfile.arm64",
315
+ platform: ecrAssets.Platform.LINUX_ARM64,
316
+ });
317
+ // Build x86_64 image using CDK Docker image asset
318
+ const x86Image = new ecrAssets.DockerImageAsset(this, "BridgeImageX86", {
319
+ directory: buildContextPath,
320
+ file: "Dockerfile.x86_64",
321
+ platform: ecrAssets.Platform.LINUX_AMD64,
322
+ });
323
+ // Output the image URIs
324
+ new cdk.CfnOutput(this, "BridgeImageArm64Uri", {
325
+ value: arm64Image.imageUri,
326
+ description: "ECR URI for ARM64 bridge Docker image",
327
+ });
328
+ new cdk.CfnOutput(this, "BridgeImageX86Uri", {
329
+ value: x86Image.imageUri,
330
+ description: "ECR URI for x86_64 bridge Docker image",
331
+ });
332
+ return {
333
+ arm64ImageUri: arm64Image.imageUri,
334
+ x86ImageUri: x86Image.imageUri,
335
+ };
336
+ }
337
+ }
338
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLXN0YWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jvb3RzdHJhcC1zdGFjay9ib290c3RyYXAtc3RhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQzdDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFBO0FBQzdCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBQ2pDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFDeEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxhQUFhLENBQUE7QUFDbEMsT0FBTyxLQUFLLE9BQU8sTUFBTSx5QkFBeUIsQ0FBQTtBQUNsRCxPQUFPLEtBQUssU0FBUyxNQUFNLDRCQUE0QixDQUFBO0FBQ3ZELE9BQU8sS0FBSyxHQUFHLE1BQU0scUJBQXFCLENBQUE7QUFDMUMsT0FBTyxLQUFLLE1BQU0sTUFBTSx3QkFBd0IsQ0FBQTtBQUNoRCxPQUFPLEtBQUssSUFBSSxNQUFNLHNCQUFzQixDQUFBO0FBQzVDLE9BQU8sS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFDeEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQTtBQUMxQyxPQUFPLEtBQUssRUFBRSxNQUFNLDhCQUE4QixDQUFBO0FBRWxELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUVyRSw4QkFBOEI7QUFDOUIsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7QUFDakQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQTtBQWExQzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sNEJBQTZCLFNBQVEsR0FBRyxDQUFDLEtBQUs7SUFDekQ7O09BRUc7SUFDYSxHQUFH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LGdCQUFnQixDQUMvQyxJQUFJLEVBQ0osa0JBQWtCLEVBQ2xCO1lBQ0UsU0FBUyxFQUFFLGdCQUFnQjtZQUMzQixJQUFJLEVBQUUsa0JBQWtCO1lBQ3hCLFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUSxDQUFDLFdBQVc7U0FDekMsQ0FDRixDQUFBO1FBRUQsa0RBQWtEO1FBQ2xELE1BQU0sUUFBUSxHQUFHLElBQUksU0FBUyxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRTtZQUN0RSxTQUFTLEVBQUUsZ0JBQWdCO1lBQzNCLElBQUksRUFBRSxtQkFBbUI7WUFDekIsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRLENBQUMsV0FBVztTQUN6QyxDQUFDLENBQUE7UUFFRix3QkFBd0I7UUFDeEIsSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxxQkFBcUIsRUFBRTtZQUM3QyxLQUFLLEVBQUUsVUFBVSxDQUFDLFFBQVE7WUFDMUIsV0FBVyxFQUFFLHVDQUF1QztTQUNyRCxDQUFDLENBQUE7UUFFRixJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFO1lBQzNDLEtBQUssRUFBRSxRQUFRLENBQUMsUUFBUTtZQUN4QixXQUFXLEVBQUUsd0NBQXdDO1NBQ3RELENBQUMsQ0FBQTtRQUVGLE9BQU87WUFDTCxhQUFhLEVBQUUsVUFBVSxDQUFDLFFBQVE7WUFDbEMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxRQUFRO1NBQy9CLENBQUE7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGVjU3luYyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIlxuaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnNcIlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tIFwibm9kZTp1cmxcIlxuaW1wb3J0ICogYXMgY2RrIGZyb20gXCJhd3MtY2RrLWxpYlwiXG5pbXBvcnQgKiBhcyBhcHBzeW5jIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXBwc3luY1wiXG5pbXBvcnQgKiBhcyBlY3JBc3NldHMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1lY3ItYXNzZXRzXCJcbmltcG9ydCAqIGFzIGlhbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiXG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIlxuaW1wb3J0ICogYXMgbG9ncyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxvZ3NcIlxuaW1wb3J0ICogYXMgczMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiXG5pbXBvcnQgKiBhcyBzc20gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zc21cIlxuaW1wb3J0ICogYXMgY3IgZnJvbSBcImF3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXNcIlxuaW1wb3J0IHR5cGUgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiXG5pbXBvcnQgeyBCT09UU1RSQVBfVkVSU0lPTiwgU1NNX0JBU0VfUEFUSCB9IGZyb20gXCIuLi9zaGFyZWQvdHlwZXMuanNcIlxuXG4vLyBFU00gZXF1aXZhbGVudCBvZiBfX2Rpcm5hbWVcbmNvbnN0IF9fZmlsZW5hbWUgPSBmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybClcbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShfX2ZpbGVuYW1lKVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIHRoZSBMaXZlTGFtYmRhQm9vdHN0cmFwU3RhY2tcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDZGtMb2NhbExhbWJkYUJvb3RzdHJhcFN0YWNrUHJvcHMgZXh0ZW5kcyBjZGsuU3RhY2tQcm9wcyB7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBuYW1lIGZvciB0aGUgQXBwU3luYyBFdmVudHMgQVBJXG4gICAqIEBkZWZhdWx0ICdMaXZlTGFtYmRhRXZlbnRzQXBpJ1xuICAgKi9cbiAgYXBpTmFtZT86IHN0cmluZ1xufVxuXG4vKipcbiAqIEJvb3RzdHJhcCBzdGFjayB0aGF0IGNyZWF0ZXMgdGhlIHNoYXJlZCBBcHBTeW5jIEV2ZW50cyBBUEkgaW5mcmFzdHJ1Y3R1cmVcbiAqIGZvciBsaXZlIGxhbWJkYSBkZWJ1Z2dpbmcuIFRoaXMgc3RhY2sgc2hvdWxkIGJlIGRlcGxveWVkIG9uY2UgcGVyIGFjY291bnQvcmVnaW9uLlxuICovXG5leHBvcnQgY2xhc3MgQ2RrTG9jYWxMYW1iZGFCb290c3RyYXBTdGFjayBleHRlbmRzIGNkay5TdGFjayB7XG4gIC8qKlxuICAgKiBUaGUgQXBwU3luYyBFdmVudHMgQVBJIGZvciBXZWJTb2NrZXQgY29tbXVuaWNhdGlvblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFwaTogYXBwc3luYy5DZm5BcGlcblxuICAvKipcbiAgICogVGhlIGNoYW5uZWwgbmFtZXNwYWNlIGZvciBsaXZlIGRlYnVnZ2luZyBjaGFubmVsc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNoYW5uZWxOYW1lc3BhY2U6IGFwcHN5bmMuQ2ZuQ2hhbm5lbE5hbWVzcGFjZVxuXG4gIC8qKlxuICAgKiBUaGUgSFRUUCBlbmRwb2ludCBmb3IgcHVibGlzaGluZyBldmVudHNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBodHRwRW5kcG9pbnQ6IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBUaGUgV2ViU29ja2V0IGVuZHBvaW50IGZvciByZWFsLXRpbWUgc3Vic2NyaXB0aW9uc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJlYWx0aW1lRW5kcG9pbnQ6IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBJQU0gcm9sZSBmb3IgcHVibGlzaGluZyB0byB0aGUgRXZlbnRzIEFQSVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHB1Ymxpc2hSb2xlOiBpYW0uUm9sZVxuXG4gIC8qKlxuICAgKiBTMyBidWNrZXQgZm9yIHN0b3JpbmcgdGhlIGJyaWRnZSBMYW1iZGEgY29kZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGJyaWRnZUJ1Y2tldDogczMuQnVja2V0XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzPzogQ2RrTG9jYWxMYW1iZGFCb290c3RyYXBTdGFja1Byb3BzLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKVxuXG4gICAgY29uc3QgYXBpTmFtZSA9IHByb3BzPy5hcGlOYW1lID8/IFwiTGl2ZUxhbWJkYUV2ZW50c0FwaVwiXG5cbiAgICAvLyBDcmVhdGUgUzMgYnVja2V0IGZvciBicmlkZ2UgY29kZVxuICAgIHRoaXMuYnJpZGdlQnVja2V0ID0gbmV3IHMzLkJ1Y2tldCh0aGlzLCBcIkJyaWRnZUJ1Y2tldFwiLCB7XG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgYXV0b0RlbGV0ZU9iamVjdHM6IHRydWUsXG4gICAgICBibG9ja1B1YmxpY0FjY2VzczogczMuQmxvY2tQdWJsaWNBY2Nlc3MuQkxPQ0tfQUxMLFxuICAgIH0pXG5cbiAgICAvLyBDcmVhdGUgQXBwU3luYyBFdmVudHMgQVBJIHdpdGggSUFNIGF1dGhlbnRpY2F0aW9uXG4gICAgdGhpcy5hcGkgPSBuZXcgYXBwc3luYy5DZm5BcGkodGhpcywgXCJFdmVudHNBcGlcIiwge1xuICAgICAgbmFtZTogYXBpTmFtZSxcbiAgICAgIGV2ZW50Q29uZmlnOiB7XG4gICAgICAgIGF1dGhQcm92aWRlcnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhdXRoVHlwZTogXCJBV1NfSUFNXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgY29ubmVjdGlvbkF1dGhNb2RlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGF1dGhUeXBlOiBcIkFXU19JQU1cIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBkZWZhdWx0UHVibGlzaEF1dGhNb2RlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGF1dGhUeXBlOiBcIkFXU19JQU1cIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBkZWZhdWx0U3Vic2NyaWJlQXV0aE1vZGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYXV0aFR5cGU6IFwiQVdTX0lBTVwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIH0pXG5cbiAgICAvLyBDcmVhdGUgY2hhbm5lbCBuYW1lc3BhY2UgZm9yIGxpdmUgZGVidWdnaW5nXG4gICAgLy8gQ2hhbm5lbHMgd2lsbCBiZTogL2xpdmUve3N0YWNrTmFtZX0ve2Z1bmN0aW9uSWR9L2luIGFuZCAvbGl2ZS97c3RhY2tOYW1lfS97ZnVuY3Rpb25JZH0vb3V0XG4gICAgdGhpcy5jaGFubmVsTmFtZXNwYWNlID0gbmV3IGFwcHN5bmMuQ2ZuQ2hhbm5lbE5hbWVzcGFjZShcbiAgICAgIHRoaXMsXG4gICAgICBcIkxpdmVOYW1lc3BhY2VcIixcbiAgICAgIHtcbiAgICAgICAgYXBpSWQ6IHRoaXMuYXBpLmF0dHJBcGlJZCxcbiAgICAgICAgbmFtZTogXCJsaXZlXCIsXG4gICAgICB9LFxuICAgIClcblxuICAgIC8vIFN0b3JlIGVuZHBvaW50cyAtIHVzaW5nIGdldEF0dCBzaW5jZSBhdHRyRG5zIGlzIHR5cGVkIGFzIElSZXNvbHZhYmxlXG4gICAgLy8gUHJlcGVuZCBwcm90b2NvbHMgc2luY2UgQXBwU3luYyBvbmx5IHJldHVybnMgaG9zdG5hbWVzXG4gICAgdGhpcy5odHRwRW5kcG9pbnQgPSBjZGsuRm4uam9pbihcIlwiLCBbXG4gICAgICBcImh0dHBzOi8vXCIsXG4gICAgICBjZGsuVG9rZW4uYXNTdHJpbmcodGhpcy5hcGkuZ2V0QXR0KFwiRG5zLkh0dHBcIikpLFxuICAgIF0pXG4gICAgdGhpcy5yZWFsdGltZUVuZHBvaW50ID0gY2RrLkZuLmpvaW4oXCJcIiwgW1xuICAgICAgXCJ3c3M6Ly9cIixcbiAgICAgIGNkay5Ub2tlbi5hc1N0cmluZyh0aGlzLmFwaS5nZXRBdHQoXCJEbnMuUmVhbHRpbWVcIikpLFxuICAgIF0pXG5cbiAgICAvLyBDcmVhdGUgSUFNIHJvbGUgZm9yIExhbWJkYSBmdW5jdGlvbnMgdG8gcHVibGlzaC9zdWJzY3JpYmVcbiAgICB0aGlzLnB1Ymxpc2hSb2xlID0gbmV3IGlhbS5Sb2xlKHRoaXMsIFwiUHVibGlzaFJvbGVcIiwge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoXCJsYW1iZGEuYW1hem9uYXdzLmNvbVwiKSxcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIlJvbGUgZm9yIExhbWJkYSBmdW5jdGlvbnMgdG8gcHVibGlzaC9zdWJzY3JpYmUgdG8gTGl2ZSBMYW1iZGEgRXZlbnRzIEFQSVwiLFxuICAgIH0pXG5cbiAgICAvLyBHcmFudCBwZXJtaXNzaW9ucyB0byBwdWJsaXNoIGFuZCBzdWJzY3JpYmUgdG8gdGhlIEV2ZW50cyBBUElcbiAgICB0aGlzLnB1Ymxpc2hSb2xlLmFkZFRvUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcImFwcHN5bmM6RXZlbnRDb25uZWN0XCIsXG4gICAgICAgICAgXCJhcHBzeW5jOkV2ZW50UHVibGlzaFwiLFxuICAgICAgICAgIFwiYXBwc3luYzpFdmVudFN1YnNjcmliZVwiLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFtgJHt0aGlzLmFwaS5hdHRyQXBpQXJufS8qYCwgdGhpcy5hcGkuYXR0ckFwaUFybl0sXG4gICAgICB9KSxcbiAgICApXG5cbiAgICAvLyBDcmVhdGUgU1NNIHBhcmFtZXRlcnMgZm9yIHRoZSBlbmRwb2ludHNcbiAgICAvLyBUaGVzZSBhcmUgdXNlZCBieSB0aGUgbGl2ZS1sYW1iZGEtYXNwZWN0IHRvIGNvbmZpZ3VyZSBMYW1iZGEgZnVuY3Rpb25zXG4gICAgLy8gVXNlIHRoZSBDREsgYm9vdHN0cmFwIHF1YWxpZmllciBmb3IgcHJvcGVyIHNjb3BpbmdcbiAgICBjb25zdCBib290c3RyYXBRdWFsaWZpZXIgPVxuICAgICAgdGhpcy5ub2RlLnRyeUdldENvbnRleHQoXCJAYXdzLWNkay9jb3JlOmJvb3RzdHJhcFF1YWxpZmllclwiKSB8fCBcImhuYjY1OWZkc1wiXG4gICAgY29uc3Qgc3NtQmFzZVBhdGggPSBgJHtTU01fQkFTRV9QQVRIfS8ke2Jvb3RzdHJhcFF1YWxpZmllcn1gXG5cbiAgICBuZXcgc3NtLlN0cmluZ1BhcmFtZXRlcih0aGlzLCBcIkh0dHBFbmRwb2ludFBhcmFtXCIsIHtcbiAgICAgIHBhcmFtZXRlck5hbWU6IGAke3NzbUJhc2VQYXRofS9odHRwLWVuZHBvaW50YCxcbiAgICAgIHN0cmluZ1ZhbHVlOiB0aGlzLmh0dHBFbmRwb2ludCxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkFwcFN5bmMgRXZlbnRzIEhUVFAgZW5kcG9pbnQgZm9yIExpdmUgTGFtYmRhXCIsXG4gICAgfSlcblxuICAgIG5ldyBzc20uU3RyaW5nUGFyYW1ldGVyKHRoaXMsIFwiUmVhbHRpbWVFbmRwb2ludFBhcmFtXCIsIHtcbiAgICAgIHBhcmFtZXRlck5hbWU6IGAke3NzbUJhc2VQYXRofS9yZWFsdGltZS1lbmRwb2ludGAsXG4gICAgICBzdHJpbmdWYWx1ZTogdGhpcy5yZWFsdGltZUVuZHBvaW50LFxuICAgICAgZGVzY3JpcHRpb246IFwiQXBwU3luYyBFdmVudHMgV2ViU29ja2V0IGVuZHBvaW50IGZvciBMaXZlIExhbWJkYVwiLFxuICAgIH0pXG5cbiAgICBuZXcgc3NtLlN0cmluZ1BhcmFtZXRlcih0aGlzLCBcIkFwaUFyblBhcmFtXCIsIHtcbiAgICAgIHBhcmFtZXRlck5hbWU6IGAke3NzbUJhc2VQYXRofS9hcGktYXJuYCxcbiAgICAgIHN0cmluZ1ZhbHVlOiB0aGlzLmFwaS5hdHRyQXBpQXJuLFxuICAgICAgZGVzY3JpcHRpb246IFwiQXBwU3luYyBFdmVudHMgQVBJIEFSTiBmb3IgTGl2ZSBMYW1iZGFcIixcbiAgICB9KVxuXG4gICAgbmV3IHNzbS5TdHJpbmdQYXJhbWV0ZXIodGhpcywgXCJBcGlJZFBhcmFtXCIsIHtcbiAgICAgIHBhcmFtZXRlck5hbWU6IGAke3NzbUJhc2VQYXRofS9hcGktaWRgLFxuICAgICAgc3RyaW5nVmFsdWU6IHRoaXMuYXBpLmF0dHJBcGlJZCxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkFwcFN5bmMgRXZlbnRzIEFQSSBJRCBmb3IgTGl2ZSBMYW1iZGFcIixcbiAgICB9KVxuXG4gICAgLy8gQnVpbGQgYnJpZGdlIGhhbmRsZXIgYW5kIHVwbG9hZCB0byBTM1xuICAgIGNvbnN0IHsgYnVja2V0TmFtZSwgczNLZXksIGJyaWRnZVNvdXJjZSB9ID0gdGhpcy5idWlsZEFuZFVwbG9hZEJyaWRnZSgpXG4gICAgY29uc3QgYnJpZGdlUzNMb2NhdGlvbiA9IHsgYnVja2V0TmFtZSwgczNLZXkgfVxuXG4gICAgLy8gU3RvcmUgYnJpZGdlIFMzIGxvY2F0aW9uIGluIFNTTVxuICAgIG5ldyBzc20uU3RyaW5nUGFyYW1ldGVyKHRoaXMsIFwiQnJpZGdlQnVja2V0UGFyYW1cIiwge1xuICAgICAgcGFyYW1ldGVyTmFtZTogYCR7c3NtQmFzZVBhdGh9L2JyaWRnZS1idWNrZXRgLFxuICAgICAgc3RyaW5nVmFsdWU6IGJyaWRnZVMzTG9jYXRpb24uYnVja2V0TmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlMzIGJ1Y2tldCBjb250YWluaW5nIExpdmUgTGFtYmRhIGJyaWRnZSBjb2RlXCIsXG4gICAgfSlcblxuICAgIG5ldyBzc20uU3RyaW5nUGFyYW1ldGVyKHRoaXMsIFwiQnJpZGdlS2V5UGFyYW1cIiwge1xuICAgICAgcGFyYW1ldGVyTmFtZTogYCR7c3NtQmFzZVBhdGh9L2JyaWRnZS1rZXlgLFxuICAgICAgc3RyaW5nVmFsdWU6IGJyaWRnZVMzTG9jYXRpb24uczNLZXksXG4gICAgICBkZXNjcmlwdGlvbjogXCJTMyBrZXkgZm9yIExpdmUgTGFtYmRhIGJyaWRnZSBjb2RlXCIsXG4gICAgfSlcblxuICAgIC8vIEJ1aWxkIGFuZCBzdG9yZSBEb2NrZXIgYnJpZGdlIGltYWdlcyBmb3IgRG9ja2VySW1hZ2VGdW5jdGlvbiBzdXBwb3J0XG4gICAgY29uc3QgZG9ja2VyQnJpZGdlSW1hZ2VzID0gdGhpcy5idWlsZERvY2tlckJyaWRnZUltYWdlcyhicmlkZ2VTb3VyY2UpXG5cbiAgICBuZXcgc3NtLlN0cmluZ1BhcmFtZXRlcih0aGlzLCBcIkJyaWRnZUltYWdlQXJtNjRQYXJhbVwiLCB7XG4gICAgICBwYXJhbWV0ZXJOYW1lOiBgJHtzc21CYXNlUGF0aH0vYnJpZGdlLWltYWdlLWFybTY0YCxcbiAgICAgIHN0cmluZ1ZhbHVlOiBkb2NrZXJCcmlkZ2VJbWFnZXMuYXJtNjRJbWFnZVVyaSxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkVDUiBpbWFnZSBVUkkgZm9yIEFSTTY0IGJyaWRnZSBEb2NrZXIgaW1hZ2VcIixcbiAgICB9KVxuXG4gICAgbmV3IHNzbS5TdHJpbmdQYXJhbWV0ZXIodGhpcywgXCJCcmlkZ2VJbWFnZVg4NlBhcmFtXCIsIHtcbiAgICAgIHBhcmFtZXRlck5hbWU6IGAke3NzbUJhc2VQYXRofS9icmlkZ2UtaW1hZ2UteDg2XzY0YCxcbiAgICAgIHN0cmluZ1ZhbHVlOiBkb2NrZXJCcmlkZ2VJbWFnZXMueDg2SW1hZ2VVcmksXG4gICAgICBkZXNjcmlwdGlvbjogXCJFQ1IgaW1hZ2UgVVJJIGZvciB4ODZfNjQgYnJpZGdlIERvY2tlciBpbWFnZVwiLFxuICAgIH0pXG5cbiAgICAvLyBTdG9yZSB0aGUgYm9vdHN0cmFwIHZlcnNpb24gZm9yIGNvbXBhdGliaWxpdHkgY2hlY2tpbmdcbiAgICBuZXcgc3NtLlN0cmluZ1BhcmFtZXRlcih0aGlzLCBcIlZlcnNpb25QYXJhbVwiLCB7XG4gICAgICBwYXJhbWV0ZXJOYW1lOiBgJHtzc21CYXNlUGF0aH0vdmVyc2lvbmAsXG4gICAgICBzdHJpbmdWYWx1ZTogQk9PVFNUUkFQX1ZFUlNJT04sXG4gICAgICBkZXNjcmlwdGlvbjogXCJCb290c3RyYXAgc3RhY2sgdmVyc2lvbiBmb3IgTGl2ZSBMYW1iZGFcIixcbiAgICB9KVxuXG4gICAgLy8gT3V0cHV0IHRoZSBlbmRwb2ludHMgKGZvciBDTEkgYW5kIGRlYnVnZ2luZylcbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCBcIkh0dHBFbmRwb2ludFwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5odHRwRW5kcG9pbnQsXG4gICAgICBkZXNjcmlwdGlvbjogXCJBcHBTeW5jIEV2ZW50cyBIVFRQIGVuZHBvaW50XCIsXG4gICAgfSlcblxuICAgIG5ldyBjZGsuQ2ZuT3V0cHV0KHRoaXMsIFwiUmVhbHRpbWVFbmRwb2ludFwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5yZWFsdGltZUVuZHBvaW50LFxuICAgICAgZGVzY3JpcHRpb246IFwiQXBwU3luYyBFdmVudHMgV2ViU29ja2V0IGVuZHBvaW50XCIsXG4gICAgfSlcblxuICAgIG5ldyBjZGsuQ2ZuT3V0cHV0KHRoaXMsIFwiQXBpSWRcIiwge1xuICAgICAgdmFsdWU6IHRoaXMuYXBpLmF0dHJBcGlJZCxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkFwcFN5bmMgRXZlbnRzIEFQSSBJRFwiLFxuICAgIH0pXG5cbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCBcIkFwaUFyblwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5hcGkuYXR0ckFwaUFybixcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkFwcFN5bmMgRXZlbnRzIEFQSSBBUk5cIixcbiAgICB9KVxuXG4gICAgbmV3IGNkay5DZm5PdXRwdXQodGhpcywgXCJQdWJsaXNoUm9sZUFyblwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5wdWJsaXNoUm9sZS5yb2xlQXJuLFxuICAgICAgZGVzY3JpcHRpb246IFwiSUFNIFJvbGUgQVJOIGZvciBwdWJsaXNoaW5nIHRvIEV2ZW50cyBBUElcIixcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IGEgTGFtYmRhIGZ1bmN0aW9uIHBlcm1pc3Npb24gdG8gcHVibGlzaCBhbmQgc3Vic2NyaWJlIHRvIHRoZSBFdmVudHMgQVBJXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRQdWJsaXNoU3Vic2NyaWJlKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIFwiYXBwc3luYzpFdmVudENvbm5lY3RcIixcbiAgICAgICAgXCJhcHBzeW5jOkV2ZW50UHVibGlzaFwiLFxuICAgICAgICBcImFwcHN5bmM6RXZlbnRTdWJzY3JpYmVcIixcbiAgICAgIF0sXG4gICAgICByZXNvdXJjZUFybnM6IFtgJHt0aGlzLmFwaS5hdHRyQXBpQXJufS8qYCwgdGhpcy5hcGkuYXR0ckFwaUFybl0sXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCB0aGUgYnJpZGdlIGhhbmRsZXIgYW5kIHVwbG9hZCB0byBTMyB1c2luZyBhIGN1c3RvbSByZXNvdXJjZS5cbiAgICogVGhlIGJyaWRnZSBjb2RlIGhhcyBBcHBTeW5jIGVuZHBvaW50cyBiYWtlZCBpbiBhdCBkZXBsb3kgdGltZS5cbiAgICovXG4gIHByaXZhdGUgYnVpbGRBbmRVcGxvYWRCcmlkZ2UoKToge1xuICAgIGJ1Y2tldE5hbWU6IHN0cmluZ1xuICAgIHMzS2V5OiBzdHJpbmdcbiAgICBicmlkZ2VTb3VyY2U6IHN0cmluZ1xuICB9IHtcbiAgICAvLyBCdWlsZCB0aGUgYnJpZGdlIHNvdXJjZSBjb2RlIGF0IHN5bnRoIHRpbWUgKHdpdGggcGxhY2Vob2xkZXJzKVxuICAgIGNvbnN0IGJyaWRnZVBhdGggPSBwYXRoLmpvaW4oX19kaXJuYW1lLCBcIi4uXCIsIFwiZnVuY3Rpb25zXCIsIFwiYnJpZGdlXCIpXG4gICAgY29uc3Qgb3V0cHV0UGF0aCA9IHBhdGguam9pbihfX2Rpcm5hbWUsIFwiLi5cIiwgXCJvdXQtdHNjXCIsIFwiYnJpZGdlLWJ1bmRsZS5qc1wiKVxuXG4gICAgLy8gQnVuZGxlIHRoZSBicmlkZ2UgaGFuZGxlclxuICAgIC8vIE5vdGU6IFdlIHVzZSAuanMgc2luY2UgVHlwZVNjcmlwdCBjb21waWxlcyBzcmMvIHRvIGxpYi9cbiAgICB0cnkge1xuICAgICAgZXhlY1N5bmMoXG4gICAgICAgIGBidW4gYnVpbGQgJHticmlkZ2VQYXRofS9oYW5kbGVyLmpzIC0tb3V0ZmlsZT0ke291dHB1dFBhdGh9IC0tdGFyZ2V0PW5vZGUgLS1mb3JtYXQ9Y2pzIC0tYnVuZGxlIC0tZXh0ZXJuYWw9QGF3cy1zZGsvKmAsXG4gICAgICAgIHsgc3RkaW86IFwicGlwZVwiIH0sXG4gICAgICApXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiRmFpbGVkIHRvIGJ1bmRsZSBicmlkZ2UgaGFuZGxlcjpcIiwgZXJyKVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuXG4gICAgLy8gUmVhZCB0aGUgYnVuZGxlZCBjb2RlXG4gICAgY29uc3QgYnJpZGdlU291cmNlID0gZnMucmVhZEZpbGVTeW5jKG91dHB1dFBhdGgsIFwidXRmLThcIilcblxuICAgIC8vIENyZWF0ZSB0aGUgYnJpZGdlIGJ1aWxkZXIgTGFtYmRhIHRoYXQgd2lsbCByZXBsYWNlIHBsYWNlaG9sZGVycyBhbmQgdXBsb2FkXG4gICAgY29uc3QgYnJpZGdlQnVpbGRlclBhdGggPSBwYXRoLmpvaW4oXG4gICAgICBfX2Rpcm5hbWUsXG4gICAgICBcIi4uXCIsXG4gICAgICBcImZ1bmN0aW9uc1wiLFxuICAgICAgXCJicmlkZ2UtYnVpbGRlclwiLFxuICAgIClcbiAgICBjb25zdCBicmlkZ2VCdWlsZGVyID0gbmV3IGxhbWJkYS5GdW5jdGlvbih0aGlzLCBcIkJyaWRnZUJ1aWxkZXJcIiwge1xuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzI0X1gsXG4gICAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChicmlkZ2VCdWlsZGVyUGF0aCwge1xuICAgICAgICBidW5kbGluZzoge1xuICAgICAgICAgIGltYWdlOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjRfWC5idW5kbGluZ0ltYWdlLFxuICAgICAgICAgIGNvbW1hbmQ6IFtcbiAgICAgICAgICAgIFwiYmFzaFwiLFxuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBcIm5wbSBpbnN0YWxsIC0tcHJlZml4IC90bXAgZXNidWlsZFwiLFxuICAgICAgICAgICAgICBcIi90bXAvbm9kZV9tb2R1bGVzLy5iaW4vZXNidWlsZCBoYW5kbGVyLnRzIC0tYnVuZGxlIC0tcGxhdGZvcm09bm9kZSAtLXRhcmdldD1ub2RlMjQgLS1mb3JtYXQ9Y2pzIC0tb3V0ZmlsZT0vYXNzZXQtb3V0cHV0L2luZGV4LmpzIC0tZXh0ZXJuYWw6QGF3cy1zZGsvKlwiLFxuICAgICAgICAgICAgXS5qb2luKFwiICYmIFwiKSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGxvY2FsOiB7XG4gICAgICAgICAgICB0cnlCdW5kbGUob3V0cHV0RGlyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBleGVjU3luYyhcbiAgICAgICAgICAgICAgICAgIGBidW4gYnVpbGQgJHticmlkZ2VCdWlsZGVyUGF0aH0vaGFuZGxlci5qcyAtLW91dGZpbGU9JHtvdXRwdXREaXJ9L2luZGV4LmpzIC0tdGFyZ2V0PW5vZGUgLS1mb3JtYXQ9Y2pzIC0tYnVuZGxlIC0tZXh0ZXJuYWw9QGF3cy1zZGsvKmAsXG4gICAgICAgICAgICAgICAgICB7IHN0ZGlvOiBcInBpcGVcIiB9LFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgICB0aW1lb3V0OiBjZGsuRHVyYXRpb24ubWludXRlcygxKSxcbiAgICAgIG1lbW9yeVNpemU6IDI1NixcbiAgICAgIGxvZ1JldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLk9ORV9XRUVLLFxuICAgIH0pXG5cbiAgICAvLyBHcmFudCB0aGUgYnVpbGRlciBMYW1iZGEgcGVybWlzc2lvbiB0byB3cml0ZSB0byB0aGUgYnJpZGdlIGJ1Y2tldFxuICAgIHRoaXMuYnJpZGdlQnVja2V0LmdyYW50V3JpdGUoYnJpZGdlQnVpbGRlcilcblxuICAgIC8vIENyZWF0ZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXJcbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBjci5Qcm92aWRlcih0aGlzLCBcIkJyaWRnZUJ1aWxkZXJQcm92aWRlclwiLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogYnJpZGdlQnVpbGRlcixcbiAgICAgIGxvZ1JldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLk9ORV9XRUVLLFxuICAgIH0pXG5cbiAgICAvLyBDcmVhdGUgY3VzdG9tIHJlc291cmNlIHRoYXQgYnVpbGRzIGFuZCB1cGxvYWRzIHRoZSBicmlkZ2VcbiAgICBjb25zdCBicmlkZ2VSZXNvdXJjZSA9IG5ldyBjZGsuQ3VzdG9tUmVzb3VyY2UodGhpcywgXCJCcmlkZ2VSZXNvdXJjZVwiLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgSHR0cEVuZHBvaW50OiB0aGlzLmh0dHBFbmRwb2ludCxcbiAgICAgICAgUmVhbHRpbWVFbmRwb2ludDogdGhpcy5yZWFsdGltZUVuZHBvaW50LFxuICAgICAgICBCdWNrZXROYW1lOiB0aGlzLmJyaWRnZUJ1Y2tldC5idWNrZXROYW1lLFxuICAgICAgICBCcmlkZ2VTb3VyY2U6IEJ1ZmZlci5mcm9tKGJyaWRnZVNvdXJjZSkudG9TdHJpbmcoXCJiYXNlNjRcIiksXG4gICAgICAgIC8vIEZvcmNlIHVwZGF0ZSB3aGVuIHNvdXJjZSBjaGFuZ2VzXG4gICAgICAgIFNvdXJjZUhhc2g6IGNkay5Gbi5iYXNlNjQoYnJpZGdlU291cmNlLnN1YnN0cmluZygwLCAxMDApKSxcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIC8vIEVuc3VyZSB0aGUgYnJpZGdlIGlzIGJ1aWx0IGFmdGVyIHRoZSBidWNrZXQgZXhpc3RzXG4gICAgYnJpZGdlUmVzb3VyY2Uubm9kZS5hZGREZXBlbmRlbmN5KHRoaXMuYnJpZGdlQnVja2V0KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJ1Y2tldE5hbWU6IGJyaWRnZVJlc291cmNlLmdldEF0dFN0cmluZyhcIkJ1Y2tldE5hbWVcIiksXG4gICAgICBzM0tleTogYnJpZGdlUmVzb3VyY2UuZ2V0QXR0U3RyaW5nKFwiUzNLZXlcIiksXG4gICAgICBicmlkZ2VTb3VyY2UsXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIERvY2tlciBicmlkZ2UgaW1hZ2VzIGZvciBBUk02NCBhbmQgeDg2XzY0IGFyY2hpdGVjdHVyZXMuXG4gICAqIFVzZXMgQ0RLIERvY2tlciBpbWFnZSBhc3NldHMgdG8gYnVpbGQgYW5kIHB1c2ggdG8gRUNSLlxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZERvY2tlckJyaWRnZUltYWdlcyhfYnJpZGdlU291cmNlOiBzdHJpbmcpOiB7XG4gICAgYXJtNjRJbWFnZVVyaTogc3RyaW5nXG4gICAgeDg2SW1hZ2VVcmk6IHN0cmluZ1xuICB9IHtcbiAgICBjb25zdCBwcm9qZWN0Um9vdCA9IHBhdGguam9pbihfX2Rpcm5hbWUsIFwiLi5cIiwgXCIuLlwiKVxuICAgIGNvbnN0IGJyaWRnZURvY2tlclBhdGggPSBwYXRoLmpvaW4oXG4gICAgICBwcm9qZWN0Um9vdCxcbiAgICAgIFwic3JjXCIsXG4gICAgICBcImZ1bmN0aW9uc1wiLFxuICAgICAgXCJicmlkZ2UtZG9ja2VyXCIsXG4gICAgKVxuXG4gICAgLy8gQ3JlYXRlIGEgdGVtcG9yYXJ5IGRpcmVjdG9yeSBmb3IgRG9ja2VyIGJ1aWxkIGNvbnRleHRcbiAgICBjb25zdCBidWlsZENvbnRleHRQYXRoID0gcGF0aC5qb2luKFxuICAgICAgcHJvamVjdFJvb3QsXG4gICAgICBcInNyY1wiLFxuICAgICAgXCJvdXQtdHNjXCIsXG4gICAgICBcImRvY2tlci1jdHhcIixcbiAgICApXG4gICAgZnMubWtkaXJTeW5jKGJ1aWxkQ29udGV4dFBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cbiAgICAvLyBCdWlsZCB0aGUgcnVudGltZSB3cmFwcGVyIHRoYXQgaW1wbGVtZW50cyB0aGUgTGFtYmRhIFJ1bnRpbWUgQVBJXG4gICAgLy8gVGhpcyBidW5kbGUgSU5DTFVERVMgYWxsIGRlcGVuZGVuY2llcyAoQVdTIFNESywgd3MsIGV0Yy4pIHNpbmNlXG4gICAgLy8gRG9ja2VyIGltYWdlcyB1c2luZyBwcm92aWRlZDphbDIwMjMgZG9uJ3QgaGF2ZSB0aGVtIHByZS1pbnN0YWxsZWRcbiAgICBjb25zdCBydW50aW1lUGF0aCA9IHBhdGguam9pbihicmlkZ2VEb2NrZXJQYXRoLCBcInJ1bnRpbWUudHNcIilcbiAgICBjb25zdCBydW50aW1lQnVuZGxlUGF0aCA9IHBhdGguam9pbihidWlsZENvbnRleHRQYXRoLCBcInJ1bnRpbWUuanNcIilcbiAgICB0cnkge1xuICAgICAgZXhlY1N5bmMoXG4gICAgICAgIGBidW4gYnVpbGQgJHtydW50aW1lUGF0aH0gLS1vdXRmaWxlPSR7cnVudGltZUJ1bmRsZVBhdGh9IC0tdGFyZ2V0PW5vZGUgLS1mb3JtYXQ9Y2pzIC0tYnVuZGxlYCxcbiAgICAgICAgeyBzdGRpbzogXCJwaXBlXCIgfSxcbiAgICAgIClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gYnVuZGxlIHJ1bnRpbWUgd3JhcHBlciBmb3IgRG9ja2VyOlwiLCBlcnIpXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG5cbiAgICAvLyBDb3B5IERvY2tlcmZpbGUgYW5kIGJvb3RzdHJhcCBzY3JpcHRcbiAgICBmcy5jb3B5RmlsZVN5bmMoXG4gICAgICBwYXRoLmpvaW4oYnJpZGdlRG9ja2VyUGF0aCwgXCJEb2NrZXJmaWxlLmFybTY0XCIpLFxuICAgICAgcGF0aC5qb2luKGJ1aWxkQ29udGV4dFBhdGgsIFwiRG9ja2VyZmlsZS5hcm02NFwiKSxcbiAgICApXG4gICAgZnMuY29weUZpbGVTeW5jKFxuICAgICAgcGF0aC5qb2luKGJyaWRnZURvY2tlclBhdGgsIFwiRG9ja2VyZmlsZS54ODZfNjRcIiksXG4gICAgICBwYXRoLmpvaW4oYnVpbGRDb250ZXh0UGF0aCwgXCJEb2NrZXJmaWxlLng4Nl82NFwiKSxcbiAgICApXG4gICAgZnMuY29weUZpbGVTeW5jKFxuICAgICAgcGF0aC5qb2luKGJyaWRnZURvY2tlclBhdGgsIFwiYm9vdHN0cmFwLnNoXCIpLFxuICAgICAgcGF0aC5qb2luKGJ1aWxkQ29udGV4dFBhdGgsIFwiYm9vdHN0cmFwLnNoXCIpLFxuICAgIClcblxuICAgIC8vIEJ1aWxkIEFSTTY0IGltYWdlIHVzaW5nIENESyBEb2NrZXIgaW1hZ2UgYXNzZXRcbiAgICBjb25zdCBhcm02NEltYWdlID0gbmV3IGVjckFzc2V0cy5Eb2NrZXJJbWFnZUFzc2V0KFxuICAgICAgdGhpcyxcbiAgICAgIFwiQnJpZGdlSW1hZ2VBcm02NFwiLFxuICAgICAge1xuICAgICAgICBkaXJlY3Rvcnk6IGJ1aWxkQ29udGV4dFBhdGgsXG4gICAgICAgIGZpbGU6IFwiRG9ja2VyZmlsZS5hcm02NFwiLFxuICAgICAgICBwbGF0Zm9ybTogZWNyQXNzZXRzLlBsYXRmb3JtLkxJTlVYX0FSTTY0LFxuICAgICAgfSxcbiAgICApXG5cbiAgICAvLyBCdWlsZCB4ODZfNjQgaW1hZ2UgdXNpbmcgQ0RLIERvY2tlciBpbWFnZSBhc3NldFxuICAgIGNvbnN0IHg4NkltYWdlID0gbmV3IGVjckFzc2V0cy5Eb2NrZXJJbWFnZUFzc2V0KHRoaXMsIFwiQnJpZGdlSW1hZ2VYODZcIiwge1xuICAgICAgZGlyZWN0b3J5OiBidWlsZENvbnRleHRQYXRoLFxuICAgICAgZmlsZTogXCJEb2NrZXJmaWxlLng4Nl82NFwiLFxuICAgICAgcGxhdGZvcm06IGVjckFzc2V0cy5QbGF0Zm9ybS5MSU5VWF9BTUQ2NCxcbiAgICB9KVxuXG4gICAgLy8gT3V0cHV0IHRoZSBpbWFnZSBVUklzXG4gICAgbmV3IGNkay5DZm5PdXRwdXQodGhpcywgXCJCcmlkZ2VJbWFnZUFybTY0VXJpXCIsIHtcbiAgICAgIHZhbHVlOiBhcm02NEltYWdlLmltYWdlVXJpLFxuICAgICAgZGVzY3JpcHRpb246IFwiRUNSIFVSSSBmb3IgQVJNNjQgYnJpZGdlIERvY2tlciBpbWFnZVwiLFxuICAgIH0pXG5cbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCBcIkJyaWRnZUltYWdlWDg2VXJpXCIsIHtcbiAgICAgIHZhbHVlOiB4ODZJbWFnZS5pbWFnZVVyaSxcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkVDUiBVUkkgZm9yIHg4Nl82NCBicmlkZ2UgRG9ja2VyIGltYWdlXCIsXG4gICAgfSlcblxuICAgIHJldHVybiB7XG4gICAgICBhcm02NEltYWdlVXJpOiBhcm02NEltYWdlLmltYWdlVXJpLFxuICAgICAgeDg2SW1hZ2VVcmk6IHg4NkltYWdlLmltYWdlVXJpLFxuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Effect-based AppSync Events client for the daemon.
3
+ *
4
+ * Wraps the existing AppSync client with Effect primitives for better
5
+ * error handling and resource management.
6
+ */
7
+ import { Effect, Stream } from "effect";
8
+ import type { InvocationMessage, ResponseMessage } from "../../shared/types.js";
9
+ /**
10
+ * Configuration for the Effect AppSync client.
11
+ */
12
+ export interface AppSyncClientConfig {
13
+ httpEndpoint: string;
14
+ realtimeEndpoint: string;
15
+ region?: string;
16
+ }
17
+ /**
18
+ * Create an Effect-based AppSync Events client.
19
+ */
20
+ export declare const makeAppSyncClient: (config: AppSyncClientConfig) => {
21
+ publish: (channel: string, message: unknown) => Effect.Effect<void, Error, never>;
22
+ subscribe: <T>(channel: string) => Stream.Stream<T, Error, never>;
23
+ subscribeToInvocations: (channel: string) => Stream.Stream<InvocationMessage, Error, never>;
24
+ publishResponse: (channel: string, response: ResponseMessage) => Effect.Effect<void, Error, never>;
25
+ createSubscribeAuthorization: (channel: string) => Effect.Effect<Record<string, string>, Error, never>;
26
+ };
27
+ /**
28
+ * Type for the AppSync client.
29
+ */
30
+ export type AppSyncClient = ReturnType<typeof makeAppSyncClient>;