aws-ec2-instance-running-scheduler 3.0.9 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jsii CHANGED
@@ -2,7 +2,6 @@
2
2
  "author": {
3
3
  "email": "yicr@users.noreply.github.com",
4
4
  "name": "yicr",
5
- "organization": true,
6
5
  "roles": [
7
6
  "author"
8
7
  ]
@@ -8441,7 +8440,7 @@
8441
8440
  "stability": "stable"
8442
8441
  },
8443
8442
  "homepage": "https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler.git",
8444
- "jsiiVersion": "5.9.35 (build 7156583)",
8443
+ "jsiiVersion": "5.9.36 (build 27873df)",
8445
8444
  "keywords": [
8446
8445
  "auto",
8447
8446
  "aws",
@@ -8463,7 +8462,7 @@
8463
8462
  },
8464
8463
  "name": "aws-ec2-instance-running-scheduler",
8465
8464
  "readme": {
8466
- "markdown": "# AWS EC2 Instance Running Scheduler\n\n[![GitHub](https://img.shields.io/github/license/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler?style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/blob/main/LICENSE)\n[![npm (scoped)](https://img.shields.io/npm/v/aws-ec2-instance-running-scheduler?style=flat-square)](https://www.npmjs.com/package/aws-ec2-instance-running-scheduler)\n[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/release.yml?branch=main&label=release&style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/actions/workflows/release.yml)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler?sort=semver&style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/releases)\n\n[![View on Construct Hub](https://constructs.dev/badge?package=aws-ec2-instance-running-scheduler)](https://constructs.dev/packages/aws-ec2-instance-running-scheduler)\n\nAWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**.\n\n## Features\n\n- **Tag-based targeting** – Select EC2 instances by tag key and values (e.g. `Schedule` / `YES`) via `tag:GetResources`.\n- **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).\n- **Durable Lambda** – One Lambda with AWS Lambda Durable Execution (`step`, `wait`, `map`, child contexts per instance) for long-running workflows without Step Functions.\n- **Stable-state polling** – After start/stop, the function waits and re-describes instances until `running` (start mode) or `stopped` (stop mode), or until a terminal error.\n- **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON).\n- **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).\n- **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.\n- **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, JSON logging, and a dedicated log group (construct defaults).\n\n## Installation\n\n**npm**\n\n```bash\nnpm install aws-ec2-instance-running-scheduler\n```\n\n**yarn**\n\n```bash\nyarn add aws-ec2-instance-running-scheduler\n```\n\n**pnpm**\n\n```bash\npnpm add aws-ec2-instance-running-scheduler\n```\n\n## Usage\n\nUse the **construct** `EC2InstanceRunningScheduler` when embedding the scheduler in an existing stack or other CDK scope.\n\n```typescript\nimport * as cdk from 'aws-cdk-lib';\nimport { TimeZone } from 'aws-cdk-lib';\nimport { EC2InstanceRunningScheduler } from 'aws-ec2-instance-running-scheduler';\n\nconst app = new cdk.App();\nconst stack = new cdk.Stack(app, 'MyStack');\n\nnew EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {\n targetResource: {\n tagKey: 'Schedule',\n tagValues: ['YES'],\n },\n secrets: {\n slackSecretName: 'my-slack-secret',\n },\n startSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '55',\n hour: '8',\n week: 'MON-FRI',\n },\n stopSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '5',\n hour: '19',\n week: 'MON-FRI',\n },\n enableScheduling: true,\n});\n```\n\nUse the **stack** `EC2InstanceRunningScheduleStack` when deploying the scheduler as its own stack. It accepts the **same scheduler options** as the construct (plus standard `StackProps` such as `env`).\n\n```typescript\nimport * as cdk from 'aws-cdk-lib';\nimport { TimeZone } from 'aws-cdk-lib';\nimport { EC2InstanceRunningScheduleStack } from 'aws-ec2-instance-running-scheduler';\n\nconst app = new cdk.App();\n\nnew EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {\n targetResource: {\n tagKey: 'Schedule',\n tagValues: ['YES'],\n },\n secrets: {\n slackSecretName: 'my-slack-secret',\n },\n startSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '55',\n hour: '8',\n week: 'MON-FRI',\n },\n stopSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '5',\n hour: '19',\n week: 'MON-FRI',\n },\n enableScheduling: true,\n});\n```\n\nEventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you.\n\n## Options\n\nThese options apply to **`EC2InstanceRunningScheduler`** and to **`EC2InstanceRunningScheduleStack`** (stack props include them alongside `StackProps`).\n\n| Option | Type | Required | Description |\n|--------|------|----------|-------------|\n| `targetResource` | `TargetResource` | Yes | Tag key and values used to select EC2 instances. |\n| `secrets` | `Secrets` | Yes | Identifies the Secrets Manager secret used for Slack (`slackSecretName`). |\n| `startSchedule` | `Schedule` | No | Cron for starting instances (default: `50 7 ? * MON-FRI *` in `Etc/UTC`). |\n| `stopSchedule` | `Schedule` | No | Cron for stopping instances (default: `5 19 ? * MON-FRI *` in `Etc/UTC`). |\n| `enableScheduling` | `boolean` | No | Whether both scheduler rules are enabled (default: `true`). |\n\n### TargetResource\n\n- `tagKey` – Tag key used to select instances (e.g. `Schedule`).\n- `tagValues` – Tag values that must match (e.g. `['YES']`).\n\n### Schedule\n\n- `timezone` – `TimeZone` from `aws-cdk-lib` (e.g. `TimeZone.ASIA_TOKYO`, `TimeZone.ETC_UTC`).\n- `minute` – Cron minute (`0`–`59`).\n- `hour` – Cron hour (`0`–`23`).\n- `week` – Cron day-of-week field (e.g. `MON-FRI`).\n\n### Secrets\n\n- `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`).\n\n## Requirements\n\n- **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).\n- **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).\n- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** and a **live alias**; EC2 (describe/start/stop); Resource Groups Tagging API; Secrets Manager. The deployed function uses the **latest Node.js runtime** available in the region (as configured by the construct’s Lambda class), **arm64**, and Durable Execution–compatible settings.\n\n## License\n\nThis project is licensed under the Apache-2.0 License.\n"
8465
+ "markdown": "# AWS EC2 Instance Running Scheduler\n\n[![GitHub](https://img.shields.io/github/license/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler?style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/blob/main/LICENSE)\n[![npm (scoped)](https://img.shields.io/npm/v/aws-ec2-instance-running-scheduler?style=flat-square)](https://www.npmjs.com/package/aws-ec2-instance-running-scheduler)\n[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/release.yml?branch=main&label=release&style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/actions/workflows/release.yml)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler?sort=semver&style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/releases)\n\n[![View on Construct Hub](https://constructs.dev/badge?package=aws-ec2-instance-running-scheduler)](https://constructs.dev/packages/aws-ec2-instance-running-scheduler)\n\nAWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**. The Lambda emits **structured application logs** (invocation, EC2 transitions, Slack steps, completion) alongside JSON platform logs.\n\n## Features\n\n- **Tag-based targeting** – Select EC2 instances by tag key and values (e.g. `Schedule` / `YES`) via `tag:GetResources`.\n- **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).\n- **Durable Lambda** – One Lambda with AWS Lambda Durable Execution (`step`, `wait`, `map`, child contexts per instance) for long-running workflows without Step Functions.\n- **Stable-state polling** – After start/stop, the function waits and re-describes instances until `running` (start mode) or `stopped` (stop mode), or until a terminal error.\n- **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON). The secret name is passed as **`SLACK_SECRET_NAME`** on the function (from `secrets.slackSecretName`) and validated at runtime via **safe-env-getter**.\n- **Structured logging** – The handler uses the durable execution **`ctx.logger`** for traceable JSON application logs (e.g. invocation, describe/start/stop/wait loops, target count, Slack posts, errors before instance state failures).\n- **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).\n- **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.\n- **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, **Parameters and Secrets Lambda Extension** (configured on the function for secret access patterns), JSON logging with configurable system/application levels, and a dedicated log group (construct defaults).\n\n## Installation\n\n**npm**\n\n```bash\nnpm install aws-ec2-instance-running-scheduler\n```\n\n**yarn**\n\n```bash\nyarn add aws-ec2-instance-running-scheduler\n```\n\n**pnpm**\n\n```bash\npnpm add aws-ec2-instance-running-scheduler\n```\n\n## Usage\n\nUse the **construct** `EC2InstanceRunningScheduler` when embedding the scheduler in an existing stack or other CDK scope.\n\n```typescript\nimport * as cdk from 'aws-cdk-lib';\nimport { TimeZone } from 'aws-cdk-lib';\nimport { EC2InstanceRunningScheduler } from 'aws-ec2-instance-running-scheduler';\n\nconst app = new cdk.App();\nconst stack = new cdk.Stack(app, 'MyStack');\n\nnew EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {\n targetResource: {\n tagKey: 'Schedule',\n tagValues: ['YES'],\n },\n secrets: {\n slackSecretName: 'my-slack-secret',\n },\n startSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '55',\n hour: '8',\n week: 'MON-FRI',\n },\n stopSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '5',\n hour: '19',\n week: 'MON-FRI',\n },\n enableScheduling: true,\n});\n```\n\nUse the **stack** `EC2InstanceRunningScheduleStack` when deploying the scheduler as its own stack. It accepts the **same scheduler options** as the construct (plus standard `StackProps` such as `env`).\n\n```typescript\nimport * as cdk from 'aws-cdk-lib';\nimport { TimeZone } from 'aws-cdk-lib';\nimport { EC2InstanceRunningScheduleStack } from 'aws-ec2-instance-running-scheduler';\n\nconst app = new cdk.App();\n\nnew EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {\n targetResource: {\n tagKey: 'Schedule',\n tagValues: ['YES'],\n },\n secrets: {\n slackSecretName: 'my-slack-secret',\n },\n startSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '55',\n hour: '8',\n week: 'MON-FRI',\n },\n stopSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '5',\n hour: '19',\n week: 'MON-FRI',\n },\n enableScheduling: true,\n});\n```\n\nEventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you. The function environment includes **`SLACK_SECRET_NAME`** set to `secrets.slackSecretName`.\n\n## Options\n\nThese options apply to **`EC2InstanceRunningScheduler`** and to **`EC2InstanceRunningScheduleStack`** (stack props include them alongside `StackProps`).\n\n| Option | Type | Required | Description |\n|--------|------|----------|-------------|\n| `targetResource` | `TargetResource` | Yes | Tag key and values used to select EC2 instances. |\n| `secrets` | `Secrets` | Yes | Identifies the Secrets Manager secret used for Slack (`slackSecretName`). |\n| `startSchedule` | `Schedule` | No | Cron for starting instances (default: `50 7 ? * MON-FRI *` in `Etc/UTC`). |\n| `stopSchedule` | `Schedule` | No | Cron for stopping instances (default: `5 19 ? * MON-FRI *` in `Etc/UTC`). |\n| `enableScheduling` | `boolean` | No | Whether both scheduler rules are enabled (default: `true`). |\n\n### TargetResource\n\n- `tagKey` – Tag key used to select instances (e.g. `Schedule`).\n- `tagValues` – Tag values that must match (e.g. `['YES']`).\n\n### Schedule\n\n- `timezone` – `TimeZone` from `aws-cdk-lib` (e.g. `TimeZone.ASIA_TOKYO`, `TimeZone.ETC_UTC`).\n- `minute` – Cron minute (`0`–`59`).\n- `hour` – Cron hour (`0`–`23`).\n- `week` – Cron day-of-week field (e.g. `MON-FRI`).\n\n### Secrets\n\n- `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`). The construct sets **`SLACK_SECRET_NAME`** on the function to this value; the handler reads and validates it at runtime (via **safe-env-getter**).\n\n## Requirements\n\n- **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).\n- **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).\n- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** (requires **Node.js 22+** in the deployment region—runtime is the latest Node.js available in the region per the construct), a **live alias**, **Parameters and Secrets Lambda Extension**; EC2 (describe/start/stop); Resource Groups Tagging API; Secrets Manager. The deployed function uses **arm64**, Durable Execution–compatible IAM and settings, and a bundled handler that loads secrets via **aws-lambda-secret-fetcher**.\n\n## License\n\nThis project is licensed under the Apache-2.0 License.\n"
8467
8466
  },
8468
8467
  "repository": {
8469
8468
  "type": "git",
@@ -8969,6 +8968,6 @@
8969
8968
  "symbolId": "src/constructs/ec2-instance-running-scheduler:TargetResource"
8970
8969
  }
8971
8970
  },
8972
- "version": "3.0.9",
8973
- "fingerprint": "i3ipjzKdxhYZn6S5yjAHIsy6ewDTCqt+nE2ro9c/Xys="
8971
+ "version": "3.1.0",
8972
+ "fingerprint": "d3YHyiyERSOnDctHGkrNVgZh16Hoxj/djXjCfTeXMyc="
8974
8973
  }
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  [![View on Construct Hub](https://constructs.dev/badge?package=aws-ec2-instance-running-scheduler)](https://constructs.dev/packages/aws-ec2-instance-running-scheduler)
9
9
 
10
- AWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**.
10
+ AWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**. The Lambda emits **structured application logs** (invocation, EC2 transitions, Slack steps, completion) alongside JSON platform logs.
11
11
 
12
12
  ## Features
13
13
 
@@ -15,10 +15,11 @@ AWS CDK construct that starts and stops EC2 instances on a cron schedule using *
15
15
  - **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).
16
16
  - **Durable Lambda** – One Lambda with AWS Lambda Durable Execution (`step`, `wait`, `map`, child contexts per instance) for long-running workflows without Step Functions.
17
17
  - **Stable-state polling** – After start/stop, the function waits and re-describes instances until `running` (start mode) or `stopped` (stop mode), or until a terminal error.
18
- - **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON).
18
+ - **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON). The secret name is passed as **`SLACK_SECRET_NAME`** on the function (from `secrets.slackSecretName`) and validated at runtime via **safe-env-getter**.
19
+ - **Structured logging** – The handler uses the durable execution **`ctx.logger`** for traceable JSON application logs (e.g. invocation, describe/start/stop/wait loops, target count, Slack posts, errors before instance state failures).
19
20
  - **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).
20
21
  - **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.
21
- - **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, JSON logging, and a dedicated log group (construct defaults).
22
+ - **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, **Parameters and Secrets Lambda Extension** (configured on the function for secret access patterns), JSON logging with configurable system/application levels, and a dedicated log group (construct defaults).
22
23
 
23
24
  ## Installation
24
25
 
@@ -109,7 +110,7 @@ new EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {
109
110
  });
110
111
  ```
111
112
 
112
- EventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you.
113
+ EventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you. The function environment includes **`SLACK_SECRET_NAME`** set to `secrets.slackSecretName`.
113
114
 
114
115
  ## Options
115
116
 
@@ -137,13 +138,13 @@ These options apply to **`EC2InstanceRunningScheduler`** and to **`EC2InstanceRu
137
138
 
138
139
  ### Secrets
139
140
 
140
- - `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`).
141
+ - `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`). The construct sets **`SLACK_SECRET_NAME`** on the function to this value; the handler reads and validates it at runtime (via **safe-env-getter**).
141
142
 
142
143
  ## Requirements
143
144
 
144
145
  - **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).
145
146
  - **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).
146
- - **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** and a **live alias**; EC2 (describe/start/stop); Resource Groups Tagging API; Secrets Manager. The deployed function uses the **latest Node.js runtime** available in the region (as configured by the construct’s Lambda class), **arm64**, and Durable Execution–compatible settings.
147
+ - **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** (requires **Node.js 22+** in the deployment region—runtime is the latest Node.js available in the region per the construct), a **live alias**, **Parameters and Secrets Lambda Extension**; EC2 (describe/start/stop); Resource Groups Tagging API; Secrets Manager. The deployed function uses **arm64**, Durable Execution–compatible IAM and settings, and a bundled handler that loads secrets via **aws-lambda-secret-fetcher**.
147
148
 
148
149
  ## License
149
150
 
@@ -18968,6 +18968,146 @@ var require_lib2 = __commonJS({
18968
18968
  }
18969
18969
  });
18970
18970
 
