@mavogel/cdk-vscode-server 0.0.60 → 0.0.62

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 (55) hide show
  1. package/.claude/hooks/file_checker.sh +3 -0
  2. package/.jsii +454 -31
  3. package/API.md +514 -0
  4. package/README.md +57 -0
  5. package/assets/idle-monitor/idle-monitor.lambda/index.js +110 -0
  6. package/assets/status-check/status-check.lambda/index.js +123 -0
  7. package/examples/auto-stop/main.ts +75 -0
  8. package/integ-tests/functions/idle-test-handler.ts +178 -0
  9. package/integ-tests/functions/login-handler.ts +62 -33
  10. package/integ-tests/integ.al2023.ts.snapshot/read.13497.1.lock +1 -0
  11. package/integ-tests/integ.custom-domain.ts.snapshot/read.13497.1.lock +1 -0
  12. package/integ-tests/integ.stop-on-idle.ts +175 -0
  13. package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegStopOnIdleFunctionalityDefaultTestDeployAssertEECF3FC0.assets.json +33 -0
  14. package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegStopOnIdleFunctionalityDefaultTestDeployAssertEECF3FC0.template.json +692 -0
  15. package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegTestStackStopOnIdle.assets.json +146 -0
  16. package/integ-tests/integ.stop-on-idle.ts.snapshot/IntegTestStackStopOnIdle.template.json +3077 -0
  17. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d/index.js +1 -0
  18. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.33da23274e25bd9f43638c5d83dad26e3931cbe78d462ffd9a9f565e948b4f5f.lambda/index.js +143 -0
  19. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.530055f7515b3f0a47900f5df37e729ba40ca977b2d07b952bdefa2b8f883f42.bundle/index.js +30676 -0
  20. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.781ab0ab74634cdaf61539ab208ab777829ef07097ac21f95b9e15a3b1eedc1b.lambda/index.js +57 -0
  21. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200/__entrypoint__.js +1 -0
  22. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.7fa1e366ee8a9ded01fc355f704cff92bfd179574e6f9cfee800a3541df1b200/index.js +1 -0
  23. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.8dd4be31c5a6cd8750dc55c07c1e2f19596f8a27b032d02c18554ed44eabe065.lambda/index.js +110 -0
  24. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.9d043014be736e8162bcc7ec5590cc6d2ff24fd0d9c73a5c5d595151c5fdad00/index.js +1 -0
  25. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/cfn-response.js +1 -0
  26. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/consts.js +1 -0
  27. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/framework.js +3 -0
  28. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/outbound.js +1 -0
  29. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.bdc104ed9cab1b5b6421713c8155f0b753380595356f710400609664d3635eca/util.js +1 -0
  30. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.d061a1ca61c6339fcb77bb6fc19194a60c96bb16531eaf1e4e733b50089512ca/index.js +118 -0
  31. package/integ-tests/integ.stop-on-idle.ts.snapshot/asset.efac30c7091c58fed492058fa6403c14f7e58aab8cf4fd595d838b8d5eeec2b9/index.js +6017 -0
  32. package/integ-tests/integ.stop-on-idle.ts.snapshot/integ.json +20 -0
  33. package/integ-tests/integ.stop-on-idle.ts.snapshot/manifest.json +1942 -0
  34. package/integ-tests/integ.stop-on-idle.ts.snapshot/tree.json +1 -0
  35. package/integ-tests/integ.ubuntu.ts.snapshot/read.13497.1.lock +1 -0
  36. package/lib/idle-monitor/idle-monitor-function.d.ts +13 -0
  37. package/lib/idle-monitor/idle-monitor-function.js +22 -0
  38. package/lib/idle-monitor/idle-monitor.d.ts +53 -0
  39. package/lib/idle-monitor/idle-monitor.js +84 -0
  40. package/lib/idle-monitor/idle-monitor.lambda.d.ts +2 -0
  41. package/lib/idle-monitor/idle-monitor.lambda.js +97 -0
  42. package/lib/index.d.ts +2 -0
  43. package/lib/index.js +3 -1
  44. package/lib/status-check/status-check-function.d.ts +13 -0
  45. package/lib/status-check/status-check-function.js +22 -0
  46. package/lib/status-check/status-check.d.ts +36 -0
  47. package/lib/status-check/status-check.js +109 -0
  48. package/lib/status-check/status-check.lambda.d.ts +2 -0
  49. package/lib/status-check/status-check.lambda.js +104 -0
  50. package/lib/vscode-server.d.ts +42 -0
  51. package/lib/vscode-server.js +51 -7
  52. package/mavogelcdkvscodeserver/go.mod +1 -1
  53. package/mavogelcdkvscodeserver/jsii/jsii.go +2 -2
  54. package/mavogelcdkvscodeserver/version +1 -1
  55. package/package.json +21 -16
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = void 0;
4
+ const client_cloudwatch_1 = require("@aws-sdk/client-cloudwatch");
5
+ const client_ec2_1 = require("@aws-sdk/client-ec2");
6
+ const cloudwatch = new client_cloudwatch_1.CloudWatchClient({});
7
+ const ec2 = new client_ec2_1.EC2Client({});
8
+ const INSTANCE_ID = process.env.INSTANCE_ID;
9
+ const DISTRIBUTION_ID = process.env.DISTRIBUTION_ID;
10
+ const IDLE_TIMEOUT_MINUTES = parseInt(process.env.IDLE_TIMEOUT_MINUTES || '30');
11
+ const handler = async (event) => {
12
+ console.log('IdleMonitor triggered', { event, INSTANCE_ID, DISTRIBUTION_ID, IDLE_TIMEOUT_MINUTES });
13
+ try {
14
+ // 1. Get CloudFront request count for the idle timeout period
15
+ const endTime = new Date();
16
+ const startTime = new Date(endTime.getTime() - IDLE_TIMEOUT_MINUTES * 60 * 1000);
17
+ const metricsCommand = new client_cloudwatch_1.GetMetricStatisticsCommand({
18
+ Namespace: 'AWS/CloudFront',
19
+ MetricName: 'Requests',
20
+ Dimensions: [
21
+ {
22
+ Name: 'DistributionId',
23
+ Value: DISTRIBUTION_ID,
24
+ },
25
+ ],
26
+ StartTime: startTime,
27
+ EndTime: endTime,
28
+ Period: IDLE_TIMEOUT_MINUTES * 60,
29
+ Statistics: ['Sum'],
30
+ });
31
+ const metricsResponse = await cloudwatch.send(metricsCommand);
32
+ const requestCount = metricsResponse.Datapoints?.[0]?.Sum || 0;
33
+ console.log('CloudFront request count:', requestCount);
34
+ // 2. Get current instance state
35
+ const describeCommand = new client_ec2_1.DescribeInstancesCommand({
36
+ InstanceIds: [INSTANCE_ID],
37
+ });
38
+ const describeResponse = await ec2.send(describeCommand);
39
+ const instanceState = describeResponse.Reservations?.[0]?.Instances?.[0]?.State?.Name;
40
+ console.log('Current instance state:', instanceState);
41
+ // 3. Skip if instance is in a transitional state (starting, stopping, pending)
42
+ const transitionalStates = ['pending', 'stopping', 'shutting-down', 'rebooting'];
43
+ if (transitionalStates.includes(instanceState || '')) {
44
+ console.log(`Instance is in transitional state '${instanceState}', skipping idle check`);
45
+ return;
46
+ }
47
+ // 3.1 Skip if instance status checks are failing or initializing
48
+ // Can be disabled for integration tests via SKIP_STATUS_CHECKS env var
49
+ if (instanceState === 'running' && process.env.SKIP_STATUS_CHECKS !== 'true') {
50
+ const statusCommand = new client_ec2_1.DescribeInstanceStatusCommand({
51
+ InstanceIds: [INSTANCE_ID],
52
+ IncludeAllInstances: false, // Only return running instances with status info
53
+ });
54
+ const statusResponse = await ec2.send(statusCommand);
55
+ const instanceStatus = statusResponse.InstanceStatuses?.[0];
56
+ if (instanceStatus) {
57
+ const systemStatus = instanceStatus.SystemStatus?.Status;
58
+ const instanceCheckStatus = instanceStatus.InstanceStatus?.Status;
59
+ console.log('Instance status checks:', {
60
+ systemStatus,
61
+ instanceCheckStatus,
62
+ });
63
+ // Skip if any status check is not 'ok'
64
+ if (systemStatus !== 'ok' || instanceCheckStatus !== 'ok') {
65
+ console.log('Instance status checks are not passing, skipping idle check');
66
+ return;
67
+ }
68
+ }
69
+ else {
70
+ // No status information available yet (instance just started)
71
+ console.log('Instance status information not available yet, skipping idle check');
72
+ return;
73
+ }
74
+ }
75
+ else if (process.env.SKIP_STATUS_CHECKS === 'true' && instanceState === 'running') {
76
+ console.log('Status check verification skipped (SKIP_STATUS_CHECKS=true)');
77
+ }
78
+ // 4. If no requests and instance is running, stop it
79
+ if (requestCount === 0 && instanceState === 'running') {
80
+ console.log('No activity detected, stopping instance');
81
+ const stopCommand = new client_ec2_1.StopInstancesCommand({
82
+ InstanceIds: [INSTANCE_ID],
83
+ });
84
+ await ec2.send(stopCommand);
85
+ console.log('Instance stopped successfully');
86
+ }
87
+ else if (requestCount > 0) {
88
+ console.log('Activity detected, instance will remain running');
89
+ }
90
+ }
91
+ catch (error) {
92
+ console.error('Error in IdleMonitor:', error);
93
+ throw error;
94
+ }
95
+ };
96
+ exports.handler = handler;
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRsZS1tb25pdG9yLmxhbWJkYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pZGxlLW1vbml0b3IvaWRsZS1tb25pdG9yLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxrRUFBMEY7QUFDMUYsb0RBQStIO0FBRy9ILE1BQU0sVUFBVSxHQUFHLElBQUksb0NBQWdCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDNUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxzQkFBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBRTlCLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBWSxDQUFDO0FBQzdDLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZ0IsQ0FBQztBQUNyRCxNQUFNLG9CQUFvQixHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixJQUFJLElBQUksQ0FBQyxDQUFDO0FBRXpFLE1BQU0sT0FBTyxHQUFHLEtBQUssRUFBRSxLQUFxQixFQUFpQixFQUFFO0lBQ3BFLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxvQkFBb0IsRUFBRSxDQUFDLENBQUM7SUFFcEcsSUFBSSxDQUFDO1FBQ0gsOERBQThEO1FBQzlELE1BQU0sT0FBTyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDM0IsTUFBTSxTQUFTLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxHQUFHLG9CQUFvQixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUVqRixNQUFNLGNBQWMsR0FBRyxJQUFJLDhDQUEwQixDQUFDO1lBQ3BELFNBQVMsRUFBRSxnQkFBZ0I7WUFDM0IsVUFBVSxFQUFFLFVBQVU7WUFDdEIsVUFBVSxFQUFFO2dCQUNWO29CQUNFLElBQUksRUFBRSxnQkFBZ0I7b0JB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R0FBRyxDQUFDLDZEQUE2RCxDQUFDLENBQUM7UUFDN0UsQ0FBQztRQUVELHFEQUFxRDtRQUNyRCxJQUFJLFlBQVksS0FBSyxDQUFDLElBQUksYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3RELE9BQU8sQ0FBQyxHQUFHLENBQUMseUNBQXlDLENBQUMsQ0FBQztZQUV2RCxNQUFNLFdBQVcsR0FBRyxJQUFJLGlDQUFvQixDQUFDO2dCQUMzQyxXQUFXLEVBQUUsQ0FBQyxXQUFXLENBQUM7YUFDM0IsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRTVCLE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUMvQyxDQUFDO2FBQU0sSUFBSSxZQUFZLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDOUMsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBOUZXLFFBQUEsT0FBTyxXQThGbEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDbG91ZFdhdGNoQ2xpZW50LCBHZXRNZXRyaWNTdGF0aXN0aWNzQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZHdhdGNoJztcbmltcG9ydCB7IEVDMkNsaWVudCwgRGVzY3JpYmVJbnN0YW5jZXNDb21tYW5kLCBEZXNjcmliZUluc3RhbmNlU3RhdHVzQ29tbWFuZCwgU3RvcEluc3RhbmNlc0NvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtZWMyJztcbmltcG9ydCB0eXBlIHsgU2NoZWR1bGVkRXZlbnQgfSBmcm9tICdhd3MtbGFtYmRhJztcblxuY29uc3QgY2xvdWR3YXRjaCA9IG5ldyBDbG91ZFdhdGNoQ2xpZW50KHt9KTtcbmNvbnN0IGVjMiA9IG5ldyBFQzJDbGllbnQoe30pO1xuXG5jb25zdCBJTlNUQU5DRV9JRCA9IHByb2Nlc3MuZW52LklOU1RBTkNFX0lEITtcbmNvbnN0IERJU1RSSUJVVElPTl9JRCA9IHByb2Nlc3MuZW52LkRJU1RSSUJVVElPTl9JRCE7XG5jb25zdCBJRExFX1RJTUVPVVRfTUlOVVRFUyA9IHBhcnNlSW50KHByb2Nlc3MuZW52LklETEVfVElNRU9VVF9NSU5VVEVTIHx8ICczMCcpO1xuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jIChldmVudDogU2NoZWR1bGVkRXZlbnQpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc29sZS5sb2coJ0lkbGVNb25pdG9yIHRyaWdnZXJlZCcsIHsgZXZlbnQsIElOU1RBTkNFX0lELCBESVNUUklCVVRJT05fSUQsIElETEVfVElNRU9VVF9NSU5VVEVTIH0pO1xuXG4gIHRyeSB7XG4gICAgLy8gMS4gR2V0IENsb3VkRnJvbnQgcmVxdWVzdCBjb3VudCBmb3IgdGhlIGlkbGUgdGltZW91dCBwZXJpb2RcbiAgICBjb25zdCBlbmRUaW1lID0gbmV3IERhdGUoKTtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBuZXcgRGF0ZShlbmRUaW1lLmdldFRpbWUoKSAtIElETEVfVElNRU9VVF9NSU5VVEVTICogNjAgKiAxMDAwKTtcblxuICAgIGNvbnN0IG1ldHJpY3NDb21tYW5kID0gbmV3IEdldE1ldHJpY1N0YXRpc3RpY3NDb21tYW5kKHtcbiAgICAgIE5hbWVzcGFjZTogJ0FXUy9DbG91ZEZyb250JyxcbiAgICAgIE1ldHJpY05hbWU6ICdSZXF1ZXN0cycsXG4gICAgICBEaW1lbnNpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBOYW1lOiAnRGlzdHJpYnV0aW9uSWQnLFxuICAgICAgICAgIFZhbHVlOiBESVNUUklCVVRJT05fSUQsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgU3RhcnRUaW1lOiBzdGFydFRpbWUsXG4gICAgICBFbmRUaW1lOiBlbmRUaW1lLFxuICAgICAgUGVyaW9kOiBJRExFX1RJTUVPVVRfTUlOVVRFUyAqIDYwLFxuICAgICAgU3RhdGlzdGljczogWydTdW0nXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IG1ldHJpY3NSZXNwb25zZSA9IGF3YWl0IGNsb3Vkd2F0Y2guc2VuZChtZXRyaWNzQ29tbWFuZCk7XG4gICAgY29uc3QgcmVxdWVzdENvdW50ID0gbWV0cmljc1Jlc3BvbnNlLkRhdGFwb2ludHM/LlswXT8uU3VtIHx8IDA7XG5cbiAgICBjb25zb2xlLmxvZygnQ2xvdWRGcm9udCByZXF1ZXN0IGNvdW50OicsIHJlcXVlc3RDb3VudCk7XG5cbiAgICAvLyAyLiBHZXQgY3VycmVudCBpbnN0YW5jZSBzdGF0ZVxuICAgIGNvbnN0IGRlc2NyaWJlQ29tbWFuZCA9IG5ldyBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQoe1xuICAgICAgSW5zdGFuY2VJZHM6IFtJTlNUQU5DRV9JRF0sXG4gICAgfSk7XG4gICAgY29uc3QgZGVzY3JpYmVSZXNwb25zZSA9IGF3YWl0IGVjMi5zZW5kKGRlc2NyaWJlQ29tbWFuZCk7XG4gICAgY29uc3QgaW5zdGFuY2VTdGF0ZSA9IGRlc2NyaWJlUmVzcG9uc2UuUmVzZXJ2YXRpb25zPy5bMF0/Lkluc3RhbmNlcz8uWzBdPy5TdGF0ZT8uTmFtZTtcblxuICAgIGNvbnNvbGUubG9nKCdDdXJyZW50IGluc3RhbmNlIHN0YXRlOicsIGluc3RhbmNlU3RhdGUpO1xuXG4gICAgLy8gMy4gU2tpcCBpZiBpbnN0YW5jZSBpcyBpbiBhIHRyYW5zaXRpb25hbCBzdGF0ZSAoc3RhcnRpbmcsIHN0b3BwaW5nLCBwZW5kaW5nKVxuICAgIGNvbnN0IHRyYW5zaXRpb25hbFN0YXRlcyA9IFsncGVuZGluZycsICdzdG9wcGluZycsICdzaHV0dGluZy1kb3duJywgJ3JlYm9vdGluZyddO1xuICAgIGlmICh0cmFuc2l0aW9uYWxTdGF0ZXMuaW5jbHVkZXMoaW5zdGFuY2VTdGF0ZSB8fCAnJykpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBJbnN0YW5jZSBpcyBpbiB0cmFuc2l0aW9uYWwgc3RhdGUgJyR7aW5zdGFuY2VTdGF0ZX0nLCBza2lwcGluZyBpZGxlIGNoZWNrYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gMy4xIFNraXAgaWYgaW5zdGFuY2Ugc3RhdHVzIGNoZWNrcyBhcmUgZmFpbGluZyBvciBpbml0aWFsaXppbmdcbiAgICAvLyBDYW4gYmUgZGlzYWJsZWQgZm9yIGludGVncmF0aW9uIHRlc3RzIHZpYSBTS0lQX1NUQVRVU19DSEVDS1MgZW52IHZhclxuICAgIGlmIChpbnN0YW5jZVN0YXRlID09PSAncnVubmluZycgJiYgcHJvY2Vzcy5lbnYuU0tJUF9TVEFUVVNfQ0hFQ0tTICE9PSAndHJ1ZScpIHtcbiAgICAgIGNvbnN0IHN0YXR1c0NvbW1hbmQgPSBuZXcgRGVzY3JpYmVJbnN0YW5jZVN0YXR1c0NvbW1hbmQoe1xuICAgICAgICBJbnN0YW5jZUlkczogW0lOU1RBTkNFX0lEXSxcbiAgICAgICAgSW5jbHVkZUFsbEluc3RhbmNlczogZmFsc2UsIC8vIE9ubHkgcmV0dXJuIHJ1bm5pbmcgaW5zdGFuY2VzIHdpdGggc3RhdHVzIGluZm9cbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc3RhdHVzUmVzcG9uc2UgPSBhd2FpdCBlYzIuc2VuZChzdGF0dXNDb21tYW5kKTtcbiAgICAgIGNvbnN0IGluc3RhbmNlU3RhdHVzID0gc3RhdHVzUmVzcG9uc2UuSW5zdGFuY2VTdGF0dXNlcz8uWzBdO1xuXG4gICAgICBpZiAoaW5zdGFuY2VTdGF0dXMpIHtcbiAgICAgICAgY29uc3Qgc3lzdGVtU3RhdHVzID0gaW5zdGFuY2VTdGF0dXMuU3lzdGVtU3RhdHVzPy5TdGF0dXM7XG4gICAgICAgIGNvbnN0IGluc3RhbmNlQ2hlY2tTdGF0dXMgPSBpbnN0YW5jZVN0YXR1cy5JbnN0YW5jZVN0YXR1cz8uU3RhdHVzO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKCdJbnN0YW5jZSBzdGF0dXMgY2hlY2tzOicsIHtcbiAgICAgICAgICBzeXN0ZW1TdGF0dXMsXG4gICAgICAgICAgaW5zdGFuY2VDaGVja1N0YXR1cyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2tpcCBpZiBhbnkgc3RhdHVzIGNoZWNrIGlzIG5vdCAnb2snXG4gICAgICAgIGlmIChzeXN0ZW1TdGF0dXMgIT09ICdvaycgfHwgaW5zdGFuY2VDaGVja1N0YXR1cyAhPT0gJ29rJykge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdJbnN0YW5jZSBzdGF0dXMgY2hlY2tzIGFyZSBub3QgcGFzc2luZywgc2tpcHBpbmcgaWRsZSBjaGVjaycpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTm8gc3RhdHVzIGluZm9ybWF0aW9uIGF2YWlsYWJsZSB5ZXQgKGluc3RhbmNlIGp1c3Qgc3RhcnRlZClcbiAgICAgICAgY29uc29sZS5sb2coJ0luc3RhbmNlIHN0YXR1cyBpbmZvcm1hdGlvbiBub3QgYXZhaWxhYmxlIHlldCwgc2tpcHBpbmcgaWRsZSBjaGVjaycpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwcm9jZXNzLmVudi5TS0lQX1NUQVRVU19DSEVDS1MgPT09ICd0cnVlJyAmJiBpbnN0YW5jZVN0YXRlID09PSAncnVubmluZycpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdTdGF0dXMgY2hlY2sgdmVyaWZpY2F0aW9uIHNraXBwZWQgKFNLSVBfU1RBVFVTX0NIRUNLUz10cnVlKScpO1xuICAgIH1cblxuICAgIC8vIDQuIElmIG5vIHJlcXVlc3RzIGFuZCBpbnN0YW5jZSBpcyBydW5uaW5nLCBzdG9wIGl0XG4gICAgaWYgKHJlcXVlc3RDb3VudCA9PT0gMCAmJiBpbnN0YW5jZVN0YXRlID09PSAncnVubmluZycpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdObyBhY3Rpdml0eSBkZXRlY3RlZCwgc3RvcHBpbmcgaW5zdGFuY2UnKTtcblxuICAgICAgY29uc3Qgc3RvcENvbW1hbmQgPSBuZXcgU3RvcEluc3RhbmNlc0NvbW1hbmQoe1xuICAgICAgICBJbnN0YW5jZUlkczogW0lOU1RBTkNFX0lEXSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgZWMyLnNlbmQoc3RvcENvbW1hbmQpO1xuXG4gICAgICBjb25zb2xlLmxvZygnSW5zdGFuY2Ugc3RvcHBlZCBzdWNjZXNzZnVsbHknKTtcbiAgICB9IGVsc2UgaWYgKHJlcXVlc3RDb3VudCA+IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKCdBY3Rpdml0eSBkZXRlY3RlZCwgaW5zdGFuY2Ugd2lsbCByZW1haW4gcnVubmluZycpO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBpbiBJZGxlTW9uaXRvcjonLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn07XG4iXX0=
package/lib/index.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export * from './vscode-server';
2
+ export * from './idle-monitor/idle-monitor';
3
+ export * from './status-check/status-check';
package/lib/index.js CHANGED
@@ -15,4 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./vscode-server"), exports);
18
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGtEQUFnQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vdnNjb2RlLXNlcnZlcic7XG4iXX0=
18
+ __exportStar(require("./idle-monitor/idle-monitor"), exports);
19
+ __exportStar(require("./status-check/status-check"), exports);
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGtEQUFnQztBQUNoQyw4REFBNEM7QUFDNUMsOERBQTRDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi92c2NvZGUtc2VydmVyJztcbmV4cG9ydCAqIGZyb20gJy4vaWRsZS1tb25pdG9yL2lkbGUtbW9uaXRvcic7XG5leHBvcnQgKiBmcm9tICcuL3N0YXR1cy1jaGVjay9zdGF0dXMtY2hlY2snO1xuIl19
@@ -0,0 +1,13 @@
1
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import { Construct } from 'constructs';
3
+ /**
4
+ * Props for StatusCheckFunction
5
+ */
6
+ export interface StatusCheckFunctionProps extends lambda.FunctionOptions {
7
+ }
8
+ /**
9
+ * An AWS Lambda function which executes src/status-check/status-check.
10
+ */
11
+ export declare class StatusCheckFunction extends lambda.Function {
12
+ constructor(scope: Construct, id: string, props?: StatusCheckFunctionProps);
13
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StatusCheckFunction = void 0;
4
+ // ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
5
+ const path = require("path");
6
+ const lambda = require("aws-cdk-lib/aws-lambda");
7
+ /**
8
+ * An AWS Lambda function which executes src/status-check/status-check.
9
+ */
10
+ class StatusCheckFunction extends lambda.Function {
11
+ constructor(scope, id, props) {
12
+ super(scope, id, {
13
+ description: 'src/status-check/status-check.lambda.ts',
14
+ ...props,
15
+ runtime: new lambda.Runtime('nodejs20.x', lambda.RuntimeFamily.NODEJS),
16
+ handler: 'index.handler',
17
+ code: lambda.Code.fromAsset(path.join(__dirname, '../../assets/status-check/status-check.lambda')),
18
+ });
19
+ }
20
+ }
21
+ exports.StatusCheckFunction = StatusCheckFunction;
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHVzLWNoZWNrLWZ1bmN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0YXR1cy1jaGVjay9zdGF0dXMtY2hlY2stZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkVBQTZFO0FBQzdFLDZCQUE2QjtBQUM3QixpREFBaUQ7QUFTakQ7O0dBRUc7QUFDSCxNQUFhLG1CQUFvQixTQUFRLE1BQU0sQ0FBQyxRQUFRO0lBQ3RELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBZ0M7UUFDeEUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixXQUFXLEVBQUUseUNBQXlDO1lBQ3RELEdBQUcsS0FBSztZQUNSLE9BQU8sRUFBRSxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDO1lBQ3RFLE9BQU8sRUFBRSxlQUFlO1lBQ3hCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDO1NBQ25HLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQVZELGtEQVVDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gfn4gR2VuZXJhdGVkIGJ5IHByb2plbi4gVG8gbW9kaWZ5LCBlZGl0IC5wcm9qZW5yYy50cyBhbmQgcnVuIFwibnB4IHByb2plblwiLlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFByb3BzIGZvciBTdGF0dXNDaGVja0Z1bmN0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdHVzQ2hlY2tGdW5jdGlvblByb3BzIGV4dGVuZHMgbGFtYmRhLkZ1bmN0aW9uT3B0aW9ucyB7XG59XG5cbi8qKlxuICogQW4gQVdTIExhbWJkYSBmdW5jdGlvbiB3aGljaCBleGVjdXRlcyBzcmMvc3RhdHVzLWNoZWNrL3N0YXR1cy1jaGVjay5cbiAqL1xuZXhwb3J0IGNsYXNzIFN0YXR1c0NoZWNrRnVuY3Rpb24gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86IFN0YXR1c0NoZWNrRnVuY3Rpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgZGVzY3JpcHRpb246ICdzcmMvc3RhdHVzLWNoZWNrL3N0YXR1cy1jaGVjay5sYW1iZGEudHMnLFxuICAgICAgLi4ucHJvcHMsXG4gICAgICBydW50aW1lOiBuZXcgbGFtYmRhLlJ1bnRpbWUoJ25vZGVqczIwLngnLCBsYW1iZGEuUnVudGltZUZhbWlseS5OT0RFSlMpLFxuICAgICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInLFxuICAgICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi9hc3NldHMvc3RhdHVzLWNoZWNrL3N0YXR1cy1jaGVjay5sYW1iZGEnKSksXG4gICAgfSk7XG4gIH1cbn0iXX0=
@@ -0,0 +1,36 @@
1
+ import { RestApi } from 'aws-cdk-lib/aws-apigateway';
2
+ import { ITable } from 'aws-cdk-lib/aws-dynamodb';
3
+ import { IInstance } from 'aws-cdk-lib/aws-ec2';
4
+ import { Function as LambdaFunction } from 'aws-cdk-lib/aws-lambda';
5
+ import { Construct } from 'constructs';
6
+ /**
7
+ * Props for StatusCheckApi construct
8
+ */
9
+ export interface StatusCheckApiProps {
10
+ /**
11
+ * The EC2 instance to check status for
12
+ */
13
+ readonly instance: IInstance;
14
+ /**
15
+ * DynamoDB table for tracking instance state
16
+ */
17
+ readonly stateTable: ITable;
18
+ }
19
+ /**
20
+ * API Gateway endpoint for checking instance status, used by resume page for polling
21
+ */
22
+ export declare class StatusCheckApi extends Construct {
23
+ /**
24
+ * The API Gateway REST API
25
+ */
26
+ readonly api: RestApi;
27
+ /**
28
+ * The URL of the status check API endpoint
29
+ */
30
+ readonly apiUrl: string;
31
+ /**
32
+ * The Lambda function that handles status check requests
33
+ */
34
+ readonly function: LambdaFunction;
35
+ constructor(scope: Construct, id: string, props: StatusCheckApiProps);
36
+ }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.StatusCheckApi = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ const path = require("path");
7
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
8
+ const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
9
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
10
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
11
+ const cdk_nag_1 = require("cdk-nag");
12
+ const constructs_1 = require("constructs");
13
+ /**
14
+ * API Gateway endpoint for checking instance status, used by resume page for polling
15
+ */
16
+ class StatusCheckApi extends constructs_1.Construct {
17
+ constructor(scope, id, props) {
18
+ super(scope, id);
19
+ this.function = new aws_lambda_1.Function(this, 'Function', {
20
+ runtime: aws_lambda_1.Runtime.NODEJS_20_X,
21
+ handler: 'index.handler',
22
+ code: aws_lambda_1.Code.fromAsset(path.join(__dirname, '../../assets/status-check/status-check.lambda')),
23
+ timeout: aws_cdk_lib_1.Duration.seconds(10),
24
+ memorySize: 128,
25
+ environment: {
26
+ TABLE_NAME: props.stateTable.tableName,
27
+ },
28
+ });
29
+ // Grant permissions
30
+ props.stateTable.grantReadWriteData(this.function);
31
+ this.function.addToRolePolicy(new aws_iam_1.PolicyStatement({
32
+ actions: [
33
+ 'ec2:DescribeInstanceStatus',
34
+ 'ec2:DescribeInstances',
35
+ 'ec2:StartInstances', // Allow starting instances for resume functionality
36
+ ],
37
+ resources: [
38
+ `arn:aws:ec2:${aws_cdk_lib_1.Stack.of(this).region}:${aws_cdk_lib_1.Stack.of(this).account}:instance/${props.instance.instanceId}`,
39
+ ],
40
+ }));
41
+ // Create API Gateway
42
+ this.api = new aws_apigateway_1.RestApi(this, 'Api', {
43
+ restApiName: 'VSCodeStatusCheckApi',
44
+ description: 'API for checking VS Code Server instance status',
45
+ defaultCorsPreflightOptions: {
46
+ allowOrigins: aws_apigateway_1.Cors.ALL_ORIGINS,
47
+ allowMethods: aws_apigateway_1.Cors.ALL_METHODS,
48
+ },
49
+ });
50
+ const statusResource = this.api.root.addResource('status');
51
+ const instanceResource = statusResource.addResource('{instanceId}');
52
+ // GET /status/{instanceId} - Check instance status
53
+ instanceResource.addMethod('GET', new aws_apigateway_1.LambdaIntegration(this.function));
54
+ // POST /status/{instanceId}/start - Start stopped instance
55
+ const startResource = instanceResource.addResource('start');
56
+ startResource.addMethod('POST', new aws_apigateway_1.LambdaIntegration(this.function));
57
+ this.apiUrl = this.api.url;
58
+ // CDK-nag suppressions
59
+ cdk_nag_1.NagSuppressions.addResourceSuppressions(this.function, [
60
+ {
61
+ id: 'AwsSolutions-IAM4',
62
+ reason: 'Managed policies acceptable for workshop Lambda functions',
63
+ },
64
+ {
65
+ id: 'AwsSolutions-L1',
66
+ reason: 'Latest runtime not required for this function',
67
+ },
68
+ ], true);
69
+ cdk_nag_1.NagSuppressions.addResourceSuppressions(this.api, [
70
+ {
71
+ id: 'AwsSolutions-APIG2',
72
+ reason: 'Request validation not required for this simple API',
73
+ },
74
+ {
75
+ id: 'AwsSolutions-IAM4',
76
+ reason: 'Managed policies acceptable for workshop API Gateway',
77
+ },
78
+ {
79
+ id: 'AwsSolutions-APIG4',
80
+ reason: 'Authorization not required for status check endpoint',
81
+ },
82
+ {
83
+ id: 'AwsSolutions-COG4',
84
+ reason: 'Cognito not required for this workshop API',
85
+ },
86
+ {
87
+ id: 'AwsSolutions-APIG1',
88
+ reason: 'Access logging not required for workshop environment',
89
+ },
90
+ {
91
+ id: 'AwsSolutions-APIG3',
92
+ reason: 'WAF not required for this workshop API',
93
+ },
94
+ {
95
+ id: 'AwsSolutions-APIG6',
96
+ reason: 'CloudWatch logging not required for workshop environment',
97
+ },
98
+ {
99
+ id: 'AwsSolutions-IAM5',
100
+ reason: 'Wildcard permissions acceptable for workshop API Gateway execution role',
101
+ appliesTo: ['Resource::*'],
102
+ },
103
+ ], true);
104
+ }
105
+ }
106
+ exports.StatusCheckApi = StatusCheckApi;
107
+ _a = JSII_RTTI_SYMBOL_1;
108
+ StatusCheckApi[_a] = { fqn: "@mavogel/cdk-vscode-server.StatusCheckApi", version: "0.0.62" };
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHVzLWNoZWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0YXR1cy1jaGVjay9zdGF0dXMtY2hlY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFDN0IsNkNBQThDO0FBQzlDLCtEQUE4RTtBQUc5RSxpREFBc0Q7QUFDdEQsdURBQW1GO0FBQ25GLHFDQUEwQztBQUMxQywyQ0FBdUM7QUFnQnZDOztHQUVHO0FBQ0gsTUFBYSxjQUFlLFNBQVEsc0JBQVM7SUFjM0MsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUEwQjtRQUNsRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxxQkFBYyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDbkQsT0FBTyxFQUFFLG9CQUFPLENBQUMsV0FBVztZQUM1QixPQUFPLEVBQUUsZUFBZTtZQUN4QixJQUFJLEVBQUUsaUJBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsK0NBQStDLENBQUMsQ0FBQztZQUMzRixPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzdCLFVBQVUsRUFBRSxHQUFHO1lBQ2YsV0FBVyxFQUFFO2dCQUNYLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLFNBQVM7YUFDdkM7U0FDRixDQUFDLENBQUM7UUFFSCxvQkFBb0I7UUFDcEIsS0FBSyxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQzNCLElBQUkseUJBQWUsQ0FBQztZQUNsQixPQUFPLEVBQUU7Z0JBQ1AsNEJBQTRCO2dCQUM1Qix1QkFBdUI7Z0JBQ3ZCLG9CQUFvQixFQUFFLG9EQUFvRDthQUMzRTtZQUNELFNBQVMsRUFBRTtnQkFDVCxlQUFlLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLGFBQWEsS0FBSyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUU7YUFDdkc7U0FDRixDQUFDLENBQ0gsQ0FBQztRQUVGLHFCQUFxQjtRQUNyQixJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksd0JBQU8sQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO1lBQ2xDLFdBQVcsRUFBRSxzQkFBc0I7WUFDbkMsV0FBVyxFQUFFLGlEQUFpRDtZQUM5RCwyQkFBMkIsRUFBRTtnQkFDM0IsWUFBWSxFQUFFLHFCQUFJLENBQUMsV0FBVztnQkFDOUIsWUFBWSxFQUFFLHFCQUFJLENBQUMsV0FBVzthQUMvQjtTQUNGLENBQUMsQ0FBQztRQUVILE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzRCxNQUFNLGdCQUFnQixHQUFHLGNBQWMsQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFcEUsbURBQW1EO1FBQ25ELGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxrQ0FBaUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUV4RSwyREFBMkQ7UUFDM0QsTUFBTSxhQUFhLEdBQUcsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzVELGFBQWEsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksa0NBQWlCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFFdEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztRQUUzQix1QkFBdUI7UUFDdkIseUJBQWUsQ0FBQyx1QkFBdUIsQ0FDckMsSUFBSSxDQUFDLFFBQVEsRUFDYjtZQUNFO2dCQUNFLEVBQUUsRUFBRSxtQkFBbUI7Z0JBQ3ZCLE1BQU0sRUFBRSwyREFBMkQ7YUFDcEU7WUFDRDtnQkFDRSxFQUFFLEVBQUUsaUJBQWlCO2dCQUNyQixNQUFNLEVBQUUsK0NBQStDO2FBQ3hEO1NBQ0YsRUFDRCxJQUFJLENBQ0wsQ0FBQztRQUVGLHlCQUFlLENBQUMsdUJBQXVCLENBQ3JDLElBQUksQ0FBQyxHQUFHLEVBQ1I7WUFDRTtnQkFDRSxFQUFFLEVBQUUsb0JBQW9CO2dCQUN4QixNQUFNLEVBQUUscURBQXFEO2FBQzlEO1lBQ0Q7Z0JBQ0UsRUFBRSxFQUFFLG1CQUFtQjtnQkFDdkIsTUFBTSxFQUFFLHNEQUFzRDthQUMvRDtZQUNEO2dCQUNFLEVBQUUsRUFBRSxvQkFBb0I7Z0JBQ3hCLE1BQU0sRUFBRSxzREFBc0Q7YUFDL0Q7WUFDRDtnQkFDRSxFQUFFLEVBQUUsbUJBQW1CO2dCQUN2QixNQUFNLEVBQUUsNENBQTRDO2FBQ3JEO1lBQ0Q7Z0JBQ0UsRUFBRSxFQUFFLG9CQUFvQjtnQkFDeEIsTUFBTSxFQUFFLHNEQUFzRDthQUMvRDtZQUNEO2dCQUNFLEVBQUUsRUFBRSxvQkFBb0I7Z0JBQ3hCLE1BQU0sRUFBRSx3Q0FBd0M7YUFDakQ7WUFDRDtnQkFDRSxFQUFFLEVBQUUsb0JBQW9CO2dCQUN4QixNQUFNLEVBQUUsMERBQTBEO2FBQ25FO1lBQ0Q7Z0JBQ0UsRUFBRSxFQUFFLG1CQUFtQjtnQkFDdkIsTUFBTSxFQUFFLHlFQUF5RTtnQkFDakYsU0FBUyxFQUFFLENBQUMsYUFBYSxDQUFDO2FBQzNCO1NBQ0YsRUFDRCxJQUFJLENBQ0wsQ0FBQztJQUNKLENBQUM7O0FBekhILHdDQTBIQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBEdXJhdGlvbiwgU3RhY2sgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBSZXN0QXBpLCBMYW1iZGFJbnRlZ3JhdGlvbiwgQ29ycyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1hcGlnYXRld2F5JztcbmltcG9ydCB7IElUYWJsZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1keW5hbW9kYic7XG5pbXBvcnQgeyBJSW5zdGFuY2UgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCB7IFBvbGljeVN0YXRlbWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgUnVudGltZSwgQ29kZSwgRnVuY3Rpb24gYXMgTGFtYmRhRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IE5hZ1N1cHByZXNzaW9ucyB9IGZyb20gJ2Nkay1uYWcnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbi8qKlxuICogUHJvcHMgZm9yIFN0YXR1c0NoZWNrQXBpIGNvbnN0cnVjdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YXR1c0NoZWNrQXBpUHJvcHMge1xuICAvKipcbiAgICogVGhlIEVDMiBpbnN0YW5jZSB0byBjaGVjayBzdGF0dXMgZm9yXG4gICAqL1xuICByZWFkb25seSBpbnN0YW5jZTogSUluc3RhbmNlO1xuICAvKipcbiAgICogRHluYW1vREIgdGFibGUgZm9yIHRyYWNraW5nIGluc3RhbmNlIHN0YXRlXG4gICAqL1xuICByZWFkb25seSBzdGF0ZVRhYmxlOiBJVGFibGU7XG59XG5cbi8qKlxuICogQVBJIEdhdGV3YXkgZW5kcG9pbnQgZm9yIGNoZWNraW5nIGluc3RhbmNlIHN0YXR1cywgdXNlZCBieSByZXN1bWUgcGFnZSBmb3IgcG9sbGluZ1xuICovXG5leHBvcnQgY2xhc3MgU3RhdHVzQ2hlY2tBcGkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogVGhlIEFQSSBHYXRld2F5IFJFU1QgQVBJXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYXBpOiBSZXN0QXBpO1xuICAvKipcbiAgICogVGhlIFVSTCBvZiB0aGUgc3RhdHVzIGNoZWNrIEFQSSBlbmRwb2ludFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFwaVVybDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIExhbWJkYSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgc3RhdHVzIGNoZWNrIHJlcXVlc3RzXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZnVuY3Rpb246IExhbWJkYUZ1bmN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTdGF0dXNDaGVja0FwaVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHRoaXMuZnVuY3Rpb24gPSBuZXcgTGFtYmRhRnVuY3Rpb24odGhpcywgJ0Z1bmN0aW9uJywge1xuICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMjBfWCxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIGNvZGU6IENvZGUuZnJvbUFzc2V0KHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi9hc3NldHMvc3RhdHVzLWNoZWNrL3N0YXR1cy1jaGVjay5sYW1iZGEnKSksXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDEwKSxcbiAgICAgIG1lbW9yeVNpemU6IDEyOCxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIFRBQkxFX05BTUU6IHByb3BzLnN0YXRlVGFibGUudGFibGVOYW1lLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIEdyYW50IHBlcm1pc3Npb25zXG4gICAgcHJvcHMuc3RhdGVUYWJsZS5ncmFudFJlYWRXcml0ZURhdGEodGhpcy5mdW5jdGlvbik7XG5cbiAgICB0aGlzLmZ1bmN0aW9uLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ2VjMjpEZXNjcmliZUluc3RhbmNlU3RhdHVzJyxcbiAgICAgICAgICAnZWMyOkRlc2NyaWJlSW5zdGFuY2VzJyxcbiAgICAgICAgICAnZWMyOlN0YXJ0SW5zdGFuY2VzJywgLy8gQWxsb3cgc3RhcnRpbmcgaW5zdGFuY2VzIGZvciByZXN1bWUgZnVuY3Rpb25hbGl0eVxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICBgYXJuOmF3czplYzI6JHtTdGFjay5vZih0aGlzKS5yZWdpb259OiR7U3RhY2sub2YodGhpcykuYWNjb3VudH06aW5zdGFuY2UvJHtwcm9wcy5pbnN0YW5jZS5pbnN0YW5jZUlkfWAsXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgLy8gQ3JlYXRlIEFQSSBHYXRld2F5XG4gICAgdGhpcy5hcGkgPSBuZXcgUmVzdEFwaSh0aGlzLCAnQXBpJywge1xuICAgICAgcmVzdEFwaU5hbWU6ICdWU0NvZGVTdGF0dXNDaGVja0FwaScsXG4gICAgICBkZXNjcmlwdGlvbjogJ0FQSSBmb3IgY2hlY2tpbmcgVlMgQ29kZSBTZXJ2ZXIgaW5zdGFuY2Ugc3RhdHVzJyxcbiAgICAgIGRlZmF1bHRDb3JzUHJlZmxpZ2h0T3B0aW9uczoge1xuICAgICAgICBhbGxvd09yaWdpbnM6IENvcnMuQUxMX09SSUdJTlMsXG4gICAgICAgIGFsbG93TWV0aG9kczogQ29ycy5BTExfTUVUSE9EUyxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBzdGF0dXNSZXNvdXJjZSA9IHRoaXMuYXBpLnJvb3QuYWRkUmVzb3VyY2UoJ3N0YXR1cycpO1xuICAgIGNvbnN0IGluc3RhbmNlUmVzb3VyY2UgPSBzdGF0dXNSZXNvdXJjZS5hZGRSZXNvdXJjZSgne2luc3RhbmNlSWR9Jyk7XG5cbiAgICAvLyBHRVQgL3N0YXR1cy97aW5zdGFuY2VJZH0gLSBDaGVjayBpbnN0YW5jZSBzdGF0dXNcbiAgICBpbnN0YW5jZVJlc291cmNlLmFkZE1ldGhvZCgnR0VUJywgbmV3IExhbWJkYUludGVncmF0aW9uKHRoaXMuZnVuY3Rpb24pKTtcblxuICAgIC8vIFBPU1QgL3N0YXR1cy97aW5zdGFuY2VJZH0vc3RhcnQgLSBTdGFydCBzdG9wcGVkIGluc3RhbmNlXG4gICAgY29uc3Qgc3RhcnRSZXNvdXJjZSA9IGluc3RhbmNlUmVzb3VyY2UuYWRkUmVzb3VyY2UoJ3N0YXJ0Jyk7XG4gICAgc3RhcnRSZXNvdXJjZS5hZGRNZXRob2QoJ1BPU1QnLCBuZXcgTGFtYmRhSW50ZWdyYXRpb24odGhpcy5mdW5jdGlvbikpO1xuXG4gICAgdGhpcy5hcGlVcmwgPSB0aGlzLmFwaS51cmw7XG5cbiAgICAvLyBDREstbmFnIHN1cHByZXNzaW9uc1xuICAgIE5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9ucyhcbiAgICAgIHRoaXMuZnVuY3Rpb24sXG4gICAgICBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU00JyxcbiAgICAgICAgICByZWFzb246ICdNYW5hZ2VkIHBvbGljaWVzIGFjY2VwdGFibGUgZm9yIHdvcmtzaG9wIExhbWJkYSBmdW5jdGlvbnMnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICdBd3NTb2x1dGlvbnMtTDEnLFxuICAgICAgICAgIHJlYXNvbjogJ0xhdGVzdCBydW50aW1lIG5vdCByZXF1aXJlZCBmb3IgdGhpcyBmdW5jdGlvbicsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgdHJ1ZSxcbiAgICApO1xuXG4gICAgTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zKFxuICAgICAgdGhpcy5hcGksXG4gICAgICBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJ0F3c1NvbHV0aW9ucy1BUElHMicsXG4gICAgICAgICAgcmVhc29uOiAnUmVxdWVzdCB2YWxpZGF0aW9uIG5vdCByZXF1aXJlZCBmb3IgdGhpcyBzaW1wbGUgQVBJJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnQXdzU29sdXRpb25zLUlBTTQnLFxuICAgICAgICAgIHJlYXNvbjogJ01hbmFnZWQgcG9saWNpZXMgYWNjZXB0YWJsZSBmb3Igd29ya3Nob3AgQVBJIEdhdGV3YXknLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICdBd3NTb2x1dGlvbnMtQVBJRzQnLFxuICAgICAgICAgIHJlYXNvbjogJ0F1dGhvcml6YXRpb24gbm90IHJlcXVpcmVkIGZvciBzdGF0dXMgY2hlY2sgZW5kcG9pbnQnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICdBd3NTb2x1dGlvbnMtQ09HNCcsXG4gICAgICAgICAgcmVhc29uOiAnQ29nbml0byBub3QgcmVxdWlyZWQgZm9yIHRoaXMgd29ya3Nob3AgQVBJJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnQXdzU29sdXRpb25zLUFQSUcxJyxcbiAgICAgICAgICByZWFzb246ICdBY2Nlc3MgbG9nZ2luZyBub3QgcmVxdWlyZWQgZm9yIHdvcmtzaG9wIGVudmlyb25tZW50JyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnQXdzU29sdXRpb25zLUFQSUczJyxcbiAgICAgICAgICByZWFzb246ICdXQUYgbm90IHJlcXVpcmVkIGZvciB0aGlzIHdvcmtzaG9wIEFQSScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJ0F3c1NvbHV0aW9ucy1BUElHNicsXG4gICAgICAgICAgcmVhc29uOiAnQ2xvdWRXYXRjaCBsb2dnaW5nIG5vdCByZXF1aXJlZCBmb3Igd29ya3Nob3AgZW52aXJvbm1lbnQnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICdBd3NTb2x1dGlvbnMtSUFNNScsXG4gICAgICAgICAgcmVhc29uOiAnV2lsZGNhcmQgcGVybWlzc2lvbnMgYWNjZXB0YWJsZSBmb3Igd29ya3Nob3AgQVBJIEdhdGV3YXkgZXhlY3V0aW9uIHJvbGUnLFxuICAgICAgICAgIGFwcGxpZXNUbzogWydSZXNvdXJjZTo6KiddLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHRydWUsXG4gICAgKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,2 @@
1
+ import type { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
2
+ export declare const handler: (event: APIGatewayProxyEvent) => Promise<APIGatewayProxyResult>;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = void 0;
4
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
5
+ const client_ec2_1 = require("@aws-sdk/client-ec2");
6
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
7
+ const ec2 = new client_ec2_1.EC2Client({});
8
+ const ddbClient = new client_dynamodb_1.DynamoDBClient({});
9
+ const ddb = lib_dynamodb_1.DynamoDBDocumentClient.from(ddbClient);
10
+ const TABLE_NAME = process.env.TABLE_NAME;
11
+ const handler = async (event) => {
12
+ console.log('StatusCheck/Start triggered', { event });
13
+ const instanceId = event.pathParameters?.instanceId;
14
+ const isStartRequest = event.resource?.includes('/start') && event.httpMethod === 'POST';
15
+ if (!instanceId) {
16
+ return {
17
+ statusCode: 400,
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'Access-Control-Allow-Origin': '*',
21
+ },
22
+ body: JSON.stringify({ error: 'Missing instanceId' }),
23
+ };
24
+ }
25
+ try {
26
+ // Handle POST /status/{instanceId}/start - Start instance
27
+ if (isStartRequest) {
28
+ console.log('Starting instance:', instanceId);
29
+ const startCommand = new client_ec2_1.StartInstancesCommand({
30
+ InstanceIds: [instanceId],
31
+ });
32
+ await ec2.send(startCommand);
33
+ // Update DynamoDB state
34
+ await ddb.send(new lib_dynamodb_1.UpdateCommand({
35
+ TableName: TABLE_NAME,
36
+ Key: { instanceId },
37
+ UpdateExpression: 'SET instanceState = :state, lastActivityTime = :time',
38
+ ExpressionAttributeValues: {
39
+ ':state': 'starting',
40
+ ':time': new Date().toISOString(),
41
+ },
42
+ }));
43
+ return {
44
+ statusCode: 200,
45
+ headers: {
46
+ 'Content-Type': 'application/json',
47
+ 'Access-Control-Allow-Origin': '*',
48
+ },
49
+ body: JSON.stringify({
50
+ message: 'Instance start initiated',
51
+ state: 'starting',
52
+ instanceId,
53
+ }),
54
+ };
55
+ }
56
+ // Handle GET /status/{instanceId} - Check status
57
+ const statusCommand = new client_ec2_1.DescribeInstanceStatusCommand({
58
+ InstanceIds: [instanceId],
59
+ IncludeAllInstances: true,
60
+ });
61
+ const statusResponse = await ec2.send(statusCommand);
62
+ const instanceStatus = statusResponse.InstanceStatuses?.[0];
63
+ const state = instanceStatus?.InstanceState?.Name || 'unknown';
64
+ console.log('Instance state:', state);
65
+ // If running, update DynamoDB
66
+ if (state === 'running') {
67
+ await ddb.send(new lib_dynamodb_1.UpdateCommand({
68
+ TableName: TABLE_NAME,
69
+ Key: { instanceId },
70
+ UpdateExpression: 'SET instanceState = :state, lastActivityTime = :time',
71
+ ExpressionAttributeValues: {
72
+ ':state': 'running',
73
+ ':time': new Date().toISOString(),
74
+ },
75
+ }));
76
+ }
77
+ return {
78
+ statusCode: 200,
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ 'Access-Control-Allow-Origin': '*',
82
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
83
+ },
84
+ body: JSON.stringify({
85
+ state,
86
+ ready: state === 'running',
87
+ instanceId,
88
+ }),
89
+ };
90
+ }
91
+ catch (error) {
92
+ console.error('Error in status check/start:', error);
93
+ return {
94
+ statusCode: 500,
95
+ headers: {
96
+ 'Content-Type': 'application/json',
97
+ 'Access-Control-Allow-Origin': '*',
98
+ },
99
+ body: JSON.stringify({ error: 'Internal server error' }),
100
+ };
101
+ }
102
+ };
103
+ exports.handler = handler;
104
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHVzLWNoZWNrLmxhbWJkYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdGF0dXMtY2hlY2svc3RhdHVzLWNoZWNrLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw4REFBMEQ7QUFDMUQsb0RBQXNHO0FBQ3RHLHdEQUE4RTtBQUc5RSxNQUFNLEdBQUcsR0FBRyxJQUFJLHNCQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxnQ0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3pDLE1BQU0sR0FBRyxHQUFHLHFDQUFzQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUVuRCxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVcsQ0FBQztBQUVwQyxNQUFNLE9BQU8sR0FBRyxLQUFLLEVBQzFCLEtBQTJCLEVBQ0ssRUFBRTtJQUNsQyxPQUFPLENBQUMsR0FBRyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUV0RCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsY0FBYyxFQUFFLFVBQVUsQ0FBQztJQUNwRCxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLE1BQU0sQ0FBQztJQUV6RixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEIsT0FBTztZQUNMLFVBQVUsRUFBRSxHQUFHO1lBQ2YsT0FBTyxFQUFFO2dCQUNQLGNBQWMsRUFBRSxrQkFBa0I7Z0JBQ2xDLDZCQUE2QixFQUFFLEdBQUc7YUFDbkM7WUFDRCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxDQUFDO1NBQ3RELENBQUM7SUFDSixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsMERBQTBE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QUMsRUFBRSxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQztTQUN6RCxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQztBQXpHVyxRQUFBLE9BQU8sV0F5R2xCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHluYW1vREJDbGllbnQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtZHluYW1vZGInO1xuaW1wb3J0IHsgRUMyQ2xpZW50LCBEZXNjcmliZUluc3RhbmNlU3RhdHVzQ29tbWFuZCwgU3RhcnRJbnN0YW5jZXNDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVjMic7XG5pbXBvcnQgeyBEeW5hbW9EQkRvY3VtZW50Q2xpZW50LCBVcGRhdGVDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvbGliLWR5bmFtb2RiJztcbmltcG9ydCB0eXBlIHsgQVBJR2F0ZXdheVByb3h5RXZlbnQsIEFQSUdhdGV3YXlQcm94eVJlc3VsdCB9IGZyb20gJ2F3cy1sYW1iZGEnO1xuXG5jb25zdCBlYzIgPSBuZXcgRUMyQ2xpZW50KHt9KTtcbmNvbnN0IGRkYkNsaWVudCA9IG5ldyBEeW5hbW9EQkNsaWVudCh7fSk7XG5jb25zdCBkZGIgPSBEeW5hbW9EQkRvY3VtZW50Q2xpZW50LmZyb20oZGRiQ2xpZW50KTtcblxuY29uc3QgVEFCTEVfTkFNRSA9IHByb2Nlc3MuZW52LlRBQkxFX05BTUUhO1xuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jIChcbiAgZXZlbnQ6IEFQSUdhdGV3YXlQcm94eUV2ZW50LFxuKTogUHJvbWlzZTxBUElHYXRld2F5UHJveHlSZXN1bHQ+ID0+IHtcbiAgY29uc29sZS5sb2coJ1N0YXR1c0NoZWNrL1N0YXJ0IHRyaWdnZXJlZCcsIHsgZXZlbnQgfSk7XG5cbiAgY29uc3QgaW5zdGFuY2VJZCA9IGV2ZW50LnBhdGhQYXJhbWV0ZXJzPy5pbnN0YW5jZUlkO1xuICBjb25zdCBpc1N0YXJ0UmVxdWVzdCA9IGV2ZW50LnJlc291cmNlPy5pbmNsdWRlcygnL3N0YXJ0JykgJiYgZXZlbnQuaHR0cE1ldGhvZCA9PT0gJ1BPU1QnO1xuXG4gIGlmICghaW5zdGFuY2VJZCkge1xuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXNDb2RlOiA0MDAsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICdBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4nOiAnKicsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBlcnJvcjogJ01pc3NpbmcgaW5zdGFuY2VJZCcgfSksXG4gICAgfTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLy8gSGFuZGxlIFBPU1QgL3N0YXR1cy97aW5zdGFuY2VJZH0vc3RhcnQgLSBTdGFydCBpbnN0YW5jZVxuICAgIGlmIChpc1N0YXJ0UmVxdWVzdCkge1xuICAgICAgY29uc29sZS5sb2coJ1N0YXJ0aW5nIGluc3RhbmNlOicsIGluc3RhbmNlSWQpO1xuXG4gICAgICBjb25zdCBzdGFydENvbW1hbmQgPSBuZXcgU3RhcnRJbnN0YW5jZXNDb21tYW5kKHtcbiAgICAgICAgSW5zdGFuY2VJZHM6IFtpbnN0YW5jZUlkXSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBlYzIuc2VuZChzdGFydENvbW1hbmQpO1xuXG4gICAgICAvLyBVcGRhdGUgRHluYW1vREIgc3RhdGVcbiAgICAgIGF3YWl0IGRkYi5zZW5kKG5ldyBVcGRhdGVDb21tYW5kKHtcbiAgICAgICAgVGFibGVOYW1lOiBUQUJMRV9OQU1FLFxuICAgICAgICBLZXk6IHsgaW5zdGFuY2VJZCB9LFxuICAgICAgICBVcGRhdGVFeHByZXNzaW9uOiAnU0VUIGluc3RhbmNlU3RhdGUgPSA6c3RhdGUsIGxhc3RBY3Rpdml0eVRpbWUgPSA6dGltZScsXG4gICAgICAgIEV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAnOnN0YXRlJzogJ3N0YXJ0aW5nJyxcbiAgICAgICAgICAnOnRpbWUnOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIH0sXG4gICAgICB9KSk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXR1c0NvZGU6IDIwMCxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbic6ICcqJyxcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIG1lc3NhZ2U6ICdJbnN0YW5jZSBzdGFydCBpbml0aWF0ZWQnLFxuICAgICAgICAgIHN0YXRlOiAnc3RhcnRpbmcnLFxuICAgICAgICAgIGluc3RhbmNlSWQsXG4gICAgICAgIH0pLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgR0VUIC9zdGF0dXMve2luc3RhbmNlSWR9IC0gQ2hlY2sgc3RhdHVzXG4gICAgY29uc3Qgc3RhdHVzQ29tbWFuZCA9IG5ldyBEZXNjcmliZUluc3RhbmNlU3RhdHVzQ29tbWFuZCh7XG4gICAgICBJbnN0YW5jZUlkczogW2luc3RhbmNlSWRdLFxuICAgICAgSW5jbHVkZUFsbEluc3RhbmNlczogdHJ1ZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHN0YXR1c1Jlc3BvbnNlID0gYXdhaXQgZWMyLnNlbmQoc3RhdHVzQ29tbWFuZCk7XG4gICAgY29uc3QgaW5zdGFuY2VTdGF0dXMgPSBzdGF0dXNSZXNwb25zZS5JbnN0YW5jZVN0YXR1c2VzPy5bMF07XG4gICAgY29uc3Qgc3RhdGUgPSBpbnN0YW5jZVN0YXR1cz8uSW5zdGFuY2VTdGF0ZT8uTmFtZSB8fCAndW5rbm93bic7XG5cbiAgICBjb25zb2xlLmxvZygnSW5zdGFuY2Ugc3RhdGU6Jywgc3RhdGUpO1xuXG4gICAgLy8gSWYgcnVubmluZywgdXBkYXRlIER5bmFtb0RCXG4gICAgaWYgKHN0YXRlID09PSAncnVubmluZycpIHtcbiAgICAgIGF3YWl0IGRkYi5zZW5kKG5ldyBVcGRhdGVDb21tYW5kKHtcbiAgICAgICAgVGFibGVOYW1lOiBUQUJMRV9OQU1FLFxuICAgICAgICBLZXk6IHsgaW5zdGFuY2VJZCB9LFxuICAgICAgICBVcGRhdGVFeHByZXNzaW9uOiAnU0VUIGluc3RhbmNlU3RhdGUgPSA6c3RhdGUsIGxhc3RBY3Rpdml0eVRpbWUgPSA6dGltZScsXG4gICAgICAgIEV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAnOnN0YXRlJzogJ3J1bm5pbmcnLFxuICAgICAgICAgICc6dGltZSc6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzQ29kZTogMjAwLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJzogJyonLFxuICAgICAgICAnQ2FjaGUtQ29udHJvbCc6ICduby1jYWNoZSwgbm8tc3RvcmUsIG11c3QtcmV2YWxpZGF0ZScsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBzdGF0ZSxcbiAgICAgICAgcmVhZHk6IHN0YXRlID09PSAncnVubmluZycsXG4gICAgICAgIGluc3RhbmNlSWQsXG4gICAgICB9KSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGluIHN0YXR1cyBjaGVjay9zdGFydDonLCBlcnJvcik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzQ29kZTogNTAwLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJzogJyonLFxuICAgICAgfSxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgZXJyb3I6ICdJbnRlcm5hbCBzZXJ2ZXIgZXJyb3InIH0pLFxuICAgIH07XG4gIH1cbn07XG4iXX0=
@@ -1,6 +1,7 @@
1
1
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
2
  import * as iam from 'aws-cdk-lib/aws-iam';
3
3
  import { Construct } from 'constructs';
4
+ import { IdleMonitor } from './idle-monitor/idle-monitor';
4
5
  /**
5
6
  * Properties for the VSCodeServer construct
6
7
  */
@@ -118,6 +119,39 @@ export interface VSCodeServerProps {
118
119
  * @default false
119
120
  */
120
121
  readonly autoCreateCertificate?: boolean;
122
+ /**
123
+ * Enable automatic instance stop when idle
124
+ * Monitors CloudFront metrics and stops the EC2 instance after specified idle time
125
+ *
126
+ * @default false
127
+ */
128
+ readonly enableAutoStop?: boolean;
129
+ /**
130
+ * Minutes of inactivity before stopping the instance
131
+ * Only applies when enableAutoStop is true
132
+ *
133
+ * @default 30
134
+ */
135
+ readonly idleTimeoutMinutes?: number;
136
+ /**
137
+ * How often to check for idle activity (in minutes)
138
+ * Only applies when enableAutoStop is true
139
+ *
140
+ * @default 5 - Check every 5 minutes
141
+ */
142
+ readonly idleCheckIntervalMinutes?: number;
143
+ /**
144
+ * Skip instance status checks in IdleMonitor
145
+ * When true, IdleMonitor will stop idle instances even if status checks haven't passed
146
+ * This is useful for integration tests where status check initialization time
147
+ * exceeds the test timeout limits
148
+ *
149
+ * WARNING: For testing only - in production, you should wait for status checks
150
+ * to pass before stopping instances to avoid stopping unhealthy instances
151
+ *
152
+ * @default false
153
+ */
154
+ readonly skipStatusChecks?: boolean;
121
155
  }
122
156
  /**
123
157
  * The flavor of linux you want to run vscode server on
@@ -161,5 +195,13 @@ export declare class VSCodeServer extends Construct {
161
195
  * The password to login to the server
162
196
  */
163
197
  readonly password: string;
198
+ /**
199
+ * The EC2 instance running VS Code Server
200
+ */
201
+ readonly instance: ec2.IInstance;
202
+ /**
203
+ * The IdleMonitor construct (only present if enableAutoStop is true)
204
+ */
205
+ readonly idleMonitor?: IdleMonitor;
164
206
  constructor(scope: Construct, id: string, props?: VSCodeServerProps);
165
207
  }