18971
+ // node_modules/safe-env-getter/lib/index.js
18972
+ var require_lib3 = __commonJS({
18973
+ "node_modules/safe-env-getter/lib/index.js"(exports2) {
18974
+ "use strict";
18975
+ Object.defineProperty(exports2, "__esModule", { value: true });
18976
+ exports2.SafeEnvGetter = exports2.SafeEnvType = exports2.SafeEnvGetterValidationError = exports2.SafeEnvGetterError = void 0;
18977
+ var SafeEnvGetterError = class extends Error {
18978
+ constructor(message) {
18979
+ super(message);
18980
+ this.name = "SafeEnvGetterError";
18981
+ }
18982
+ };
18983
+ exports2.SafeEnvGetterError = SafeEnvGetterError;
18984
+ var SafeEnvGetterValidationError = class _SafeEnvGetterValidationError extends SafeEnvGetterError {
18985
+ /**
18986
+ * Formats validation errors into a human-readable error message.
18987
+ */
18988
+ static format(errors) {
18989
+ const lines = errors.map((e) => `- ${e.key}: ${e.message}${e.raw == null ? "" : ` (raw="${e.raw}")`}`);
18990
+ return `Invalid environment variables (${errors.length}):
18991
+ ${lines.join("\n")}`;
18992
+ }
18993
+ /**
18994
+ * Creates a new validation error from one or more `SafeEnvError` entries.
18995
+ */
18996
+ constructor(errors) {
18997
+ const msg = _SafeEnvGetterValidationError.format(errors);
18998
+ super(msg);
18999
+ this.name = "SafeEnvGetterValidationError";
19000
+ this.errors = errors;
19001
+ this.keys = errors.map((e) => e.key);
19002
+ }
19003
+ };
19004
+ exports2.SafeEnvGetterValidationError = SafeEnvGetterValidationError;
19005
+ exports2.SafeEnvType = {
19006
+ /** Spec for a string value. */
19007
+ String: { type: "string" },
19008
+ /** Spec for a numeric value. */
19009
+ Number: { type: "number" },
19010
+ /** Spec for a boolean value (1/true/yes/on → true). */
19011
+ Boolean: { type: "boolean" },
19012
+ /**
19013
+ * Returns a spec that restricts the value to one of the given choices.
19014
+ * @param choices - Allowed string literals.
19015
+ * @returns Enum spec for use with `getEnv`.
19016
+ */
19017
+ Enum: (choices) => ({ type: "enum", choices })
19018
+ };
19019
+ function getEnv(key, spec = exports2.SafeEnvType.String, options) {
19020
+ const raw = process.env[key];
19021
+ const defaultValue = options?.default;
19022
+ const hasDefault = defaultValue !== void 0;
19023
+ if (raw == null || raw === "") {
19024
+ if (!hasDefault) {
19025
+ throw new SafeEnvGetterValidationError([
19026
+ { key, message: `Missing required environment variable: ${key}`, raw, kind: "missing" }
19027
+ ]);
19028
+ }
19029
+ return defaultValue;
19030
+ }
19031
+ switch (spec.type) {
19032
+ case "number": {
19033
+ const n = Number(raw);
19034
+ if (Number.isNaN(n)) {
19035
+ throw new SafeEnvGetterValidationError([
19036
+ { key, message: `Env ${key}: expected number, got "${raw}"`, raw, kind: "invalid_number" }
19037
+ ]);
19038
+ }
19039
+ return n;
19040
+ }
19041
+ case "boolean":
19042
+ return /^(1|true|yes|on)$/i.test(raw) ? true : false;
19043
+ case "enum":
19044
+ if (!spec.choices.includes(raw)) {
19045
+ throw new SafeEnvGetterValidationError([
19046
+ { key, message: `Env ${key}: must be one of [${spec.choices.join(", ")}]`, raw, kind: "invalid_enum" }
19047
+ ]);
19048
+ }
19049
+ return raw;
19050
+ default:
19051
+ return raw;
19052
+ }
19053
+ }
19054
+ var getEnvs = (schema) => {
19055
+ const envs = {};
19056
+ const errors = [];
19057
+ for (const key of Object.keys(schema)) {
19058
+ const entry = schema[key];
19059
+ const spec = Array.isArray(entry) ? entry[0] : entry;
19060
+ const options = Array.isArray(entry) ? entry[1] : void 0;
19061
+ const raw = process.env[key];
19062
+ const defaultValue = options?.default;
19063
+ const hasDefault = defaultValue !== void 0;
19064
+ if (raw == null || raw === "") {
19065
+ if (!hasDefault) {
19066
+ errors.push({ key, message: `Missing required environment variable: ${key}`, raw, kind: "missing" });
19067
+ continue;
19068
+ }
19069
+ envs[key] = defaultValue;
19070
+ continue;
19071
+ }
19072
+ if (spec.type === "number") {
19073
+ const n = Number(raw);
19074
+ if (Number.isNaN(n)) {
19075
+ errors.push({ key, message: `Env ${key}: expected number, got "${raw}"`, raw, kind: "invalid_number" });
19076
+ continue;
19077
+ }
19078
+ envs[key] = n;
19079
+ continue;
19080
+ }
19081
+ if (spec.type === "boolean") {
19082
+ envs[key] = /^(1|true|yes|on)$/i.test(raw) ? true : false;
19083
+ continue;
19084
+ }
19085
+ if (spec.type === "enum") {
19086
+ if (!spec.choices.includes(raw)) {
19087
+ errors.push({
19088
+ key,
19089
+ message: `Env ${key}: must be one of [${spec.choices.join(", ")}]`,
19090
+ raw,
19091
+ kind: "invalid_enum"
19092
+ });
19093
+ continue;
19094
+ }
19095
+ envs[key] = raw;
19096
+ continue;
19097
+ }
19098
+ envs[key] = raw;
19099
+ }
19100
+ if (errors.length > 0)
19101
+ throw new SafeEnvGetterValidationError(errors);
19102
+ return envs;
19103
+ };
19104
+ exports2.SafeEnvGetter = {
19105
+ getEnv,
19106
+ getEnvs
19107
+ };
19108
+ }
19109
+ });
19110
+
18971
19111
  // src/funcs/running-scheduler.lambda.ts
18972
19112
  var running_scheduler_lambda_exports = {};
18973
19113
  __export(running_scheduler_lambda_exports, {
@@ -22469,6 +22609,7 @@ var import_client_ec2 = require("@aws-sdk/client-ec2");
22469
22609
  var import_client_resource_groups_tagging_api = require("@aws-sdk/client-resource-groups-tagging-api");
22470
22610
  var import_web_api = __toESM(require_dist4());
22471
22611
  var import_aws_lambda_secret_fetcher = __toESM(require_lib2());
22612
+ var import_safe_env_getter = __toESM(require_lib3());
22472
22613
 
22473
22614
  // src/funcs/running-scheduler-predicates.ts
22474
22615
  var isDesiredStableState = (mode, currentState) => mode === "Start" && currentState === "running" || mode === "Stop" && currentState === "stopped";
@@ -22490,6 +22631,13 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
22490
22631
  const account = arnParts[4] ?? "";
22491
22632
  const region = arnParts[3] ?? "";
22492
22633
  const stepPrefix = `resource-${resourceIndex}-${identifier}`;
22634
+ ctx.logger.info("processOneResource: start", {
22635
+ resourceIndex,
22636
+ identifier,
22637
+ region,
22638
+ account,
22639
+ mode: params.Mode
22640
+ });
22493
22641
  let loopCount = 0;
22494
22642
  let currentState = "";
22495
22643
  do {
@@ -22498,21 +22646,37 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
22498
22646
  const out = await ec2.send(new import_client_ec2.DescribeInstancesCommand({ InstanceIds: [identifier] }));
22499
22647
  return out.Reservations?.[0]?.Instances?.[0]?.State?.Name ?? "unknown";
22500
22648
  });
22649
+ ctx.logger.info("processOneResource: described", {
22650
+ identifier,
22651
+ loopCount,
22652
+ currentState,
22653
+ mode: params.Mode
22654
+ });
22501
22655
  const mode = params.Mode;
22502
22656
  if (mode === "Start" && currentState === "stopped") {
22657
+ ctx.logger.info("processOneResource: starting instance", { identifier, loopCount });
22503
22658
  await ctx.step(`${stepPrefix}-start-${loopCount}`, async () => {
22504
22659
  const ec2 = new import_client_ec2.EC2Client({});
22505
22660
  await ec2.send(new import_client_ec2.StartInstancesCommand({ InstanceIds: [identifier] }));
22506
22661
  });
22662
+ ctx.logger.info("processOneResource: wait after start", {
22663
+ identifier,
22664
+ seconds: STATUS_CHANGE_WAIT_SECONDS
22665
+ });
22507
22666
  await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
22508
22667
  loopCount += 1;
22509
22668
  continue;
22510
22669
  }
22511
22670
  if (mode === "Stop" && currentState === "running") {
22671
+ ctx.logger.info("processOneResource: stopping instance", { identifier, loopCount });
22512
22672
  await ctx.step(`${stepPrefix}-stop-${loopCount}`, async () => {
22513
22673
  const ec2 = new import_client_ec2.EC2Client({});
22514
22674
  await ec2.send(new import_client_ec2.StopInstancesCommand({ InstanceIds: [identifier] }));
22515
22675
  });
22676
+ ctx.logger.info("processOneResource: wait after stop", {
22677
+ identifier,
22678
+ seconds: STATUS_CHANGE_WAIT_SECONDS
22679
+ });
22516
22680
  await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
22517
22681
  loopCount += 1;
22518
22682
  continue;
@@ -22520,13 +22684,32 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
22520
22684
  if (!isDesiredStableState(mode, currentState)) {
22521
22685
  const transitioning = mode === "Start" && currentState === "pending" || mode === "Stop" && (currentState === "stopping" || currentState === "shutting-down");
22522
22686
  if (transitioning) {
22687
+ ctx.logger.info("processOneResource: wait while transitioning", {
22688
+ identifier,
22689
+ loopCount,
22690
+ currentState,
22691
+ mode,
22692
+ seconds: STATUS_CHANGE_WAIT_SECONDS
22693
+ });
22523
22694
  await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
22524
22695
  loopCount += 1;
22525
22696
  continue;
22526
22697
  }
22698
+ ctx.logger.error("processOneResource: unexpected state", {
22699
+ identifier,
22700
+ mode,
22701
+ currentState,
22702
+ loopCount
22703
+ });
22527
22704
  throw new Error(`instance status fail: mode=${mode} currentState=${currentState}`);
22528
22705
  }
22529
22706
  } while (!isDesiredStableState(params.Mode, currentState));
22707
+ ctx.logger.info("processOneResource: reached desired stable state", {
22708
+ identifier,
22709
+ finalState: currentState,
22710
+ mode: params.Mode,
22711
+ loopCount
22712
+ });
22530
22713
  return {
22531
22714
  identifier,
22532
22715
  account,
@@ -22535,22 +22718,26 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
22535
22718
  status: currentState
22536
22719
  };
22537
22720
  };
22538
- var handler = withDurableExecution(async (event, context) => {
22721
+ var handler = withDurableExecution(async (event, ctx) => {
22539
22722
  const params = event.Params;
22723
+ ctx.logger.info("running-scheduler: invocation", {
22724
+ mode: params?.Mode,
22725
+ tagKey: params?.TagKey,
22726
+ tagValueCount: params?.TagValues?.length ?? 0
22727
+ });
22540
22728
  if (!params?.TagKey || !params?.TagValues || !params?.Mode) {
22541
22729
  throw new Error("Invalid event: Params.TagKey, Params.TagValues, Params.Mode are required.");
22542
22730
  }
22543
- const slackSecretName = process.env.SLACK_SECRET_NAME;
22544
- if (!slackSecretName) {
22545
- throw new Error("missing environment variable SLACK_SECRET_NAME.");
22546
- }
22547
- const slackSecretValue = await context.step("fetch-slack-secret", async () => {
22731
+ const slackSecretName = import_safe_env_getter.SafeEnvGetter.getEnv("SLACK_SECRET_NAME");
22732
+ const slackSecretValue = await ctx.step("fetch-slack-secret", async () => {
22733
+ ctx.logger.info("running-scheduler: fetching Slack secret", { secretName: slackSecretName });
22548
22734
  return import_aws_lambda_secret_fetcher.secretFetcher.getSecretValue(slackSecretName);
22549
22735
  });
22736
+ ctx.logger.info("running-scheduler: Slack secret loaded");
22550
22737
  if (!slackSecretValue?.token || !slackSecretValue?.channel) {
22551
22738
  throw new Error("Slack secret must contain token and channel.");
22552
22739
  }
22553
- const targetResources = await context.step("get-target-resources", async () => {
22740
+ const targetResources = await ctx.step("get-target-resources", async () => {
22554
22741
  const client2 = new import_client_resource_groups_tagging_api.ResourceGroupsTaggingAPIClient({});
22555
22742
  const result = await client2.send(
22556
22743
  new import_client_resource_groups_tagging_api.GetResourcesCommand({
@@ -22558,28 +22745,46 @@ var handler = withDurableExecution(async (event, context) => {
22558
22745
  TagFilters: [{ Key: params.TagKey, Values: params.TagValues }]
22559
22746
  })
22560
22747
  );
22561
- return (result.ResourceTagMappingList ?? []).map((m) => m.ResourceARN).filter((arn) => arn != null);
22748
+ const arns = (result.ResourceTagMappingList ?? []).map((m) => m.ResourceARN).filter((arn) => arn != null);
22749
+ ctx.logger.info("running-scheduler: get-target-resources done", { count: arns.length });
22750
+ return arns;
22562
22751
  });
22563
22752
  if (targetResources.length === 0) {
22753
+ ctx.logger.info("running-scheduler: no matching instances", { tagKey: params.TagKey });
22564
22754
  return { status: "TargetResourcesNotFound" };
22565
22755
  }
22566
22756
  const client = new import_web_api.WebClient(slackSecretValue.token);
22567
22757
  const channel = slackSecretValue.channel;
22568
- const slackParentMessageResult = await context.step("post-slack-messages", async () => {
22758
+ ctx.logger.info("running-scheduler: posting parent Slack message", {
22759
+ instanceCount: targetResources.length
22760
+ });
22761
+ const slackParentMessageResult = await ctx.step("post-slack-messages", async () => {
22569
22762
  return client.chat.postMessage({
22570
22763
  channel,
22571
22764
  text: `${params.Mode === "Start" ? "\u{1F606} Starts" : "\u{1F971} Stops"} the scheduled EC2 Instance.`
22572
22765
  });
22573
22766
  });
22574
- const results = await context.map(
22767
+ ctx.logger.info("running-scheduler: parent Slack message posted", {
22768
+ threadTs: slackParentMessageResult?.ts ?? null
22769
+ });
22770
+ ctx.logger.info("running-scheduler: starting parallel instance processing", {
22771
+ count: targetResources.length,
22772
+ maxConcurrency: 10
22773
+ });
22774
+ const results = await ctx.map(
22575
22775
  targetResources,
22576
22776
  // async (ctx: DurableContext, targetResource: string, index: number) =>
22577
22777
  // ctx.step(`process-resource-${index}`, async () =>
22578
22778
  // processOneResource(ctx, targetResource, params, index),
22579
22779
  // ),
22580
- async (ctx, targetResource, index) => {
22581
- return ctx.runInChildContext(`resource-${index}`, async (childCtx) => {
22780
+ async (mapCtx, targetResource, index) => {
22781
+ return mapCtx.runInChildContext(`resource-${index}`, async (childCtx) => {
22582
22782
  const result = await processOneResource(childCtx, targetResource, params, index);
22783
+ childCtx.logger.info("running-scheduler: posting thread Slack message", {
22784
+ index,
22785
+ identifier: result.identifier,
22786
+ status: result.status
22787
+ });
22583
22788
  await childCtx.step("post-slack-child-messages", async () => {
22584
22789
  const display = getStateDisplay(result.status);
22585
22790
  return client.chat.postMessage({
@@ -22605,6 +22810,10 @@ var handler = withDurableExecution(async (event, context) => {
22605
22810
  { maxConcurrency: 10 }
22606
22811
  );
22607
22812
  const resultList = Array.isArray(results) ? results : [];
22813
+ ctx.logger.info("running-scheduler: completed", {
22814
+ processed: targetResources.length,
22815
+ resultCount: resultList.length
22816
+ });
22608
22817
  return {
22609
22818
  status: "Completed",
22610
22819
  processed: targetResources.length,
@@ -139,5 +139,5 @@ class EC2InstanceRunningScheduler extends constructs_1.Construct {
139
139
  }
140
140
  exports.EC2InstanceRunningScheduler = EC2InstanceRunningScheduler;
141
141
  _a = JSII_RTTI_SYMBOL_1;
142
- EC2InstanceRunningScheduler[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduler", version: "3.0.9" };
142
+ EC2InstanceRunningScheduler[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduler", version: "3.1.0" };
143
143
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWMyLWluc3RhbmNlLXJ1bm5pbmctc2NoZWR1bGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnN0cnVjdHMvZWMyLWluc3RhbmNlLXJ1bm5pbmctc2NoZWR1bGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQWdFO0FBQ2hFLDJDQUEyQztBQUMzQyxpREFBaUQ7QUFDakQsNkNBQTZDO0FBQzdDLHVEQUF1RDtBQUN2RCw2REFBNkQ7QUFDN0QsdUVBQXdEO0FBQ3hELDJDQUF1QztBQUN2QyxvRkFBK0U7QUFrRC9FOzs7OztHQUtHO0FBQ0gsTUFBYSwyQkFBNEIsU0FBUSxzQkFBUztJQUN4RDs7Ozs7O09BTUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXVDO1FBQy9FLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxXQUFXLEdBQUcsMkJBQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFaEcsbUdBQW1HO1FBQ25HLDBDQUEwQztRQUMxQyxNQUFNLHVCQUF1QixHQUFHLElBQUkscURBQXdCLENBQUMsSUFBSSxFQUFFLDBCQUEwQixFQUFFO1lBQzdGLFdBQVcsRUFBRSwyRUFBMkU7WUFDeEYsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTTtZQUN4QyxPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzdCLFVBQVUsRUFBRSxHQUFHO1lBQ2YsYUFBYSxFQUFFLENBQUM7WUFDaEIsYUFBYSxFQUFFO2dCQUNiLGdCQUFnQixFQUFFLHNCQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDbkMsZUFBZSxFQUFFLHNCQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzthQUNsQztZQUNELFdBQVcsRUFBRTtnQkFD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QUFFO3dCQUNOLE1BQU0sRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQU07d0JBQ25DLFNBQVMsRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVM7d0JBQ3pDLElBQUksRUFBRSxNQUFNO3FCQUNiO2lCQUNGLENBQUM7YUFDSCxDQUFDO1NBQ0gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUExSEgsa0VBMkhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHVyYXRpb24sIFJlbW92YWxQb2xpY3ksIFRpbWVab25lIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgbG9ncyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgKiBhcyBzY2hlZHVsZXIgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNjaGVkdWxlcic7XG5pbXBvcnQgKiBhcyB0YXJnZXRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zY2hlZHVsZXItdGFyZ2V0cyc7XG5pbXBvcnQgeyBTZWNyZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc2VjcmV0c21hbmFnZXInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBSdW5uaW5nU2NoZWR1bGVyRnVuY3Rpb24gfSBmcm9tICcuLi9mdW5jcy9ydW5uaW5nLXNjaGVkdWxlci1mdW5jdGlvbic7XG5cbi8qKlxuICogQ3Jvbi1zdHlsZSBzY2hlZHVsZSBjb25maWd1cmF0aW9uIGZvciBzdGFydC9zdG9wIGFjdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZWR1bGUge1xuICAvKiogVGltZSB6b25lIGZvciB0aGUgc2NoZWR1bGUgKGUuZy4gRVRDX1VUQykuICovXG4gIHJlYWRvbmx5IHRpbWV6b25lOiBUaW1lWm9uZTtcbiAgLyoqIENyb24gbWludXRlICgw4oCTNTkpLiAqL1xuICByZWFkb25seSBtaW51dGU/OiBzdHJpbmc7XG4gIC8qKiBDcm9uIGhvdXIgKDDigJMyMykuICovXG4gIHJlYWRvbmx5IGhvdXI/OiBzdHJpbmc7XG4gIC8qKiBDcm9uIGRheSBvZiB3ZWVrIChlLmcuIE1PTi1GUkkpLiAqL1xuICByZWFkb25seSB3ZWVrPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIERlZmluZXMgd2hpY2ggRUMyIGluc3RhbmNlcyBhcmUgdGFyZ2V0ZWQgYnkgdGFnIGtleSBhbmQgdmFsdWVzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhcmdldFJlc291cmNlIHtcbiAgLyoqIFRhZyBrZXkgdXNlZCB0byBzZWxlY3QgaW5zdGFuY2VzIChlLmcuIFNjaGVkdWxlKS4gKi9cbiAgcmVhZG9ubHkgdGFnS2V5OiBzdHJpbmc7XG4gIC8qKiBUYWcgdmFsdWVzIHRoYXQgbWF0Y2ggaW5zdGFuY2VzIHRvIGluY2x1ZGUuICovXG4gIHJlYWRvbmx5IHRhZ1ZhbHVlczogc3RyaW5nW107XG59XG5cbi8qKlxuICogU2VjcmV0IGlkZW50aWZpZXJzIHJlcXVpcmVkIGJ5IHRoZSBzY2hlZHVsZXIgKGUuZy4gU2xhY2spLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlY3JldHMge1xuICAvKiogTmFtZSBvZiB0aGUgU2VjcmV0cyBNYW5hZ2VyIHNlY3JldCBjb250YWluaW5nIFNsYWNrIHRva2VuIGFuZCBjaGFubmVsLiAqL1xuICByZWFkb25seSBzbGFja1NlY3JldE5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBjcmVhdGluZyBhbiBFQzIgaW5zdGFuY2UgcnVubmluZyBzY2hlZHVsZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyUHJvcHMge1xuICAvKiogVGFnLWJhc2VkIHRhcmdldGluZyBmb3IgRUMyIGluc3RhbmNlcyB0byBzdGFydC9zdG9wLiAqL1xuICByZWFkb25seSB0YXJnZXRSZXNvdXJjZTogVGFyZ2V0UmVzb3VyY2U7XG4gIC8qKiBXaGV0aGVyIEV2ZW50QnJpZGdlIFNjaGVkdWxlciBydWxlcyBhcmUgZW5hYmxlZC4gRGVmYXVsdHMgdG8gdHJ1ZSBpZiBvbWl0dGVkLiAqL1xuICByZWFkb25seSBlbmFibGVTY2hlZHVsaW5nPzogYm9vbGVhbjtcbiAgLyoqIFNlY3JldHMgKGUuZy4gU2xhY2spIHVzZWQgZm9yIG5vdGlmaWNhdGlvbnMuICovXG4gIHJlYWRvbmx5IHNlY3JldHM6IFNlY3JldHM7XG4gIC8qKiBDcm9uIHNjaGVkdWxlIGZvciBzdG9wcGluZyBpbnN0YW5jZXMuICovXG4gIHJlYWRvbmx5IHN0b3BTY2hlZHVsZT86IFNjaGVkdWxlO1xuICAvKiogQ3JvbiBzY2hlZHVsZSBmb3Igc3RhcnRpbmcgaW5zdGFuY2VzLiAqL1xuICByZWFkb25seSBzdGFydFNjaGVkdWxlPzogU2NoZWR1bGU7XG59XG5cbi8qKlxuICogUHJvdmlzaW9ucyBFdmVudEJyaWRnZSBTY2hlZHVsZXIgcnVsZXMgYW5kIGEgRHVyYWJsZSBFeGVjdXRpb24gTGFtYmRhIHRoYXQgc3RhcnQvc3RvcCB0YWdnZWQgRUMyIGluc3RhbmNlcy5cbiAqXG4gKiBFYWNoIHNjaGVkdWxlIGludm9rZXMgdGhlIGZ1bmN0aW9uIHdpdGggYFBhcmFtc2AgKGBUYWdLZXlgLCBgVGFnVmFsdWVzYCwgYE1vZGVgKS4gVGhlIGZ1bmN0aW9uIHVzZXNcbiAqIHRoZSBSZXNvdXJjZSBHcm91cHMgVGFnZ2luZyBBUEkgYW5kIEVDMiBBUElzOyBTbGFjayBub3RpZmljYXRpb25zIHVzZSB0aGUgc2VjcmV0IG5hbWVkIGluIHtAbGluayBTZWNyZXRzLnNsYWNrU2VjcmV0TmFtZX0uXG4gKi9cbmV4cG9ydCBjbGFzcyBFQzJJbnN0YW5jZVJ1bm5pbmdTY2hlZHVsZXIgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogRGVmaW5lcyBJQU0sIGxvZ2dpbmcsIHR3byBjcm9uIHNjaGVkdWxlcyAoc3RhcnQvc3RvcCksIGFuZCB0aGUgYnVuZGxlZCBydW5uaW5nLXNjaGVkdWxlciBMYW1iZGEgKE5vZGUuanMsIER1cmFibGUgRXhlY3V0aW9uKS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gUGFyZW50IGNvbnN0cnVjdC5cbiAgICogQHBhcmFtIGlkIC0gQ29uc3RydWN0IGlkLlxuICAgKiBAcGFyYW0gcHJvcHMgLSBUYXJnZXQgdGFncywgb3B0aW9uYWwgY3JvbiBvdmVycmlkZXMsIFNsYWNrIHNlY3JldCBuYW1lLCBhbmQgc2NoZWR1bGUgZW5hYmxlIGZsYWcuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qgc2xhY2tTZWNyZXQgPSBTZWNyZXQuZnJvbVNlY3JldE5hbWVWMih0aGlzLCAnU2xhY2tTZWNyZXQnLCBwcm9wcy5zZWNyZXRzLnNsYWNrU2VjcmV0TmFtZSk7XG5cbiAgICAvLyBEdXJhYmxlIEZ1bmN0aW9ucy1iYXNlZCBSdW5uaW5nIFNjaGVkdWxlciAocHJldmlvdXMgU3RlcCBGdW5jdGlvbnMgbG9naWMgaW1wbGVtZW50ZWQgaW4gTGFtYmRhKS5cbiAgICAvLyBEdXJhYmxlIEV4ZWN1dGlvbiByZXF1aXJlcyBOb2RlLmpzIDIyKy5cbiAgICBjb25zdCBydW5uaW5nU2NoZWR1bGVGdW5jdGlvbiA9IG5ldyBSdW5uaW5nU2NoZWR1bGVyRnVuY3Rpb24odGhpcywgJ1J1bm5pbmdTY2hlZHVsZXJGdW5jdGlvbicsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnU3RhcnRzIGFuZCBzdG9wcyB0YWdnZWQgRUMyIGluc3RhbmNlcyBvbiBFdmVudEJyaWRnZSBTY2hlZHVsZXIgc2NoZWR1bGVzLicsXG4gICAgICBhcmNoaXRlY3R1cmU6IGxhbWJkYS5BcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcygxNSksXG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICByZXRyeUF0dGVtcHRzOiAyLFxuICAgICAgZHVyYWJsZUNvbmZpZzoge1xuICAgICAgICBleGVjdXRpb25UaW1lb3V0OiBEdXJhdGlvbi5ob3VycygyKSxcbiAgICAgICAgcmV0ZW50aW9uUGVyaW9kOiBEdXJhdGlvbi5kYXlzKDEpLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIFNMQUNLX1NFQ1JFVF9OQU1FOiBwcm9wcy5zZWNyZXRzLnNsYWNrU2VjcmV0TmFtZSxcbiAgICAgIH0sXG4gICAgICBwYXJhbXNBbmRTZWNyZXRzOiBsYW1iZGEuUGFyYW1zQW5kU2VjcmV0c0xheWVyVmVyc2lvbi5mcm9tVmVyc2lvbihsYW1iZGEuUGFyYW1zQW5kU2VjcmV0c1ZlcnNpb25zLlYxXzBfMTAzLCB7XG4gICAgICAgIGNhY2hlU2l6ZTogNTAwLFxuICAgICAgICBsb2dMZXZlbDogbGFtYmRhLlBhcmFtc0FuZFNlY3JldHNMb2dMZXZlbC5JTkZPLFxuICAgICAgfSksXG4gICAgICByb2xlOiBuZXcgaWFtLlJvbGUodGhpcywgJ1J1bm5pbmdTY2hlZHVsZXJGdW5jdGlvblJvbGUnLCB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3dzIHRoZSBydW5uaW5nIHNjaGVkdWxlciB0byBkZXNjcmliZSwgc3RhcnQsIGFuZCBzdG9wIEVDMiBpbnN0YW5jZXMgYW5kIHJlYWQgU2xhY2sgc2VjcmV0cy4nLFxuICAgICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgICAgbWFuYWdlZFBvbGljaWVzOiBbXG4gICAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlJyksXG4gICAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNEdXJhYmxlRXhlY3V0aW9uUm9sZVBvbGljeScpLFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgICBsb2dHcm91cDogbmV3IGxvZ3MuTG9nR3JvdXAodGhpcywgJ1J1bm5pbmdTY2hlZHVsZXJGdW5jdGlvbkxvZ0dyb3VwJywge1xuICAgICAgICByZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5USFJFRV9NT05USFMsXG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIH0pLFxuICAgICAgbG9nZ2luZ0Zvcm1hdDogbGFtYmRhLkxvZ2dpbmdGb3JtYXQuSlNPTixcbiAgICAgIHN5c3RlbUxvZ0xldmVsVjI6IGxhbWJkYS5TeXN0ZW1Mb2dMZXZlbC5JTkZPLFxuICAgICAgYXBwbGljYXRpb25Mb2dMZXZlbFYyOiBsYW1iZGEuQXBwbGljYXRpb25Mb2dMZXZlbC5JTkZPLFxuICAgIH0pO1xuICAgIHJ1bm5pbmdTY2hlZHVsZUZ1bmN0aW9uLmFkZFRvUm9sZVBvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6ICdHZXRSZXNvdXJjZXMnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAndGFnOkdldFJlc291cmNlcycsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICB9KSk7XG4gICAgLy8gRUMyOiBkZXNjcmliZSBpbnN0YW5jZXMgYW5kIHN0YXJ0L3N0b3AgYnkgaW5zdGFuY2UgaWRcbiAgICBydW5uaW5nU2NoZWR1bGVGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiAnRWMyUnVubmluZ0NvbnRyb2wnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAnZWMyOkRlc2NyaWJlSW5zdGFuY2VzJyxcbiAgICAgICAgJ2VjMjpTdGFydEluc3RhbmNlcycsXG4gICAgICAgICdlYzI6U3RvcEluc3RhbmNlcycsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICB9KSk7XG4gICAgLy8gR3JhbnQgcmVhZCBhY2Nlc3MgdG8gdGhlIFNsYWNrIHNlY3JldFxuICAgIHNsYWNrU2VjcmV0LmdyYW50UmVhZChydW5uaW5nU2NoZWR1bGVGdW5jdGlvbik7XG5cbiAgICAvLyBTZWU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sYW1iZGEvbGF0ZXN0L2RnL2R1cmFibGUtZ2V0dGluZy1zdGFydGVkLWlhYy5odG1sXG4gICAgY29uc3QgcnVubmluZ1NjaGVkdWxlRnVuY3Rpb25BbGlhcyA9IHJ1bm5pbmdTY2hlZHVsZUZ1bmN0aW9uLmFkZEFsaWFzKCdsaXZlJyk7XG5cbiAgICAvLyBXaGV0aGVyIHNjaGVkdWxlcyBhcmUgZW5hYmxlZCAoZGVmYXVsdCB0cnVlIHVubGVzcyBleHBsaWNpdGx5IGRpc2FibGVkKS5cbiAgICBjb25zdCBzY2hlZHVsZUVuYWJsZWQ6IGJvb2xlYW4gPSAoKCkgPT4ge1xuICAgICAgaWYgKHByb3BzLmVuYWJsZVNjaGVkdWxpbmcgPT09IHVuZGVmaW5lZCB8fCBwcm9wcy5lbmFibGVTY2hlZHVsaW5nKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICAvLyBEdXJhYmxlIEZ1bmN0aW9uczogTGFtYmRhIHBlcmZvcm1zIHRhZyBsb29rdXAgYW5kIGluc3RhbmNlIHN0YXJ0L3N0b3AgaW4gYSBzaW5nbGUgcnVuLlxuICAgIG5ldyBzY2hlZHVsZXIuU2NoZWR1bGUodGhpcywgJ1J1bm5pbmdTdGFydFNjaGVkdWxlJywge1xuICAgICAgZGVzY3JpcHRpb246ICdydW5uaW5nIHN0YXJ0IHNjaGVkdWxlJyxcbiAgICAgIGVuYWJsZWQ6IHNjaGVkdWxlRW5hYmxlZCxcbiAgICAgIHNjaGVkdWxlOiBzY2hlZHVsZXIuU2NoZWR1bGVFeHByZXNzaW9uLmNyb24oe1xuICAgICAgICBtaW51dGU6IHByb3BzLnN0YXJ0U2NoZWR1bGU/Lm1pbnV0ZSA/PyAnNTAnLFxuICAgICAgICBob3VyOiBwcm9wcy5zdGFydFNjaGVkdWxlPy5ob3VyID8/ICc3JyxcbiAgICAgICAgd2Vla0RheTogcHJvcHMuc3RhcnRTY2hlZHVsZT8ud2VlayA/PyAnTU9OLUZSSScsXG4gICAgICAgIHRpbWVab25lOiBwcm9wcy5zdGFydFNjaGVkdWxlPy50aW1lem9uZSA/PyBUaW1lWm9uZS5FVENfVVRDLFxuICAgICAgfSksXG4gICAgICB0YXJnZXQ6IG5ldyB0YXJnZXRzLkxhbWJkYUludm9rZShydW5uaW5nU2NoZWR1bGVGdW5jdGlvbkFsaWFzLCB7XG4gICAgICAgIGlucHV0OiBzY2hlZHVsZXIuU2NoZWR1bGVUYXJnZXRJbnB1dC5mcm9tT2JqZWN0KHtcbiAgICAgICAgICBQYXJhbXM6IHtcbiAgICAgICAgICAgIFRhZ0tleTogcHJvcHMudGFyZ2V0UmVzb3VyY2UudGFnS2V5LFxuICAgICAgICAgICAgVGFnVmFsdWVzOiBwcm9wcy50YXJnZXRSZXNvdXJjZS50YWdWYWx1ZXMsXG4gICAgICAgICAgICBNb2RlOiAnU3RhcnQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBuZXcgc2NoZWR1bGVyLlNjaGVkdWxlKHRoaXMsICdSdW5uaW5nU3RvcFNjaGVkdWxlJywge1xuICAgICAgZGVzY3JpcHRpb246ICdydW5uaW5nIHN0b3Agc2NoZWR1bGUnLFxuICAgICAgZW5hYmxlZDogc2NoZWR1bGVFbmFibGVkLFxuICAgICAgc2NoZWR1bGU6IHNjaGVkdWxlci5TY2hlZHVsZUV4cHJlc3Npb24uY3Jvbih7XG4gICAgICAgIG1pbnV0ZTogcHJvcHMuc3RvcFNjaGVkdWxlPy5taW51dGUgPz8gJzUnLFxuICAgICAgICBob3VyOiBwcm9wcy5zdG9wU2NoZWR1bGU/LmhvdXIgPz8gJzE5JyxcbiAgICAgICAgd2Vla0RheTogcHJvcHMuc3RvcFNjaGVkdWxlPy53ZWVrID8/ICdNT04tRlJJJyxcbiAgICAgICAgdGltZVpvbmU6IHByb3BzLnN0b3BTY2hlZHVsZT8udGltZXpvbmUgPz8gVGltZVpvbmUuRVRDX1VUQyxcbiAgICAgIH0pLFxuICAgICAgdGFyZ2V0OiBuZXcgdGFyZ2V0cy5MYW1iZGFJbnZva2UocnVubmluZ1NjaGVkdWxlRnVuY3Rpb25BbGlhcywge1xuICAgICAgICBpbnB1dDogc2NoZWR1bGVyLlNjaGVkdWxlVGFyZ2V0SW5wdXQuZnJvbU9iamVjdCh7XG4gICAgICAgICAgUGFyYW1zOiB7XG4gICAgICAgICAgICBUYWdLZXk6IHByb3BzLnRhcmdldFJlc291cmNlLnRhZ0tleSxcbiAgICAgICAgICAgIFRhZ1ZhbHVlczogcHJvcHMudGFyZ2V0UmVzb3VyY2UudGFnVmFsdWVzLFxuICAgICAgICAgICAgTW9kZTogJ1N0b3AnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSksXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -25,7 +25,7 @@ export interface SchedulerEvent {
25
25
  * and uses durable `step` / `wait` / `map` so the run can resume across suspensions.
26
26
  *
27
27
  * @param event - Payload from EventBridge Scheduler; must include `Params.TagKey`, `Params.TagValues`, `Params.Mode`.
28
- * @param context - Root durable execution context.
28
+ * @param ctx - Root durable execution context.
29
29
  * @returns
30
30
  * - `{ status: 'TargetResourcesNotFound' }` when no instances match the tag filter.
31
31
  * - `{ status: 'Completed', processed, results }` when instances were handled (`results` entries match {@link processOneResource}).
@@ -14,6 +14,7 @@ const client_ec2_1 = require("@aws-sdk/client-ec2");
14
14
  const client_resource_groups_tagging_api_1 = require("@aws-sdk/client-resource-groups-tagging-api");
15
15
  const web_api_1 = require("@slack/web-api");
16
16
  const aws_lambda_secret_fetcher_1 = require("aws-lambda-secret-fetcher");
17
+ const safe_env_getter_1 = require("safe-env-getter");
17
18
  const running_scheduler_predicates_1 = require("./running-scheduler-predicates");
18
19
  /** Mapping of EC2 instance state to display name and emoji for Slack. */
19
20
  const STATE_LIST = [
@@ -50,6 +51,13 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
50
51
  const account = arnParts[4] ?? '';
51
52
  const region = arnParts[3] ?? '';
52
53
  const stepPrefix = `resource-${resourceIndex}-${identifier}`;
54
+ ctx.logger.info('processOneResource: start', {
55
+ resourceIndex,
56
+ identifier,
57
+ region,
58
+ account,
59
+ mode: params.Mode,
60
+ });
53
61
  let loopCount = 0;
54
62
  let currentState = '';
55
63
  do {
@@ -58,21 +66,37 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
58
66
  const out = await ec2.send(new client_ec2_1.DescribeInstancesCommand({ InstanceIds: [identifier] }));
59
67
  return out.Reservations?.[0]?.Instances?.[0]?.State?.Name ?? 'unknown';
60
68
  });
69
+ ctx.logger.info('processOneResource: described', {
70
+ identifier,
71
+ loopCount,
72
+ currentState,
73
+ mode: params.Mode,
74
+ });
61
75
  const mode = params.Mode;
62
76
  if (mode === 'Start' && currentState === 'stopped') {
77
+ ctx.logger.info('processOneResource: starting instance', { identifier, loopCount });
63
78
  await ctx.step(`${stepPrefix}-start-${loopCount}`, async () => {
64
79
  const ec2 = new client_ec2_1.EC2Client({});
65
80
  await ec2.send(new client_ec2_1.StartInstancesCommand({ InstanceIds: [identifier] }));
66
81
  });
82
+ ctx.logger.info('processOneResource: wait after start', {
83
+ identifier,
84
+ seconds: STATUS_CHANGE_WAIT_SECONDS,
85
+ });
67
86
  await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
68
87
  loopCount += 1;
69
88
  continue;
70
89
  }
71
90
  if (mode === 'Stop' && currentState === 'running') {
91
+ ctx.logger.info('processOneResource: stopping instance', { identifier, loopCount });
72
92
  await ctx.step(`${stepPrefix}-stop-${loopCount}`, async () => {
73
93
  const ec2 = new client_ec2_1.EC2Client({});
74
94
  await ec2.send(new client_ec2_1.StopInstancesCommand({ InstanceIds: [identifier] }));
75
95
  });
96
+ ctx.logger.info('processOneResource: wait after stop', {
97
+ identifier,
98
+ seconds: STATUS_CHANGE_WAIT_SECONDS,
99
+ });
76
100
  await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
77
101
  loopCount += 1;
78
102
  continue;
@@ -81,13 +105,32 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
81
105
  const transitioning = (mode === 'Start' && currentState === 'pending') ||
82
106
  (mode === 'Stop' && (currentState === 'stopping' || currentState === 'shutting-down'));
83
107
  if (transitioning) {
108
+ ctx.logger.info('processOneResource: wait while transitioning', {
109
+ identifier,
110
+ loopCount,
111
+ currentState,
112
+ mode,
113
+ seconds: STATUS_CHANGE_WAIT_SECONDS,
114
+ });
84
115
  await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
85
116
  loopCount += 1;
86
117
  continue;
87
118
  }
119
+ ctx.logger.error('processOneResource: unexpected state', {
120
+ identifier,
121
+ mode,
122
+ currentState,
123
+ loopCount,
124
+ });
88
125
  throw new Error(`instance status fail: mode=${mode} currentState=${currentState}`);
89
126
  }
90
127
  } while (!(0, running_scheduler_predicates_1.isDesiredStableState)(params.Mode, currentState));
128
+ ctx.logger.info('processOneResource: reached desired stable state', {
129
+ identifier,
130
+ finalState: currentState,
131
+ mode: params.Mode,
132
+ loopCount,
133
+ });
91
134
  return {
92
135
  identifier,
93
136
  account,
@@ -104,60 +147,83 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
104
147
  * and uses durable `step` / `wait` / `map` so the run can resume across suspensions.
105
148
  *
106
149
  * @param event - Payload from EventBridge Scheduler; must include `Params.TagKey`, `Params.TagValues`, `Params.Mode`.
107
- * @param context - Root durable execution context.
150
+ * @param ctx - Root durable execution context.
108
151
  * @returns
109
152
  * - `{ status: 'TargetResourcesNotFound' }` when no instances match the tag filter.
110
153
  * - `{ status: 'Completed', processed, results }` when instances were handled (`results` entries match {@link processOneResource}).
111
154
  * @throws {Error} If `Params` is invalid, `SLACK_SECRET_NAME` is unset, the Slack secret is incomplete, or instance processing fails.
112
155
  */
113
- exports.handler = (0, durable_execution_sdk_js_1.withDurableExecution)(async (event, context) => {
156
+ exports.handler = (0, durable_execution_sdk_js_1.withDurableExecution)(async (event, ctx) => {
114
157
  const params = event.Params;
158
+ ctx.logger.info('running-scheduler: invocation', {
159
+ mode: params?.Mode,
160
+ tagKey: params?.TagKey,
161
+ tagValueCount: params?.TagValues?.length ?? 0,
162
+ });
115
163
  if (!params?.TagKey || !params?.TagValues || !params?.Mode) {
116
164
  throw new Error('Invalid event: Params.TagKey, Params.TagValues, Params.Mode are required.');
117
165
  }
118
- const slackSecretName = process.env.SLACK_SECRET_NAME;
119
- if (!slackSecretName) {
120
- throw new Error('missing environment variable SLACK_SECRET_NAME.');
121
- }
122
- const slackSecretValue = await context.step('fetch-slack-secret', async () => {
166
+ // safe get Secrets name from environment variable
167
+ const slackSecretName = safe_env_getter_1.SafeEnvGetter.getEnv('SLACK_SECRET_NAME');
168
+ const slackSecretValue = await ctx.step('fetch-slack-secret', async () => {
169
+ ctx.logger.info('running-scheduler: fetching Slack secret', { secretName: slackSecretName });
123
170
  return aws_lambda_secret_fetcher_1.secretFetcher.getSecretValue(slackSecretName);
124
171
  });
172
+ ctx.logger.info('running-scheduler: Slack secret loaded');
125
173
  if (!slackSecretValue?.token || !slackSecretValue?.channel) {
126
174
  throw new Error('Slack secret must contain token and channel.');
127
175
  }
128
- const targetResources = await context.step('get-target-resources', async () => {
176
+ const targetResources = await ctx.step('get-target-resources', async () => {
129
177
  const client = new client_resource_groups_tagging_api_1.ResourceGroupsTaggingAPIClient({});
130
178
  const result = await client.send(new client_resource_groups_tagging_api_1.GetResourcesCommand({
131
179
  ResourceTypeFilters: ['ec2:instance'],
132
180
  TagFilters: [{ Key: params.TagKey, Values: params.TagValues }],
133
181
  }));
134
- return (result.ResourceTagMappingList ?? [])
182
+ const arns = (result.ResourceTagMappingList ?? [])
135
183
  .map((m) => m.ResourceARN)
136
184
  .filter((arn) => arn != null);
185
+ ctx.logger.info('running-scheduler: get-target-resources done', { count: arns.length });
186
+ return arns;
137
187
  });
138
188
  if (targetResources.length === 0) {
189
+ ctx.logger.info('running-scheduler: no matching instances', { tagKey: params.TagKey });
139
190
  return { status: 'TargetResourcesNotFound' };
140
191
  }
141
192
  const client = new web_api_1.WebClient(slackSecretValue.token);
142
193
  const channel = slackSecretValue.channel;
194
+ ctx.logger.info('running-scheduler: posting parent Slack message', {
195
+ instanceCount: targetResources.length,
196
+ });
143
197
  // send slack message
144
- const slackParentMessageResult = await context.step('post-slack-messages', async () => {
198
+ const slackParentMessageResult = await ctx.step('post-slack-messages', async () => {
145
199
  return client.chat.postMessage({
146
200
  channel,
147
201
  text: `${params.Mode === 'Start' ? '😆 Starts' : '🥱 Stops'} the scheduled EC2 Instance.`,
148
202
  });
149
203
  });
150
- const results = await context.map(targetResources,
204
+ ctx.logger.info('running-scheduler: parent Slack message posted', {
205
+ threadTs: slackParentMessageResult?.ts ?? null,
206
+ });
207
+ ctx.logger.info('running-scheduler: starting parallel instance processing', {
208
+ count: targetResources.length,
209
+ maxConcurrency: 10,
210
+ });
211
+ const results = await ctx.map(targetResources,
151
212
  // async (ctx: DurableContext, targetResource: string, index: number) =>
152
213
  // ctx.step(`process-resource-${index}`, async () =>
153
214
  // processOneResource(ctx, targetResource, params, index),
154
215
  // ),
155
- async (ctx, targetResource, index) => {
156
- return ctx.runInChildContext(`resource-${index}`, async (childCtx) => {
216
+ async (mapCtx, targetResource, index) => {
217
+ return mapCtx.runInChildContext(`resource-${index}`, async (childCtx) => {
157
218
  const result = await processOneResource(childCtx, targetResource, params, index);
158
219
  // if (result.status === 'skipped') {
159
220
  // return result;
160
221
  // }
222
+ childCtx.logger.info('running-scheduler: posting thread Slack message', {
223
+ index,
224
+ identifier: result.identifier,
225
+ status: result.status,
226
+ });
161
227
  // send slack thread message
162
228
  await childCtx.step('post-slack-child-messages', async () => {
163
229
  const display = getStateDisplay(result.status);
@@ -182,10 +248,14 @@ exports.handler = (0, durable_execution_sdk_js_1.withDurableExecution)(async (ev
182
248
  });
183
249
  }, { maxConcurrency: 10 });
184
250
  const resultList = Array.isArray(results) ? results : [];
251
+ ctx.logger.info('running-scheduler: completed', {
252
+ processed: targetResources.length,
253
+ resultCount: resultList.length,
254
+ });
185
255
  return {
186
256
  status: 'Completed',
187
257
  processed: targetResources.length,
188
258
  results: resultList,
189
259
  };
190
260
  });
191
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVubmluZy1zY2hlZHVsZXIubGFtYmRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Z1bmNzL3J1bm5pbmctc2NoZWR1bGVyLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7R0FPRzs7O0FBRUgsNEVBQTBGO0FBQzFGLG9EQUs2QjtBQUM3QixvR0FBa0g7QUFDbEgsNENBQTJDO0FBQzNDLHlFQUEwRDtBQUMxRCxpRkFBc0U7QUFFdEUseUVBQXlFO0FBQ3pFLE1BQU0sVUFBVSxHQUFHO0lBQ2pCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7SUFDbEQsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtDQUMxQyxDQUFDO0FBRVgsdUVBQXVFO0FBQ3ZFLE1BQU0sMEJBQTBCLEdBQUcsRUFBRSxDQUFDO0FBc0J0Qzs7Ozs7R0FLRztBQUNILE1BQU0sZUFBZSxHQUFHLENBQUMsT0FBZSxFQUErQyxFQUFFO0lBQ3ZGLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLENBQUM7SUFDMUQsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3RFLENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLGtCQUFrQixHQUFHLEtBQUssRUFDOUIsR0FBbUIsRUFDbkIsY0FBc0IsRUFDdEIsTUFBZ0MsRUFDaEMsYUFBcUIsRUFDK0UsRUFBRTtJQUN0RyxNQUFNLEtBQUssR0FBRyxjQUFj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LyoqXG4gKiBFQzIgUnVubmluZyBTY2hlZHVsZXIg4oCTIER1cmFibGUgRnVuY3Rpb25zIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIEltcGxlbWVudHMgdGhlIHJ1bm5pbmctY29udHJvbCBmbG93IHVzaW5nIEFXUyBMYW1iZGEgRHVyYWJsZSBFeGVjdXRpb24uXG4gKiBTdGVwIGNoZWNrcG9pbnRzLCB3YWl0IChubyBjaGFyZ2UpLCBhbmQgcGFyYWxsZWwgbWFwIHByb3ZpZGUgYSBmbG93IGVxdWl2YWxlbnQgdG8gU3RlcCBGdW5jdGlvbnMuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGsuaHRtbFxuICovXG5cbmltcG9ydCB7IHdpdGhEdXJhYmxlRXhlY3V0aW9uLCB0eXBlIER1cmFibGVDb250ZXh0IH0gZnJvbSAnQGF3cy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGstanMnO1xuaW1wb3J0IHtcbiAgRUMyQ2xpZW50LFxuICBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQsXG4gIFN0YXJ0SW5zdGFuY2VzQ29tbWFuZCxcbiAgU3RvcEluc3RhbmNlc0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lYzInO1xuaW1wb3J0IHsgR2V0UmVzb3VyY2VzQ29tbWFuZCwgUmVzb3VyY2VHcm91cHNUYWdnaW5nQVBJQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXJlc291cmNlLWdyb3Vwcy10YWdnaW5nLWFwaSc7XG5pbXBvcnQgeyBXZWJDbGllbnQgfSBmcm9tICdAc2xhY2svd2ViLWFwaSc7XG5pbXBvcnQgeyBzZWNyZXRGZXRjaGVyIH0gZnJvbSAnYXdzLWxhbWJkYS1zZWNyZXQtZmV0Y2hlcic7XG5pbXBvcnQgeyBpc0Rlc2lyZWRTdGFibGVTdGF0ZSB9IGZyb20gJy4vcnVubmluZy1zY2hlZHVsZXItcHJlZGljYXRlcyc7XG5cbi8qKiBNYXBwaW5nIG9mIEVDMiBpbnN0YW5jZSBzdGF0ZSB0byBkaXNwbGF5IG5hbWUgYW5kIGVtb2ppIGZvciBTbGFjay4gKi9cbmNvbnN0IFNUQVRFX0xJU1QgPSBbXG4gIHsgbmFtZTogJ1JVTk5JTkcnLCBlbW9qaTogJ/CfmIYnLCBzdGF0ZTogJ3J1bm5pbmcnIH0sXG4gIHsgbmFtZTogJ1NUT1BQRUQnLCBlbW9qaTogJ/CfmLQnLCBzdGF0ZTogJ3N0b3BwZWQnIH0sXG5dIGFzIGNvbnN0O1xuXG4vKiogU2Vjb25kcyB0byB3YWl0IGJldHdlZW4gcG9sbGluZyBpbnN0YW5jZSBzdGF0ZSBhZnRlciBzdGFydC9zdG9wLiAqL1xuY29uc3QgU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgPSAyMDtcblxuLyoqIEV2ZW50IHBheWxvYWQgZnJvbSBFdmVudEJyaWRnZSBTY2hlZHVsZXIgaW52b2tpbmcgdGhpcyBMYW1iZGEuICovXG5leHBvcnQgaW50ZXJmYWNlIFNjaGVkdWxlckV2ZW50IHtcbiAgUGFyYW1zOiB7XG4gICAgLyoqIFRhZyBrZXkgdXNlZCB0byBzZWxlY3QgRUMyIGluc3RhbmNlcy4gKi9cbiAgICBUYWdLZXk6IHN0cmluZztcbiAgICAvKiogVGFnIHZhbHVlcyB0byBtYXRjaC4gKi9cbiAgICBUYWdWYWx1ZXM6IHN0cmluZ1tdO1xuICAgIC8qKiBXaGV0aGVyIHRvIHN0YXJ0IG9yIHN0b3AgaW5zdGFuY2VzLiAqL1xuICAgIE1vZGU6ICdTdGFydCcgfCAnU3RvcCc7XG4gIH07XG59XG5cbi8qKiBTbGFjayBjcmVkZW50aWFscyBhbmQgZGVmYXVsdCBjaGFubmVsIGxvYWRlZCBmcm9tIFNlY3JldHMgTWFuYWdlciAoYFNMQUNLX1NFQ1JFVF9OQU1FYCkuICovXG5pbnRlcmZhY2UgU2xhY2tTZWNyZXQge1xuICAvKiogU2xhY2sgYm90IHRva2VuIGZvciB0aGUgU2xhY2sgYFdlYkNsaWVudGAuICovXG4gIHRva2VuOiBzdHJpbmc7XG4gIC8qKiBDaGFubmVsIElEIG9yIG5hbWUgcGFzc2VkIHRvIGBjaGF0LnBvc3RNZXNzYWdlYC4gKi9cbiAgY2hhbm5lbDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJldHVybnMgZGlzcGxheSBuYW1lIGFuZCBlbW9qaSBmb3IgYW4gRUMyIGluc3RhbmNlIHN0YXRlLlxuICpcbiAqIEBwYXJhbSBjdXJyZW50IC0gQ3VycmVudCBpbnN0YW5jZSBzdGF0ZSAoZS5nLiAncnVubmluZycsICdzdG9wcGVkJykuXG4gKiBAcmV0dXJucyBEaXNwbGF5IGluZm8gb3IgdW5kZWZpbmVkIGlmIHN0YXRlIGlzIG5vdCBpbiBTVEFURV9MSVNULlxuICovXG5jb25zdCBnZXRTdGF0ZURpc3BsYXkgPSAoY3VycmVudDogc3RyaW5nKTogeyBlbW9qaTogc3RyaW5nOyBuYW1lOiBzdHJpbmcgfSB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IGZvdW5kID0gU1RBVEVfTElTVC5maW5kKChzKSA9PiBzLnN0YXRlID09PSBjdXJyZW50KTtcbiAgcmV0dXJuIGZvdW5kID8geyBlbW9qaTogZm91bmQuZW1vamksIG5hbWU6IGZvdW5kLm5hbWUgfSA6IHVuZGVmaW5lZDtcbn07XG5cbi8qKlxuICogUHJvY2Vzc2VzIG9uZSBFQzIgaW5zdGFuY2U6IGRlc2NyaWJlcyBzdGF0ZSwgaXNzdWVzIHN0YXJ0L3N0b3Agd2hlbiBuZWVkZWQsIHRoZW4gcG9sbHMgdW50aWxcbiAqIHtAbGluayBpc0Rlc2lyZWRTdGFibGVTdGF0ZX0gaXMgc2F0aXNmaWVkIChkdXJhYmxlIGBzdGVwYCAvIGB3YWl0YCBiZXR3ZWVuIGF0dGVtcHRzKS5cbiAqXG4gKiBAcGFyYW0gY3R4IC0gRHVyYWJsZSBleGVjdXRpb24gY29udGV4dCAoY2hpbGQgY29udGV4dCBwZXIgaW5zdGFuY2UgcmVjb21tZW5kZWQpLlxuICogQHBhcmFtIHRhcmdldFJlc291cmNlIC0gRUMyIGluc3RhbmNlIEFSTi5cbiAqIEBwYXJhbSBwYXJhbXMgLSBTY2hlZHVsZXIgcGFyYW1zIChgVGFnS2V5YCwgYFRhZ1ZhbHVlc2AsIGBNb2RlYCkuXG4gKiBAcGFyYW0gcmVzb3VyY2VJbmRleCAtIEluZGV4IHVzZWQgaW4gZHVyYWJsZSBzdGVwIG5hbWVzIGZvciB0aGlzIHJlc291cmNlLlxuICogQHJldHVybnMgRmluYWwgcmVzb3VyY2UgQVJOLCBFQzIgc3RhdGUgbmFtZSwgcGFyc2VkIGFjY291bnQsIHJlZ2lvbiwgYW5kIGluc3RhbmNlIGlkLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBzdGF0ZSBpcyBuZWl0aGVyIGFjdGlvbmFibGUsIHRyYW5zaXRpb25pbmcsIG5vciB0aGUgZGVzaXJlZCBzdGFibGUgc3RhdGUuXG4gKi9cbmNvbnN0IHByb2Nlc3NPbmVSZXNvdXJjZSA9IGFzeW5jIChcbiAgY3R4OiBEdXJhYmxlQ29udGV4dCxcbiAgdGFyZ2V0UmVzb3VyY2U6IHN0cmluZyxcbiAgcGFyYW1zOiBTY2hlZHVsZXJFdmVudFsnUGFyYW1zJ10sXG4gIHJlc291cmNlSW5kZXg6IG51bWJlcixcbik6IFByb21pc2U8eyByZXNvdXJjZTogc3RyaW5nOyBzdGF0dXM6IHN0cmluZzsgYWNjb3VudDogc3RyaW5nOyByZWdpb246IHN0cmluZzsgaWRlbnRpZmllcjogc3RyaW5nIH0+ID0+IHtcbiAgY29uc3QgcGFydHMgPSB0YXJnZXRSZXNvdXJjZS5zcGxpdCgnLycpO1xuICBjb25zdCBpZGVudGlmaWVyID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPz8gJ3Vua25vd24nO1xuICBjb25zdCBhcm5QYXJ0cyA9IHRhcmdldFJlc291cmNlLnNwbGl0KCc6Jyk7XG4gIGNvbnN0IGFjY291bnQgPSBhcm5QYXJ0c1s0XSA/PyAnJztcbiAgY29uc3QgcmVnaW9uID0gYXJuUGFydHNbM10gPz8gJyc7XG4gIGNvbnN0IHN0ZXBQcmVmaXggPSBgcmVzb3VyY2UtJHtyZXNvdXJjZUluZGV4fS0ke2lkZW50aWZpZXJ9YDtcblxuICBsZXQgbG9vcENvdW50ID0gMDtcbiAgbGV0IGN1cnJlbnRTdGF0ZSA9ICcnO1xuICBkbyB7XG4gICAgY3VycmVudFN0YXRlID0gYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tZGVzY3JpYmUtJHtsb29wQ291bnR9YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZWMyID0gbmV3IEVDMkNsaWVudCh7fSk7XG4gICAgICBjb25zdCBvdXQgPSBhd2FpdCBlYzIuc2VuZChuZXcgRGVzY3JpYmVJbnN0YW5jZXNDb21tYW5kKHsgSW5zdGFuY2VJZHM6IFtpZGVudGlmaWVyXSB9KSk7XG4gICAgICByZXR1cm4gb3V0LlJlc2VydmF0aW9ucz8uWzBdPy5JbnN0YW5jZXM/LlswXT8uU3RhdGU/Lk5hbWUgPz8gJ3Vua25vd24nO1xuICAgIH0pO1xuXG4gICAgY29uc3QgbW9kZSA9IHBhcmFtcy5Nb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdTdGFydCcgJiYgY3VycmVudFN0YXRlID09PSAnc3RvcHBlZCcpIHtcbiAgICAgIGF3YWl0IGN0eC5zdGVwKGAke3N0ZXBQcmVmaXh9LXN0YXJ0LSR7bG9vcENvdW50fWAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgZWMyID0gbmV3IEVDMkNsaWVudCh7fSk7XG4gICAgICAgIGF3YWl0IGVjMi5zZW5kKG5ldyBTdGFydEluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgY3R4LndhaXQoeyBzZWNvbmRzOiBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyB9KTtcbiAgICAgIGxvb3BDb3VudCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKG1vZGUgPT09ICdTdG9wJyAmJiBjdXJyZW50U3RhdGUgPT09ICdydW5uaW5nJykge1xuICAgICAgYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tc3RvcC0ke2xvb3BDb3VudH1gLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVjMiA9IG5ldyBFQzJDbGllbnQoe30pO1xuICAgICAgICBhd2FpdCBlYzIuc2VuZChuZXcgU3RvcEluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgY3R4LndhaXQoeyBzZWNvbmRzOiBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyB9KTtcbiAgICAgIGxvb3BDb3VudCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKCFpc0Rlc2lyZWRTdGFibGVTdGF0ZShtb2RlLCBjdXJyZW50U3RhdGUpKSB7XG4gICAgICBjb25zdCB0cmFuc2l0aW9uaW5nID1cbiAgICAgICAgKG1vZGUgPT09ICdTdGFydCcgJiYgY3VycmVudFN0YXRlID09PSAncGVuZGluZycpIHx8XG4gICAgICAgIChtb2RlID09PSAnU3RvcCcgJiYgKGN1cnJlbnRTdGF0ZSA9PT0gJ3N0b3BwaW5nJyB8fCBjdXJyZW50U3RhdGUgPT09ICdzaHV0dGluZy1kb3duJykpO1xuXG4gICAgICBpZiAodHJhbnNpdGlvbmluZykge1xuICAgICAgICBhd2FpdCBjdHgud2FpdCh7IHNlY29uZHM6IFNUQVRVU19DSEFOR0VfV0FJVF9TRUNPTkRTIH0pO1xuICAgICAgICBsb29wQ291bnQgKz0gMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW5zdGFuY2Ugc3RhdHVzIGZhaWw6IG1vZGU9JHttb2RlfSBjdXJyZW50U3RhdGU9JHtjdXJyZW50U3RhdGV9YCk7XG4gICAgfVxuICB9IHdoaWxlICghaXNEZXNpcmVkU3RhYmxlU3RhdGUocGFyYW1zLk1vZGUsIGN1cnJlbnRTdGF0ZSkpO1xuXG4gIHJldHVybiB7XG4gICAgaWRlbnRpZmllcixcbiAgICBhY2NvdW50LFxuICAgIHJlZ2lvbixcbiAgICByZXNvdXJjZTogdGFyZ2V0UmVzb3VyY2UsXG4gICAgc3RhdHVzOiBjdXJyZW50U3RhdGUsXG4gIH07XG59O1xuXG4vKipcbiAqIER1cmFibGUgTGFtYmRhIGVudHJ5IHBvaW50IGZvciB0aGUgRUMyIHJ1bm5pbmcgc2NoZWR1bGVyLlxuICpcbiAqIFJlc29sdmVzIGluc3RhbmNlcyB2aWEgUmVzb3VyY2UgR3JvdXBzIFRhZ2dpbmcgQVBJLCBydW5zIHtAbGluayBwcm9jZXNzT25lUmVzb3VyY2V9IGZvciBlYWNoIEFSTlxuICogaW4gcGFyYWxsZWwgKGJvdW5kZWQgY29uY3VycmVuY3kpLCBwb3N0cyBhIHBhcmVudCBTbGFjayBtZXNzYWdlIGFuZCBwZXItaW5zdGFuY2UgdGhyZWFkIHJlcGxpZXMsXG4gKiBhbmQgdXNlcyBkdXJhYmxlIGBzdGVwYCAvIGB3YWl0YCAvIGBtYXBgIHNvIHRoZSBydW4gY2FuIHJlc3VtZSBhY3Jvc3Mgc3VzcGVuc2lvbnMuXG4gKlxuICogQHBhcmFtIGV2ZW50IC0gUGF5bG9hZCBmcm9tIEV2ZW50QnJpZGdlIFNjaGVkdWxlcjsgbXVzdCBpbmNsdWRlIGBQYXJhbXMuVGFnS2V5YCwgYFBhcmFtcy5UYWdWYWx1ZXNgLCBgUGFyYW1zLk1vZGVgLlxuICogQHBhcmFtIGNvbnRleHQgLSBSb290IGR1cmFibGUgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcmV0dXJuc1xuICogLSBgeyBzdGF0dXM6ICdUYXJnZXRSZXNvdXJjZXNOb3RGb3VuZCcgfWAgd2hlbiBubyBpbnN0YW5jZXMgbWF0Y2ggdGhlIHRhZyBmaWx0ZXIuXG4gKiAtIGB7IHN0YXR1czogJ0NvbXBsZXRlZCcsIHByb2Nlc3NlZCwgcmVzdWx0cyB9YCB3aGVuIGluc3RhbmNlcyB3ZXJlIGhhbmRsZWQgKGByZXN1bHRzYCBlbnRyaWVzIG1hdGNoIHtAbGluayBwcm9jZXNzT25lUmVzb3VyY2V9KS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBgUGFyYW1zYCBpcyBpbnZhbGlkLCBgU0xBQ0tfU0VDUkVUX05BTUVgIGlzIHVuc2V0LCB0aGUgU2xhY2sgc2VjcmV0IGlzIGluY29tcGxldGUsIG9yIGluc3RhbmNlIHByb2Nlc3NpbmcgZmFpbHMuXG4gKi9cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gd2l0aER1cmFibGVFeGVjdXRpb24oYXN5bmMgKGV2ZW50OiBTY2hlZHVsZXJFdmVudCwgY29udGV4dDogRHVyYWJsZUNvbnRleHQpID0+IHtcblxuICBjb25zdCBwYXJhbXMgPSBldmVudC5QYXJhbXM7XG5cbiAgaWYgKCFwYXJhbXM/LlRhZ0tleSB8fCAhcGFyYW1zPy5UYWdWYWx1ZXMgfHwgIXBhcmFtcz8uTW9kZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBldmVudDogUGFyYW1zLlRhZ0tleSwgUGFyYW1zLlRhZ1ZhbHVlcywgUGFyYW1zLk1vZGUgYXJlIHJlcXVpcmVkLicpO1xuICB9XG4gIGNvbnN0IHNsYWNrU2VjcmV0TmFtZSA9IHByb2Nlc3MuZW52LlNMQUNLX1NFQ1JFVF9OQU1FO1xuICBpZiAoIXNsYWNrU2VjcmV0TmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBlbnZpcm9ubWVudCB2YXJpYWJsZSBTTEFDS19TRUNSRVRfTkFNRS4nKTtcbiAgfVxuICBjb25zdCBzbGFja1NlY3JldFZhbHVlID0gYXdhaXQgY29udGV4dC5zdGVwKCdmZXRjaC1zbGFjay1zZWNyZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgcmV0dXJuIHNlY3JldEZldGNoZXIuZ2V0U2VjcmV0VmFsdWU8U2xhY2tTZWNyZXQ+KHNsYWNrU2VjcmV0TmFtZSk7XG4gIH0pO1xuXG4gIGlmICghc2xhY2tTZWNyZXRWYWx1ZT8udG9rZW4gfHwgIXNsYWNrU2VjcmV0VmFsdWU/LmNoYW5uZWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NsYWNrIHNlY3JldCBtdXN0IGNvbnRhaW4gdG9rZW4gYW5kIGNoYW5uZWwuJyk7XG4gIH1cblxuICBjb25zdCB0YXJnZXRSZXNvdXJjZXMgPSBhd2FpdCBjb250ZXh0LnN0ZXAoJ2dldC10YXJnZXQtcmVzb3VyY2VzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBSZXNvdXJjZUdyb3Vwc1RhZ2dpbmdBUElDbGllbnQoe30pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5zZW5kKFxuICAgICAgbmV3IEdldFJlc291cmNlc0NvbW1hbmQoe1xuICAgICAgICBSZXNvdXJjZVR5cGVGaWx0ZXJzOiBbJ2VjMjppbnN0YW5jZSddLFxuICAgICAgICBUYWdGaWx0ZXJzOiBbeyBLZXk6IHBhcmFtcy5UYWdLZXksIFZhbHVlczogcGFyYW1zLlRhZ1ZhbHVlcyB9XSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIChyZXN1bHQuUmVzb3VyY2VUYWdNYXBwaW5nTGlzdCA/PyBbXSlcbiAgICAgIC5tYXAoKG06IHsgUmVzb3VyY2VBUk4/OiBzdHJpbmcgfSkgPT4gbS5SZXNvdXJjZUFSTilcbiAgICAgIC5maWx0ZXIoKGFybjogc3RyaW5nIHwgdW5kZWZpbmVkKTogYXJuIGlzIHN0cmluZyA9PiBhcm4gIT0gbnVsbCk7XG4gIH0pO1xuXG4gIGlmICh0YXJnZXRSZXNvdXJjZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHsgc3RhdHVzOiAnVGFyZ2V0UmVzb3VyY2VzTm90Rm91bmQnIGFzIGNvbnN0IH07XG4gIH1cblxuICBjb25zdCBjbGllbnQgPSBuZXcgV2ViQ2xpZW50KHNsYWNrU2VjcmV0VmFsdWUudG9rZW4pO1xuICBjb25zdCBjaGFubmVsID0gc2xhY2tTZWNyZXRWYWx1ZS5jaGFubmVsO1xuXG4gIC8vIHNlbmQgc2xhY2sgbWVzc2FnZVxuICBjb25zdCBzbGFja1BhcmVudE1lc3NhZ2VSZXN1bHQgPSBhd2FpdCBjb250ZXh0LnN0ZXAoJ3Bvc3Qtc2xhY2stbWVzc2FnZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgcmV0dXJuIGNsaWVudC5jaGF0LnBvc3RNZXNzYWdlKHtcbiAgICAgIGNoYW5uZWwsXG4gICAgICB0ZXh0OiBgJHtwYXJhbXMuTW9kZSA9PT0gJ1N0YXJ0JyA/ICfwn5iGIFN0YXJ0cycgOiAn8J+lsSBTdG9wcyd9IHRoZSBzY2hlZHVsZWQgRUMyIEluc3RhbmNlLmAsXG4gICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBjb250ZXh0Lm1hcChcbiAgICB0YXJnZXRSZXNvdXJjZXMsXG4gICAgLy8gYXN5bmMgKGN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+XG4gICAgLy8gICBjdHguc3RlcChgcHJvY2Vzcy1yZXNvdXJjZS0ke2luZGV4fWAsIGFzeW5jICgpID0+XG4gICAgLy8gICAgIHByb2Nlc3NPbmVSZXNvdXJjZShjdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KSxcbiAgICAvLyAgICksXG4gICAgYXN5bmMgKGN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIHJldHVybiBjdHgucnVuSW5DaGlsZENvbnRleHQoYHJlc291cmNlLSR7aW5kZXh9YCwgYXN5bmMgKGNoaWxkQ3R4OiBEdXJhYmxlQ29udGV4dCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9jZXNzT25lUmVzb3VyY2UoY2hpbGRDdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KTtcbiAgICAgICAgLy8gaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdza2lwcGVkJykge1xuICAgICAgICAvLyAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIC8vIH1cbiAgICAgICAgLy8gc2VuZCBzbGFjayB0aHJlYWQgbWVzc2FnZVxuICAgICAgICBhd2FpdCBjaGlsZEN0eC5zdGVwKCdwb3N0LXNsYWNrLWNoaWxkLW1lc3NhZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRpc3BsYXkgPSBnZXRTdGF0ZURpc3BsYXkocmVzdWx0LnN0YXR1cyk7XG5cbiAgICAgICAgICByZXR1cm4gY2xpZW50LmNoYXQucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgIHRocmVhZF90czogc2xhY2tQYXJlbnRNZXNzYWdlUmVzdWx0Py50cyxcbiAgICAgICAgICAgIGF0dGFjaG1lbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjb2xvcjogJyMzNmE2NGYnLFxuICAgICAgICAgICAgICAgIHByZXRleHQ6IGAke2Rpc3BsYXk/LmVtb2ppfSBUaGUgc3RhdHVzIG9mIHRoZSBFQzIgSW5zdGFuY2UgJHtyZXN1bHQuaWRlbnRpZmllcn0gY2hhbmdlZCB0byAke2Rpc3BsYXk/Lm5hbWV9IGR1ZSB0byB0aGUgc2NoZWR1bGUuYCxcbiAgICAgICAgICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICAgICAgICAgIHsgdGl0bGU6ICdBY2NvdW50JywgdmFsdWU6IHJlc3VsdC5hY2NvdW50LCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgeyB0aXRsZTogJ1JlZ2lvbicsIHZhbHVlOiByZXN1bHQucmVnaW9uLCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgeyB0aXRsZTogJ0lkZW50aWZpZXInLCB2YWx1ZTogcmVzdWx0LmlkZW50aWZpZXIsIHNob3J0OiB0cnVlIH0sXG4gICAgICAgICAgICAgICAgICB7IHRpdGxlOiAnU3RhdHVzJywgdmFsdWU6IChkaXNwbGF5Py5uYW1lID8/ICdVbmtub3duJyksIHNob3J0OiB0cnVlIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfSxcbiAgICB7IG1heENvbmN1cnJlbmN5OiAxMCB9LFxuICApO1xuXG4gIGNvbnN0IHJlc3VsdExpc3QgPSBBcnJheS5pc0FycmF5KHJlc3VsdHMpID8gcmVzdWx0cyA6IFtdO1xuICByZXR1cm4ge1xuICAgIHN0YXR1czogJ0NvbXBsZXRlZCcgYXMgY29uc3QsXG4gICAgcHJvY2Vzc2VkOiB0YXJnZXRSZXNvdXJjZXMubGVuZ3RoLFxuICAgIHJlc3VsdHM6IHJlc3VsdExpc3QsXG4gIH07XG59KTtcbiJdfQ==
261
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVubmluZy1zY2hlZHVsZXIubGFtYmRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Z1bmNzL3J1bm5pbmctc2NoZWR1bGVyLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7R0FPRzs7O0FBRUgsNEVBQTBGO0FBQzFGLG9EQUs2QjtBQUM3QixvR0FBa0g7QUFDbEgsNENBQTJDO0FBQzNDLHlFQUEwRDtBQUMxRCxxREFBZ0Q7QUFDaEQsaUZBQXNFO0FBRXRFLHlFQUF5RTtBQUN6RSxNQUFNLFVBQVUsR0FBRztJQUNqQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFO0lBQ2xELEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7Q0FDMUMsQ0FBQztBQUVYLHVFQUF1RTtBQUN2RSxNQUFNLDBCQUEwQixHQUFHLEVBQUUsQ0FBQztBQXNCdEM7Ozs7O0dBS0c7QUFDSCxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQWUsRUFBK0MsRUFBRTtJQUN2RixNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLE9BQU8sQ0FBQyxDQUFDO0lBQzFELE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUN0RSxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBRyxLQUFLLEVBQzlCLEdBQW1CLEVBQ25CLGNBQXNCLEVBQ3RCLE1BQWdDLEVBQ2hDLGFBQXFCLEVBQytFLEVBQUU7SUFDdEcsTUFBTSxL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Q0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDhCQUE4QixFQUFFO1FBQzlDLFNBQVMsRUFBRSxlQUFlLENBQUMsTUFBTTtRQUNqQyxXQUFXLEVBQUUsVUFBVSxDQUFDLE1BQU07S0FDL0IsQ0FBQyxDQUFDO0lBQ0gsT0FBTztRQUNMLE1BQU0sRUFBRSxXQUFvQjtRQUM1QixTQUFTLEVBQUUsZUFBZSxDQUFDLE1BQU07UUFDakMsT0FBTyxFQUFFLFVBQVU7S0FDcEIsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBFQzIgUnVubmluZyBTY2hlZHVsZXIg4oCTIER1cmFibGUgRnVuY3Rpb25zIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIEltcGxlbWVudHMgdGhlIHJ1bm5pbmctY29udHJvbCBmbG93IHVzaW5nIEFXUyBMYW1iZGEgRHVyYWJsZSBFeGVjdXRpb24uXG4gKiBTdGVwIGNoZWNrcG9pbnRzLCB3YWl0IChubyBjaGFyZ2UpLCBhbmQgcGFyYWxsZWwgbWFwIHByb3ZpZGUgYSBmbG93IGVxdWl2YWxlbnQgdG8gU3RlcCBGdW5jdGlvbnMuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGsuaHRtbFxuICovXG5cbmltcG9ydCB7IHdpdGhEdXJhYmxlRXhlY3V0aW9uLCB0eXBlIER1cmFibGVDb250ZXh0IH0gZnJvbSAnQGF3cy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGstanMnO1xuaW1wb3J0IHtcbiAgRUMyQ2xpZW50LFxuICBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQsXG4gIFN0YXJ0SW5zdGFuY2VzQ29tbWFuZCxcbiAgU3RvcEluc3RhbmNlc0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lYzInO1xuaW1wb3J0IHsgR2V0UmVzb3VyY2VzQ29tbWFuZCwgUmVzb3VyY2VHcm91cHNUYWdnaW5nQVBJQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXJlc291cmNlLWdyb3Vwcy10YWdnaW5nLWFwaSc7XG5pbXBvcnQgeyBXZWJDbGllbnQgfSBmcm9tICdAc2xhY2svd2ViLWFwaSc7XG5pbXBvcnQgeyBzZWNyZXRGZXRjaGVyIH0gZnJvbSAnYXdzLWxhbWJkYS1zZWNyZXQtZmV0Y2hlcic7XG5pbXBvcnQgeyBTYWZlRW52R2V0dGVyIH0gZnJvbSAnc2FmZS1lbnYtZ2V0dGVyJztcbmltcG9ydCB7IGlzRGVzaXJlZFN0YWJsZVN0YXRlIH0gZnJvbSAnLi9ydW5uaW5nLXNjaGVkdWxlci1wcmVkaWNhdGVzJztcblxuLyoqIE1hcHBpbmcgb2YgRUMyIGluc3RhbmNlIHN0YXRlIHRvIGRpc3BsYXkgbmFtZSBhbmQgZW1vamkgZm9yIFNsYWNrLiAqL1xuY29uc3QgU1RBVEVfTElTVCA9IFtcbiAgeyBuYW1lOiAnUlVOTklORycsIGVtb2ppOiAn8J+YhicsIHN0YXRlOiAncnVubmluZycgfSxcbiAgeyBuYW1lOiAnU1RPUFBFRCcsIGVtb2ppOiAn8J+YtCcsIHN0YXRlOiAnc3RvcHBlZCcgfSxcbl0gYXMgY29uc3Q7XG5cbi8qKiBTZWNvbmRzIHRvIHdhaXQgYmV0d2VlbiBwb2xsaW5nIGluc3RhbmNlIHN0YXRlIGFmdGVyIHN0YXJ0L3N0b3AuICovXG5jb25zdCBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyA9IDIwO1xuXG4vKiogRXZlbnQgcGF5bG9hZCBmcm9tIEV2ZW50QnJpZGdlIFNjaGVkdWxlciBpbnZva2luZyB0aGlzIExhbWJkYS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZWR1bGVyRXZlbnQge1xuICBQYXJhbXM6IHtcbiAgICAvKiogVGFnIGtleSB1c2VkIHRvIHNlbGVjdCBFQzIgaW5zdGFuY2VzLiAqL1xuICAgIFRhZ0tleTogc3RyaW5nO1xuICAgIC8qKiBUYWcgdmFsdWVzIHRvIG1hdGNoLiAqL1xuICAgIFRhZ1ZhbHVlczogc3RyaW5nW107XG4gICAgLyoqIFdoZXRoZXIgdG8gc3RhcnQgb3Igc3RvcCBpbnN0YW5jZXMuICovXG4gICAgTW9kZTogJ1N0YXJ0JyB8ICdTdG9wJztcbiAgfTtcbn1cblxuLyoqIFNsYWNrIGNyZWRlbnRpYWxzIGFuZCBkZWZhdWx0IGNoYW5uZWwgbG9hZGVkIGZyb20gU2VjcmV0cyBNYW5hZ2VyIChgU0xBQ0tfU0VDUkVUX05BTUVgKS4gKi9cbmludGVyZmFjZSBTbGFja1NlY3JldCB7XG4gIC8qKiBTbGFjayBib3QgdG9rZW4gZm9yIHRoZSBTbGFjayBgV2ViQ2xpZW50YC4gKi9cbiAgdG9rZW46IHN0cmluZztcbiAgLyoqIENoYW5uZWwgSUQgb3IgbmFtZSBwYXNzZWQgdG8gYGNoYXQucG9zdE1lc3NhZ2VgLiAqL1xuICBjaGFubmVsOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmV0dXJucyBkaXNwbGF5IG5hbWUgYW5kIGVtb2ppIGZvciBhbiBFQzIgaW5zdGFuY2Ugc3RhdGUuXG4gKlxuICogQHBhcmFtIGN1cnJlbnQgLSBDdXJyZW50IGluc3RhbmNlIHN0YXRlIChlLmcuICdydW5uaW5nJywgJ3N0b3BwZWQnKS5cbiAqIEByZXR1cm5zIERpc3BsYXkgaW5mbyBvciB1bmRlZmluZWQgaWYgc3RhdGUgaXMgbm90IGluIFNUQVRFX0xJU1QuXG4gKi9cbmNvbnN0IGdldFN0YXRlRGlzcGxheSA9IChjdXJyZW50OiBzdHJpbmcpOiB7IGVtb2ppOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9IHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgZm91bmQgPSBTVEFURV9MSVNULmZpbmQoKHMpID0+IHMuc3RhdGUgPT09IGN1cnJlbnQpO1xuICByZXR1cm4gZm91bmQgPyB7IGVtb2ppOiBmb3VuZC5lbW9qaSwgbmFtZTogZm91bmQubmFtZSB9IDogdW5kZWZpbmVkO1xufTtcblxuLyoqXG4gKiBQcm9jZXNzZXMgb25lIEVDMiBpbnN0YW5jZTogZGVzY3JpYmVzIHN0YXRlLCBpc3N1ZXMgc3RhcnQvc3RvcCB3aGVuIG5lZWRlZCwgdGhlbiBwb2xscyB1bnRpbFxuICoge0BsaW5rIGlzRGVzaXJlZFN0YWJsZVN0YXRlfSBpcyBzYXRpc2ZpZWQgKGR1cmFibGUgYHN0ZXBgIC8gYHdhaXRgIGJldHdlZW4gYXR0ZW1wdHMpLlxuICpcbiAqIEBwYXJhbSBjdHggLSBEdXJhYmxlIGV4ZWN1dGlvbiBjb250ZXh0IChjaGlsZCBjb250ZXh0IHBlciBpbnN0YW5jZSByZWNvbW1lbmRlZCkuXG4gKiBAcGFyYW0gdGFyZ2V0UmVzb3VyY2UgLSBFQzIgaW5zdGFuY2UgQVJOLlxuICogQHBhcmFtIHBhcmFtcyAtIFNjaGVkdWxlciBwYXJhbXMgKGBUYWdLZXlgLCBgVGFnVmFsdWVzYCwgYE1vZGVgKS5cbiAqIEBwYXJhbSByZXNvdXJjZUluZGV4IC0gSW5kZXggdXNlZCBpbiBkdXJhYmxlIHN0ZXAgbmFtZXMgZm9yIHRoaXMgcmVzb3VyY2UuXG4gKiBAcmV0dXJucyBGaW5hbCByZXNvdXJjZSBBUk4sIEVDMiBzdGF0ZSBuYW1lLCBwYXJzZWQgYWNjb3VudCwgcmVnaW9uLCBhbmQgaW5zdGFuY2UgaWQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHN0YXRlIGlzIG5laXRoZXIgYWN0aW9uYWJsZSwgdHJhbnNpdGlvbmluZywgbm9yIHRoZSBkZXNpcmVkIHN0YWJsZSBzdGF0ZS5cbiAqL1xuY29uc3QgcHJvY2Vzc09uZVJlc291cmNlID0gYXN5bmMgKFxuICBjdHg6IER1cmFibGVDb250ZXh0LFxuICB0YXJnZXRSZXNvdXJjZTogc3RyaW5nLFxuICBwYXJhbXM6IFNjaGVkdWxlckV2ZW50WydQYXJhbXMnXSxcbiAgcmVzb3VyY2VJbmRleDogbnVtYmVyLFxuKTogUHJvbWlzZTx7IHJlc291cmNlOiBzdHJpbmc7IHN0YXR1czogc3RyaW5nOyBhY2NvdW50OiBzdHJpbmc7IHJlZ2lvbjogc3RyaW5nOyBpZGVudGlmaWVyOiBzdHJpbmcgfT4gPT4ge1xuICBjb25zdCBwYXJ0cyA9IHRhcmdldFJlc291cmNlLnNwbGl0KCcvJyk7XG4gIGNvbnN0IGlkZW50aWZpZXIgPSBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSA/PyAndW5rbm93bic7XG4gIGNvbnN0IGFyblBhcnRzID0gdGFyZ2V0UmVzb3VyY2Uuc3BsaXQoJzonKTtcbiAgY29uc3QgYWNjb3VudCA9IGFyblBhcnRzWzRdID8/ICcnO1xuICBjb25zdCByZWdpb24gPSBhcm5QYXJ0c1szXSA/PyAnJztcbiAgY29uc3Qgc3RlcFByZWZpeCA9IGByZXNvdXJjZS0ke3Jlc291cmNlSW5kZXh9LSR7aWRlbnRpZmllcn1gO1xuXG4gIGN0eC5sb2dnZXIuaW5mbygncHJvY2Vzc09uZVJlc291cmNlOiBzdGFydCcsIHtcbiAgICByZXNvdXJjZUluZGV4LFxuICAgIGlkZW50aWZpZXIsXG4gICAgcmVnaW9uLFxuICAgIGFjY291bnQsXG4gICAgbW9kZTogcGFyYW1zLk1vZGUsXG4gIH0pO1xuXG4gIGxldCBsb29wQ291bnQgPSAwO1xuICBsZXQgY3VycmVudFN0YXRlID0gJyc7XG4gIGRvIHtcbiAgICBjdXJyZW50U3RhdGUgPSBhd2FpdCBjdHguc3RlcChgJHtzdGVwUHJlZml4fS1kZXNjcmliZS0ke2xvb3BDb3VudH1gLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlYzIgPSBuZXcgRUMyQ2xpZW50KHt9KTtcbiAgICAgIGNvbnN0IG91dCA9IGF3YWl0IGVjMi5zZW5kKG5ldyBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIHJldHVybiBvdXQuUmVzZXJ2YXRpb25zPy5bMF0/Lkluc3RhbmNlcz8uWzBdPy5TdGF0ZT8uTmFtZSA/PyAndW5rbm93bic7XG4gICAgfSk7XG5cbiAgICBjdHgubG9nZ2VyLmluZm8oJ3Byb2Nlc3NPbmVSZXNvdXJjZTogZGVzY3JpYmVkJywge1xuICAgICAgaWRlbnRpZmllcixcbiAgICAgIGxvb3BDb3VudCxcbiAgICAgIGN1cnJlbnRTdGF0ZSxcbiAgICAgIG1vZGU6IHBhcmFtcy5Nb2RlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgbW9kZSA9IHBhcmFtcy5Nb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdTdGFydCcgJiYgY3VycmVudFN0YXRlID09PSAnc3RvcHBlZCcpIHtcbiAgICAgIGN0eC5sb2dnZXIuaW5mbygncHJvY2Vzc09uZVJlc291cmNlOiBzdGFydGluZyBpbnN0YW5jZScsIHsgaWRlbnRpZmllciwgbG9vcENvdW50IH0pO1xuICAgICAgYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tc3RhcnQtJHtsb29wQ291bnR9YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBlYzIgPSBuZXcgRUMyQ2xpZW50KHt9KTtcbiAgICAgICAgYXdhaXQgZWMyLnNlbmQobmV3IFN0YXJ0SW5zdGFuY2VzQ29tbWFuZCh7IEluc3RhbmNlSWRzOiBbaWRlbnRpZmllcl0gfSkpO1xuICAgICAgfSk7XG4gICAgICBjdHgubG9nZ2VyLmluZm8oJ3Byb2Nlc3NPbmVSZXNvdXJjZTogd2FpdCBhZnRlciBzdGFydCcsIHtcbiAgICAgICAgaWRlbnRpZmllcixcbiAgICAgICAgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IGN0eC53YWl0KHsgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgfSk7XG4gICAgICBsb29wQ291bnQgKz0gMTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChtb2RlID09PSAnU3RvcCcgJiYgY3VycmVudFN0YXRlID09PSAncnVubmluZycpIHtcbiAgICAgIGN0eC5sb2dnZXIuaW5mbygncHJvY2Vzc09uZVJlc291cmNlOiBzdG9wcGluZyBpbnN0YW5jZScsIHsgaWRlbnRpZmllciwgbG9vcENvdW50IH0pO1xuICAgICAgYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tc3RvcC0ke2xvb3BDb3VudH1gLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVjMiA9IG5ldyBFQzJDbGllbnQoe30pO1xuICAgICAgICBhd2FpdCBlYzIuc2VuZChuZXcgU3RvcEluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIH0pO1xuICAgICAgY3R4LmxvZ2dlci5pbmZvKCdwcm9jZXNzT25lUmVzb3VyY2U6IHdhaXQgYWZ0ZXIgc3RvcCcsIHtcbiAgICAgICAgaWRlbnRpZmllcixcbiAgICAgICAgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IGN0eC53YWl0KHsgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgfSk7XG4gICAgICBsb29wQ291bnQgKz0gMTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICghaXNEZXNpcmVkU3RhYmxlU3RhdGUobW9kZSwgY3VycmVudFN0YXRlKSkge1xuICAgICAgY29uc3QgdHJhbnNpdGlvbmluZyA9XG4gICAgICAgIChtb2RlID09PSAnU3RhcnQnICYmIGN1cnJlbnRTdGF0ZSA9PT0gJ3BlbmRpbmcnKSB8fFxuICAgICAgICAobW9kZSA9PT0gJ1N0b3AnICYmIChjdXJyZW50U3RhdGUgPT09ICdzdG9wcGluZycgfHwgY3VycmVudFN0YXRlID09PSAnc2h1dHRpbmctZG93bicpKTtcblxuICAgICAgaWYgKHRyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgY3R4LmxvZ2dlci5pbmZvKCdwcm9jZXNzT25lUmVzb3VyY2U6IHdhaXQgd2hpbGUgdHJhbnNpdGlvbmluZycsIHtcbiAgICAgICAgICBpZGVudGlmaWVyLFxuICAgICAgICAgIGxvb3BDb3VudCxcbiAgICAgICAgICBjdXJyZW50U3RhdGUsXG4gICAgICAgICAgbW9kZSxcbiAgICAgICAgICBzZWNvbmRzOiBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IGN0eC53YWl0KHsgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgfSk7XG4gICAgICAgIGxvb3BDb3VudCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY3R4LmxvZ2dlci5lcnJvcigncHJvY2Vzc09uZVJlc291cmNlOiB1bmV4cGVjdGVkIHN0YXRlJywge1xuICAgICAgICBpZGVudGlmaWVyLFxuICAgICAgICBtb2RlLFxuICAgICAgICBjdXJyZW50U3RhdGUsXG4gICAgICAgIGxvb3BDb3VudCxcbiAgICAgIH0pO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnN0YW5jZSBzdGF0dXMgZmFpbDogbW9kZT0ke21vZGV9IGN1cnJlbnRTdGF0ZT0ke2N1cnJlbnRTdGF0ZX1gKTtcbiAgICB9XG4gIH0gd2hpbGUgKCFpc0Rlc2lyZWRTdGFibGVTdGF0ZShwYXJhbXMuTW9kZSwgY3VycmVudFN0YXRlKSk7XG5cbiAgY3R4LmxvZ2dlci5pbmZvKCdwcm9jZXNzT25lUmVzb3VyY2U6IHJlYWNoZWQgZGVzaXJlZCBzdGFibGUgc3RhdGUnLCB7XG4gICAgaWRlbnRpZmllcixcbiAgICBmaW5hbFN0YXRlOiBjdXJyZW50U3RhdGUsXG4gICAgbW9kZTogcGFyYW1zLk1vZGUsXG4gICAgbG9vcENvdW50LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIGlkZW50aWZpZXIsXG4gICAgYWNjb3VudCxcbiAgICByZWdpb24sXG4gICAgcmVzb3VyY2U6IHRhcmdldFJlc291cmNlLFxuICAgIHN0YXR1czogY3VycmVudFN0YXRlLFxuICB9O1xufTtcblxuLyoqXG4gKiBEdXJhYmxlIExhbWJkYSBlbnRyeSBwb2ludCBmb3IgdGhlIEVDMiBydW5uaW5nIHNjaGVkdWxlci5cbiAqXG4gKiBSZXNvbHZlcyBpbnN0YW5jZXMgdmlhIFJlc291cmNlIEdyb3VwcyBUYWdnaW5nIEFQSSwgcnVucyB7QGxpbmsgcHJvY2Vzc09uZVJlc291cmNlfSBmb3IgZWFjaCBBUk5cbiAqIGluIHBhcmFsbGVsIChib3VuZGVkIGNvbmN1cnJlbmN5KSwgcG9zdHMgYSBwYXJlbnQgU2xhY2sgbWVzc2FnZSBhbmQgcGVyLWluc3RhbmNlIHRocmVhZCByZXBsaWVzLFxuICogYW5kIHVzZXMgZHVyYWJsZSBgc3RlcGAgLyBgd2FpdGAgLyBgbWFwYCBzbyB0aGUgcnVuIGNhbiByZXN1bWUgYWNyb3NzIHN1c3BlbnNpb25zLlxuICpcbiAqIEBwYXJhbSBldmVudCAtIFBheWxvYWQgZnJvbSBFdmVudEJyaWRnZSBTY2hlZHVsZXI7IG11c3QgaW5jbHVkZSBgUGFyYW1zLlRhZ0tleWAsIGBQYXJhbXMuVGFnVmFsdWVzYCwgYFBhcmFtcy5Nb2RlYC5cbiAqIEBwYXJhbSBjdHggLSBSb290IGR1cmFibGUgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcmV0dXJuc1xuICogLSBgeyBzdGF0dXM6ICdUYXJnZXRSZXNvdXJjZXNOb3RGb3VuZCcgfWAgd2hlbiBubyBpbnN0YW5jZXMgbWF0Y2ggdGhlIHRhZyBmaWx0ZXIuXG4gKiAtIGB7IHN0YXR1czogJ0NvbXBsZXRlZCcsIHByb2Nlc3NlZCwgcmVzdWx0cyB9YCB3aGVuIGluc3RhbmNlcyB3ZXJlIGhhbmRsZWQgKGByZXN1bHRzYCBlbnRyaWVzIG1hdGNoIHtAbGluayBwcm9jZXNzT25lUmVzb3VyY2V9KS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBgUGFyYW1zYCBpcyBpbnZhbGlkLCBgU0xBQ0tfU0VDUkVUX05BTUVgIGlzIHVuc2V0LCB0aGUgU2xhY2sgc2VjcmV0IGlzIGluY29tcGxldGUsIG9yIGluc3RhbmNlIHByb2Nlc3NpbmcgZmFpbHMuXG4gKi9cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gd2l0aER1cmFibGVFeGVjdXRpb24oYXN5bmMgKGV2ZW50OiBTY2hlZHVsZXJFdmVudCwgY3R4OiBEdXJhYmxlQ29udGV4dCkgPT4ge1xuXG4gIGNvbnN0IHBhcmFtcyA9IGV2ZW50LlBhcmFtcztcblxuICBjdHgubG9nZ2VyLmluZm8oJ3J1bm5pbmctc2NoZWR1bGVyOiBpbnZvY2F0aW9uJywge1xuICAgIG1vZGU6IHBhcmFtcz8uTW9kZSxcbiAgICB0YWdLZXk6IHBhcmFtcz8uVGFnS2V5LFxuICAgIHRhZ1ZhbHVlQ291bnQ6IHBhcmFtcz8uVGFnVmFsdWVzPy5sZW5ndGggPz8gMCxcbiAgfSk7XG5cbiAgaWYgKCFwYXJhbXM/LlRhZ0tleSB8fCAhcGFyYW1zPy5UYWdWYWx1ZXMgfHwgIXBhcmFtcz8uTW9kZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBldmVudDogUGFyYW1zLlRhZ0tleSwgUGFyYW1zLlRhZ1ZhbHVlcywgUGFyYW1zLk1vZGUgYXJlIHJlcXVpcmVkLicpO1xuICB9XG5cbiAgLy8gc2FmZSBnZXQgU2VjcmV0cyBuYW1lIGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgY29uc3Qgc2xhY2tTZWNyZXROYW1lID0gU2FmZUVudkdldHRlci5nZXRFbnYoJ1NMQUNLX1NFQ1JFVF9OQU1FJyk7XG5cbiAgY29uc3Qgc2xhY2tTZWNyZXRWYWx1ZSA9IGF3YWl0IGN0eC5zdGVwKCdmZXRjaC1zbGFjay1zZWNyZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogZmV0Y2hpbmcgU2xhY2sgc2VjcmV0JywgeyBzZWNyZXROYW1lOiBzbGFja1NlY3JldE5hbWUgfSk7XG4gICAgcmV0dXJuIHNlY3JldEZldGNoZXIuZ2V0U2VjcmV0VmFsdWU8U2xhY2tTZWNyZXQ+KHNsYWNrU2VjcmV0TmFtZSk7XG4gIH0pO1xuXG4gIGN0eC5sb2dnZXIuaW5mbygncnVubmluZy1zY2hlZHVsZXI6IFNsYWNrIHNlY3JldCBsb2FkZWQnKTtcblxuICBpZiAoIXNsYWNrU2VjcmV0VmFsdWU/LnRva2VuIHx8ICFzbGFja1NlY3JldFZhbHVlPy5jaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTbGFjayBzZWNyZXQgbXVzdCBjb250YWluIHRva2VuIGFuZCBjaGFubmVsLicpO1xuICB9XG5cbiAgY29uc3QgdGFyZ2V0UmVzb3VyY2VzID0gYXdhaXQgY3R4LnN0ZXAoJ2dldC10YXJnZXQtcmVzb3VyY2VzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBSZXNvdXJjZUdyb3Vwc1RhZ2dpbmdBUElDbGllbnQoe30pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5zZW5kKFxuICAgICAgbmV3IEdldFJlc291cmNlc0NvbW1hbmQoe1xuICAgICAgICBSZXNvdXJjZVR5cGVGaWx0ZXJzOiBbJ2VjMjppbnN0YW5jZSddLFxuICAgICAgICBUYWdGaWx0ZXJzOiBbeyBLZXk6IHBhcmFtcy5UYWdLZXksIFZhbHVlczogcGFyYW1zLlRhZ1ZhbHVlcyB9XSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgY29uc3QgYXJucyA9IChyZXN1bHQuUmVzb3VyY2VUYWdNYXBwaW5nTGlzdCA/PyBbXSlcbiAgICAgIC5tYXAoKG06IHsgUmVzb3VyY2VBUk4/OiBzdHJpbmcgfSkgPT4gbS5SZXNvdXJjZUFSTilcbiAgICAgIC5maWx0ZXIoKGFybjogc3RyaW5nIHwgdW5kZWZpbmVkKTogYXJuIGlzIHN0cmluZyA9PiBhcm4gIT0gbnVsbCk7XG4gICAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogZ2V0LXRhcmdldC1yZXNvdXJjZXMgZG9uZScsIHsgY291bnQ6IGFybnMubGVuZ3RoIH0pO1xuICAgIHJldHVybiBhcm5zO1xuICB9KTtcblxuICBpZiAodGFyZ2V0UmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIGN0eC5sb2dnZXIuaW5mbygncnVubmluZy1zY2hlZHVsZXI6IG5vIG1hdGNoaW5nIGluc3RhbmNlcycsIHsgdGFnS2V5OiBwYXJhbXMuVGFnS2V5IH0pO1xuICAgIHJldHVybiB7IHN0YXR1czogJ1RhcmdldFJlc291cmNlc05vdEZvdW5kJyBhcyBjb25zdCB9O1xuICB9XG5cbiAgY29uc3QgY2xpZW50ID0gbmV3IFdlYkNsaWVudChzbGFja1NlY3JldFZhbHVlLnRva2VuKTtcbiAgY29uc3QgY2hhbm5lbCA9IHNsYWNrU2VjcmV0VmFsdWUuY2hhbm5lbDtcblxuICBjdHgubG9nZ2VyLmluZm8oJ3J1bm5pbmctc2NoZWR1bGVyOiBwb3N0aW5nIHBhcmVudCBTbGFjayBtZXNzYWdlJywge1xuICAgIGluc3RhbmNlQ291bnQ6IHRhcmdldFJlc291cmNlcy5sZW5ndGgsXG4gIH0pO1xuXG4gIC8vIHNlbmQgc2xhY2sgbWVzc2FnZVxuICBjb25zdCBzbGFja1BhcmVudE1lc3NhZ2VSZXN1bHQgPSBhd2FpdCBjdHguc3RlcCgncG9zdC1zbGFjay1tZXNzYWdlcycsIGFzeW5jICgpID0+IHtcbiAgICByZXR1cm4gY2xpZW50LmNoYXQucG9zdE1lc3NhZ2Uoe1xuICAgICAgY2hhbm5lbCxcbiAgICAgIHRleHQ6IGAke3BhcmFtcy5Nb2RlID09PSAnU3RhcnQnID8gJ/CfmIYgU3RhcnRzJyA6ICfwn6WxIFN0b3BzJ30gdGhlIHNjaGVkdWxlZCBFQzIgSW5zdGFuY2UuYCxcbiAgICB9KTtcbiAgfSk7XG5cbiAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogcGFyZW50IFNsYWNrIG1lc3NhZ2UgcG9zdGVkJywge1xuICAgIHRocmVhZFRzOiBzbGFja1BhcmVudE1lc3NhZ2VSZXN1bHQ/LnRzID8/IG51bGwsXG4gIH0pO1xuXG4gIGN0eC5sb2dnZXIuaW5mbygncnVubmluZy1zY2hlZHVsZXI6IHN0YXJ0aW5nIHBhcmFsbGVsIGluc3RhbmNlIHByb2Nlc3NpbmcnLCB7XG4gICAgY291bnQ6IHRhcmdldFJlc291cmNlcy5sZW5ndGgsXG4gICAgbWF4Q29uY3VycmVuY3k6IDEwLFxuICB9KTtcblxuICBjb25zdCByZXN1bHRzID0gYXdhaXQgY3R4Lm1hcChcbiAgICB0YXJnZXRSZXNvdXJjZXMsXG4gICAgLy8gYXN5bmMgKGN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+XG4gICAgLy8gICBjdHguc3RlcChgcHJvY2Vzcy1yZXNvdXJjZS0ke2luZGV4fWAsIGFzeW5jICgpID0+XG4gICAgLy8gICAgIHByb2Nlc3NPbmVSZXNvdXJjZShjdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KSxcbiAgICAvLyAgICksXG4gICAgYXN5bmMgKG1hcEN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIHJldHVybiBtYXBDdHgucnVuSW5DaGlsZENvbnRleHQoYHJlc291cmNlLSR7aW5kZXh9YCwgYXN5bmMgKGNoaWxkQ3R4OiBEdXJhYmxlQ29udGV4dCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9jZXNzT25lUmVzb3VyY2UoY2hpbGRDdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KTtcbiAgICAgICAgLy8gaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdza2lwcGVkJykge1xuICAgICAgICAvLyAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIC8vIH1cbiAgICAgICAgY2hpbGRDdHgubG9nZ2VyLmluZm8oJ3J1bm5pbmctc2NoZWR1bGVyOiBwb3N0aW5nIHRocmVhZCBTbGFjayBtZXNzYWdlJywge1xuICAgICAgICAgIGluZGV4LFxuICAgICAgICAgIGlkZW50aWZpZXI6IHJlc3VsdC5pZGVudGlmaWVyLFxuICAgICAgICAgIHN0YXR1czogcmVzdWx0LnN0YXR1cyxcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHNlbmQgc2xhY2sgdGhyZWFkIG1lc3NhZ2VcbiAgICAgICAgYXdhaXQgY2hpbGRDdHguc3RlcCgncG9zdC1zbGFjay1jaGlsZC1tZXNzYWdlcycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBkaXNwbGF5ID0gZ2V0U3RhdGVEaXNwbGF5KHJlc3VsdC5zdGF0dXMpO1xuXG4gICAgICAgICAgcmV0dXJuIGNsaWVudC5jaGF0LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgICB0aHJlYWRfdHM6IHNsYWNrUGFyZW50TWVzc2FnZVJlc3VsdD8udHMsXG4gICAgICAgICAgICBhdHRhY2htZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgY29sb3I6ICcjMzZhNjRmJyxcbiAgICAgICAgICAgICAgICBwcmV0ZXh0OiBgJHtkaXNwbGF5Py5lbW9qaX0gVGhlIHN0YXR1cyBvZiB0aGUgRUMyIEluc3RhbmNlICR7cmVzdWx0LmlkZW50aWZpZXJ9IGNoYW5nZWQgdG8gJHtkaXNwbGF5Py5uYW1lfSBkdWUgdG8gdGhlIHNjaGVkdWxlLmAsXG4gICAgICAgICAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgICAgICAgICB7IHRpdGxlOiAnQWNjb3VudCcsIHZhbHVlOiByZXN1bHQuYWNjb3VudCwgc2hvcnQ6IHRydWUgfSxcbiAgICAgICAgICAgICAgICAgIHsgdGl0bGU6ICdSZWdpb24nLCB2YWx1ZTogcmVzdWx0LnJlZ2lvbiwgc2hvcnQ6IHRydWUgfSxcbiAgICAgICAgICAgICAgICAgIHsgdGl0bGU6ICdJZGVudGlmaWVyJywgdmFsdWU6IHJlc3VsdC5pZGVudGlmaWVyLCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgeyB0aXRsZTogJ1N0YXR1cycsIHZhbHVlOiAoZGlzcGxheT8ubmFtZSA/PyAnVW5rbm93bicpLCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgeyBtYXhDb25jdXJyZW5jeTogMTAgfSxcbiAgKTtcblxuICBjb25zdCByZXN1bHRMaXN0ID0gQXJyYXkuaXNBcnJheShyZXN1bHRzKSA/IHJlc3VsdHMgOiBbXTtcbiAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogY29tcGxldGVkJywge1xuICAgIHByb2Nlc3NlZDogdGFyZ2V0UmVzb3VyY2VzLmxlbmd0aCxcbiAgICByZXN1bHRDb3VudDogcmVzdWx0TGlzdC5sZW5ndGgsXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIHN0YXR1czogJ0NvbXBsZXRlZCcgYXMgY29uc3QsXG4gICAgcHJvY2Vzc2VkOiB0YXJnZXRSZXNvdXJjZXMubGVuZ3RoLFxuICAgIHJlc3VsdHM6IHJlc3VsdExpc3QsXG4gIH07XG59KTtcbiJdfQ==
@@ -29,5 +29,5 @@ class EC2InstanceRunningScheduleStack extends aws_cdk_lib_1.Stack {
29
29
  }
30
30
  exports.EC2InstanceRunningScheduleStack = EC2InstanceRunningScheduleStack;
31
31
  _a = JSII_RTTI_SYMBOL_1;
32
- EC2InstanceRunningScheduleStack[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduleStack", version: "3.0.9" };
32
+ EC2InstanceRunningScheduleStack[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduleStack", version: "3.1.0" };
33
33
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWMyLWluc3RhbmNlLXJ1bm5pbmctc2NoZWR1bGUtc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RhY2tzL2VjMi1pbnN0YW5jZS1ydW5uaW5nLXNjaGVkdWxlLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQWdEO0FBRWhELGlHQUE4SDtBQWtCOUg7O0dBRUc7QUFDSCxNQUFhLCtCQUFnQyxTQUFRLG1CQUFLO0lBQ3hEOzs7Ozs7T0FNRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBMkM7UUFDbkYsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFeEIsSUFBSSw0REFBMkIsQ0FBQyxJQUFJLEVBQUUsNkJBQTZCLEVBQUU7WUFDbkUsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQ3BDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7WUFDeEMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtZQUNoQyxhQUFhLEVBQUUsS0FBSyxDQUFDLGFBQWE7U0FDbkMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUFsQkgsMEVBbUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3RhY2ssIFN0YWNrUHJvcHMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEVDMkluc3RhbmNlUnVubmluZ1NjaGVkdWxlciwgVGFyZ2V0UmVzb3VyY2UsIFNlY3JldHMsIFNjaGVkdWxlIH0gZnJvbSAnLi4vY29uc3RydWN0cy9lYzItaW5zdGFuY2UtcnVubmluZy1zY2hlZHVsZXInO1xuXG4vKipcbiAqIFByb3BzIGZvciB0aGUgRUMyIGluc3RhbmNlIHJ1bm5pbmcgc2NoZWR1bGUgQ0RLIHN0YWNrLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVDMkluc3RhbmNlUnVubmluZ1NjaGVkdWxlU3RhY2tQcm9wcyBleHRlbmRzIFN0YWNrUHJvcHMge1xuICAvKiogVGFnLWJhc2VkIHRhcmdldCByZXNvdXJjZSBmb3IgRUMyIGluc3RhbmNlcyB0byBzdGFydC9zdG9wLiAqL1xuICByZWFkb25seSB0YXJnZXRSZXNvdXJjZTogVGFyZ2V0UmVzb3VyY2U7XG4gIC8qKiBXaGV0aGVyIHNjaGVkdWxpbmcgaXMgZW5hYmxlZC4gRGVmYXVsdHMgdG8gdHJ1ZSBpZiBvbWl0dGVkLiAqL1xuICByZWFkb25seSBlbmFibGVTY2hlZHVsaW5nPzogYm9vbGVhbjtcbiAgLyoqIFNlY3JldHMgKGUuZy4gU2xhY2spIGZvciB0aGUgc2NoZWR1bGVyLiAqL1xuICByZWFkb25seSBzZWNyZXRzOiBTZWNyZXRzO1xuICAvKiogQ3JvbiBzY2hlZHVsZSBmb3Igc3RvcHBpbmcgaW5zdGFuY2VzLiAqL1xuICByZWFkb25seSBzdG9wU2NoZWR1bGU/OiBTY2hlZHVsZTtcbiAgLyoqIENyb24gc2NoZWR1bGUgZm9yIHN0YXJ0aW5nIGluc3RhbmNlcy4gKi9cbiAgcmVhZG9ubHkgc3RhcnRTY2hlZHVsZT86IFNjaGVkdWxlO1xufVxuXG4vKipcbiAqIENESyBTdGFjayB0aGF0IGRlcGxveXMgdGhlIEVDMiBpbnN0YW5jZSBydW5uaW5nIHNjaGVkdWxlciAoRXZlbnRCcmlkZ2UgU2NoZWR1bGVyICsgRHVyYWJsZSBMYW1iZGEpLlxuICovXG5leHBvcnQgY2xhc3MgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVTdGFjayBleHRlbmRzIFN0YWNrIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIHN0YWNrIGFuZCB0aGUgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyIGNvbnN0cnVjdC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gUGFyZW50IGNvbnN0cnVjdC5cbiAgICogQHBhcmFtIGlkIC0gU3RhY2sgaWQuXG4gICAqIEBwYXJhbSBwcm9wcyAtIFN0YWNrIHByb3BzICh0YXJnZXQgcmVzb3VyY2UsIHNjaGVkdWxlcywgc2VjcmV0cykuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVTdGFja1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICBuZXcgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyKHRoaXMsICdFQzJJbnN0YW5jZVJ1bm5pbmdTY2hlZHVsZXInLCB7XG4gICAgICB0YXJnZXRSZXNvdXJjZTogcHJvcHMudGFyZ2V0UmVzb3VyY2UsXG4gICAgICBlbmFibGVTY2hlZHVsaW5nOiBwcm9wcy5lbmFibGVTY2hlZHVsaW5nLFxuICAgICAgc2VjcmV0czogcHJvcHMuc2VjcmV0cyxcbiAgICAgIHN0b3BTY2hlZHVsZTogcHJvcHMuc3RvcFNjaGVkdWxlLFxuICAgICAgc3RhcnRTY2hlZHVsZTogcHJvcHMuc3RhcnRTY2hlZHVsZSxcbiAgICB9KTtcbiAgfVxufSJdfQ==
package/package.json CHANGED
@@ -35,7 +35,7 @@
35
35
  "author": {
36
36
  "name": "yicr",
37
37
  "email": "yicr@users.noreply.github.com",
38
- "organization": true
38
+ "organization": false
39
39
  },
40
40
  "devDependencies": {
41
41
  "@aws-sdk/client-ec2": "^3",
@@ -54,7 +54,7 @@
54
54
  "aws-sdk-client-mock-jest": "^2",
55
55
  "commit-and-tag-version": "^12",
56
56
  "constructs": "10.5.1",
57
- "esbuild": "^0.27.4",
57
+ "esbuild": "^0.28.0",
58
58
  "eslint": "^9",
59
59
  "eslint-import-resolver-typescript": "^3.10.1",
60
60
  "eslint-plugin-import": "^2.32.0",
@@ -65,8 +65,9 @@
65
65
  "jsii-docgen": "^10.5.0",
66
66
  "jsii-pacmak": "^1.127.0",
67
67
  "jsii-rosetta": "5.9.x",
68
- "projen": "^0.99.26",
69
- "ts-jest": "^29.4.6",
68
+ "projen": "^0.99.34",
69
+ "safe-env-getter": "^0.2",
70
+ "ts-jest": "^29.4.9",
70
71
  "ts-node": "^10.9.2",
71
72
  "typescript": "5.9.x"
72
73
  },
@@ -87,12 +88,19 @@
87
88
  "engines": {
88
89
  "node": ">= 20.0.0"
89
90
  },
91
+ "devEngines": {
92
+ "packageManager": {
93
+ "name": "yarn",
94
+ "version": "<2.0.0",
95
+ "onFail": "ignore"
96
+ }
97
+ },
90
98
  "main": "lib/index.js",
91
99
  "license": "Apache-2.0",
92
100
  "publishConfig": {
93
101
  "access": "public"
94
102
  },
95
- "version": "3.0.9",
103
+ "version": "3.1.0",
96
104
  "jest": {
97
105
  "coverageProvider": "v8",
98
106
  "testMatch": [
@@ -148,5 +156,6 @@
148
156
  "rootDir": "src"
149
157
  }
150
158
  },
159
+ "packageManager": "yarn@1.22.22",
151
160
  "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
152
161
  }