rds-database-auto-start-preventer 0.2.6 → 0.3.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.
@@ -20566,7 +20566,7 @@ var require_lib = __commonJS({
20566
20566
  "node_modules/fetch-retrier/lib/index.js"(exports2) {
20567
20567
  "use strict";
20568
20568
  Object.defineProperty(exports2, "__esModule", { value: true });
20569
- exports2.fetchRetrier = exports2.FetchRetrierUnreachableError = exports2.FetchRetrierNetworkError = exports2.FetchRetrierHttpError = exports2.FetchRetrierAlreadyAbortedError = exports2.FetchRetrierAbortError = void 0;
20569
+ exports2.parseRetryAfterMs = exports2.fetchRetrier = exports2.defaultShouldRetry = exports2.DEFAULT_RETRYABLE_HTTP_STATUSES = exports2.FetchRetrierUnreachableError = exports2.FetchRetrierInvalidOptionsError = exports2.FetchRetrierNetworkError = exports2.FetchRetrierHttpError = exports2.FetchRetrierAlreadyAbortedError = exports2.FetchRetrierAbortError = void 0;
20570
20570
  var FetchRetrierAbortError = class _FetchRetrierAbortError extends Error {
20571
20571
  /**
20572
20572
  * @param message - Human-readable reason (default: `'Aborted'`)
@@ -20593,10 +20593,12 @@ var require_lib = __commonJS({
20593
20593
  /**
20594
20594
  * @param message - Error description
20595
20595
  * @param status - HTTP status code from the last non-OK response
20596
+ * @param body - Response body text already read via `response.text()` for that attempt
20596
20597
  */
20597
- constructor(message, status) {
20598
+ constructor(message, status, body) {
20598
20599
  super(message);
20599
20600
  this.status = status;
20601
+ this.body = body;
20600
20602
  this.name = "FetchRetrierHttpError";
20601
20603
  Object.setPrototypeOf(this, _FetchRetrierHttpError.prototype);
20602
20604
  }
@@ -20615,6 +20617,17 @@ var require_lib = __commonJS({
20615
20617
  }
20616
20618
  };
20617
20619
  exports2.FetchRetrierNetworkError = FetchRetrierNetworkError;
20620
+ var FetchRetrierInvalidOptionsError = class _FetchRetrierInvalidOptionsError extends TypeError {
20621
+ /**
20622
+ * @param message - Human-readable reason describing the invalid option
20623
+ */
20624
+ constructor(message) {
20625
+ super(message);
20626
+ this.name = "FetchRetrierInvalidOptionsError";
20627
+ Object.setPrototypeOf(this, _FetchRetrierInvalidOptionsError.prototype);
20628
+ }
20629
+ };
20630
+ exports2.FetchRetrierInvalidOptionsError = FetchRetrierInvalidOptionsError;
20618
20631
  var FetchRetrierUnreachableError = class _FetchRetrierUnreachableError extends Error {
20619
20632
  /**
20620
20633
  * @param message - Human-readable reason (default: `'Unreachable'`)
@@ -20626,11 +20639,26 @@ var require_lib = __commonJS({
20626
20639
  }
20627
20640
  };
20628
20641
  exports2.FetchRetrierUnreachableError = FetchRetrierUnreachableError;
20629
- var defaultShouldRetry = (res) => {
20630
- return [429, 500, 502, 503, 504].includes(res.status);
20642
+ exports2.DEFAULT_RETRYABLE_HTTP_STATUSES = [408, 425, 429, 500, 502, 503, 504];
20643
+ var defaultShouldRetry = (response, _body) => {
20644
+ return exports2.DEFAULT_RETRYABLE_HTTP_STATUSES.includes(response.status);
20645
+ };
20646
+ exports2.defaultShouldRetry = defaultShouldRetry;
20647
+ var validateRequestOptions = (options) => {
20648
+ const { retries, timeoutMs, baseBackoffMs } = options;
20649
+ if (retries < 1) {
20650
+ throw new FetchRetrierInvalidOptionsError("retries must be >= 1");
20651
+ }
20652
+ if (timeoutMs <= 0) {
20653
+ throw new FetchRetrierInvalidOptionsError("timeoutMs must be > 0");
20654
+ }
20655
+ if (baseBackoffMs < 0) {
20656
+ throw new FetchRetrierInvalidOptionsError("baseBackoffMs must be >= 0");
20657
+ }
20631
20658
  };
20632
20659
  var fetchRetrier = async (url, options) => {
20633
- const { headers, init, retries, timeoutMs, baseBackoffMs, signal: externalSignal, shouldRetry = defaultShouldRetry } = options;
20660
+ const { headers, init, retries, timeoutMs, baseBackoffMs, signal: externalSignal, shouldRetry = exports2.defaultShouldRetry } = options;
20661
+ validateRequestOptions({ retries, timeoutMs, baseBackoffMs });
20634
20662
  for (let attempt = 1; attempt <= retries; attempt++) {
20635
20663
  if (externalSignal?.aborted) {
20636
20664
  throw new FetchRetrierAlreadyAbortedError();
@@ -20659,11 +20687,11 @@ var require_lib = __commonJS({
20659
20687
  const isContinue = shouldRetry(res, text);
20660
20688
  if (isContinue) {
20661
20689
  if (attempt === retries) {
20662
- throw new FetchRetrierHttpError(`HTTP ${res.status}`, res.status);
20690
+ throw new FetchRetrierHttpError(`HTTP ${res.status}`, res.status, text);
20663
20691
  }
20664
- await wait(fullJitter(baseBackoffMs, attempt));
20692
+ await wait(resolveRetryDelayMs(res, baseBackoffMs, attempt));
20665
20693
  } else {
20666
- throw new FetchRetrierHttpError(`Non-retriable HTTP error: ${res.status}`, res.status);
20694
+ throw new FetchRetrierHttpError(`Non-retriable HTTP error: ${res.status}`, res.status, text);
20667
20695
  }
20668
20696
  } catch (err) {
20669
20697
  clearTimeout(timer);
@@ -20693,32 +20721,251 @@ var require_lib = __commonJS({
20693
20721
  const cap = base * Math.pow(2, attempt);
20694
20722
  return Math.floor(Math.random() * cap);
20695
20723
  };
20724
+ var parseRetryAfterMs = (value, nowMs = Date.now()) => {
20725
+ const trimmed = value.trim();
20726
+ if (trimmed === "") {
20727
+ return void 0;
20728
+ }
20729
+ if (/^\d+$/.test(trimmed)) {
20730
+ return Number.parseInt(trimmed, 10) * 1e3;
20731
+ }
20732
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
20733
+ return void 0;
20734
+ }
20735
+ const dateMs = Date.parse(trimmed);
20736
+ if (Number.isNaN(dateMs)) {
20737
+ return void 0;
20738
+ }
20739
+ return Math.max(0, dateMs - nowMs);
20740
+ };
20741
+ exports2.parseRetryAfterMs = parseRetryAfterMs;
20742
+ var resolveRetryDelayMs = (response, baseBackoffMs, attempt, nowMs = Date.now()) => {
20743
+ const header = response.headers?.get("Retry-After");
20744
+ if (header == null) {
20745
+ return fullJitter(baseBackoffMs, attempt);
20746
+ }
20747
+ const fromHeader = (0, exports2.parseRetryAfterMs)(header, nowMs);
20748
+ if (fromHeader === void 0) {
20749
+ return fullJitter(baseBackoffMs, attempt);
20750
+ }
20751
+ return fromHeader;
20752
+ };
20696
20753
  }
20697
20754
  });
20698
20755
 
20699
- // node_modules/aws-lambda-secret-fetcher/lib/index.js
20756
+ // node_modules/quiet-json-parser/lib/index.js
20700
20757
  var require_lib2 = __commonJS({
20758
+ "node_modules/quiet-json-parser/lib/index.js"(exports2) {
20759
+ "use strict";
20760
+ Object.defineProperty(exports2, "__esModule", { value: true });
20761
+ exports2.quietParse = void 0;
20762
+ var safeReviver = (key, value) => {
20763
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
20764
+ return void 0;
20765
+ }
20766
+ return value;
20767
+ };
20768
+ var quietParse = (jsonString, fallback, onError) => {
20769
+ if (!jsonString) {
20770
+ return fallback;
20771
+ }
20772
+ try {
20773
+ return JSON.parse(jsonString, safeReviver);
20774
+ } catch (error) {
20775
+ onError?.(error);
20776
+ return fallback;
20777
+ }
20778
+ };
20779
+ exports2.quietParse = quietParse;
20780
+ }
20781
+ });
20782
+
20783
+ // node_modules/aws-lambda-secret-fetcher/node_modules/strict-env-resolver/lib/index.js
20784
+ var require_lib3 = __commonJS({
20785
+ "node_modules/aws-lambda-secret-fetcher/node_modules/strict-env-resolver/lib/index.js"(exports2) {
20786
+ "use strict";
20787
+ Object.defineProperty(exports2, "__esModule", { value: true });
20788
+ exports2.StrictEnvResolver = exports2.StrictEnvType = exports2.StrictEnvValidationError = exports2.StrictEnvError = void 0;
20789
+ var TRUE_BOOLEAN_PATTERN = /^(1|true|yes|on)$/i;
20790
+ var parseNumber = (raw) => {
20791
+ const n = Number(raw);
20792
+ if (!Number.isFinite(n)) {
20793
+ return void 0;
20794
+ }
20795
+ return n;
20796
+ };
20797
+ var parseBooleanEnvValue = (normalizedRaw) => TRUE_BOOLEAN_PATTERN.test(normalizedRaw);
20798
+ var StrictEnvError = class extends Error {
20799
+ /**
20800
+ * @param message - Error message.
20801
+ */
20802
+ constructor(message) {
20803
+ super(message);
20804
+ this.name = "StrictEnvError";
20805
+ }
20806
+ };
20807
+ exports2.StrictEnvError = StrictEnvError;
20808
+ var StrictEnvValidationError = class _StrictEnvValidationError extends StrictEnvError {
20809
+ /**
20810
+ * Formats validation errors into a human-readable error message.
20811
+ *
20812
+ * @template K - Environment variable key type.
20813
+ * @param errors - Validation error entries to format.
20814
+ * @returns Multi-line summary listing each key and message.
20815
+ */
20816
+ static format(errors) {
20817
+ const lines = errors.map((e) => `- ${e.key}: ${e.message}${e.raw == null ? "" : ` (raw="${e.raw}")`}`);
20818
+ return `Invalid environment variables (${errors.length}):
20819
+ ${lines.join("\n")}`;
20820
+ }
20821
+ /**
20822
+ * Creates a new validation error from one or more `StrictEnvValidationEntry` entries.
20823
+ *
20824
+ * @param errors - One or more structured validation errors.
20825
+ */
20826
+ constructor(errors) {
20827
+ const msg = _StrictEnvValidationError.format(errors);
20828
+ super(msg);
20829
+ this.name = "StrictEnvValidationError";
20830
+ this.errors = errors;
20831
+ this.keys = errors.map((e) => e.key);
20832
+ }
20833
+ };
20834
+ exports2.StrictEnvValidationError = StrictEnvValidationError;
20835
+ exports2.StrictEnvType = {
20836
+ /** Spec for a string value (returned as-is unless `trim: true` is set in options). */
20837
+ String: { type: "string" },
20838
+ /**
20839
+ * Spec for a finite numeric value (`Number()` parsing; rejects `NaN` and `Infinity`).
20840
+ */
20841
+ Number: { type: "number" },
20842
+ /** Spec for a boolean value (`1`/`true`/`yes`/`on` → `true`; other non-empty values → `false`). */
20843
+ Boolean: { type: "boolean" },
20844
+ /**
20845
+ * Returns a spec that restricts the value to one of the given choices.
20846
+ *
20847
+ * @param choices - Allowed string literals.
20848
+ * @returns Enum spec for use with `resolve` or `resolveAll`.
20849
+ */
20850
+ Enum: (choices) => ({ type: "enum", choices })
20851
+ };
20852
+ var defaultTrimForSpec = (spec) => spec.type !== "string";
20853
+ var normalizeEnvRaw = (raw, trim) => {
20854
+ if (raw == null) {
20855
+ return void 0;
20856
+ }
20857
+ if (!trim) {
20858
+ return raw;
20859
+ }
20860
+ return raw.trim();
20861
+ };
20862
+ var resolveSchemaEntry = (entry) => ({
20863
+ spec: Array.isArray(entry) ? entry[0] : entry,
20864
+ options: Array.isArray(entry) ? entry[1] : void 0
20865
+ });
20866
+ var parseEnvValue = (key, spec, raw, defaultValue, options) => {
20867
+ const trim = options?.trim ?? defaultTrimForSpec(spec);
20868
+ const normalizedRaw = normalizeEnvRaw(raw, trim);
20869
+ const hasDefault = defaultValue !== void 0;
20870
+ if (normalizedRaw == null || normalizedRaw === "") {
20871
+ if (hasDefault) {
20872
+ return { ok: true, value: defaultValue };
20873
+ }
20874
+ return {
20875
+ ok: false,
20876
+ error: { key, message: `Missing required environment variable: ${key}`, raw, kind: "missing" }
20877
+ };
20878
+ }
20879
+ switch (spec.type) {
20880
+ case "number": {
20881
+ const n = parseNumber(normalizedRaw);
20882
+ if (n === void 0) {
20883
+ return {
20884
+ ok: false,
20885
+ error: { key, message: `Env ${key}: expected number, got "${raw}"`, raw, kind: "invalid_number" }
20886
+ };
20887
+ }
20888
+ return { ok: true, value: n };
20889
+ }
20890
+ case "boolean":
20891
+ return { ok: true, value: parseBooleanEnvValue(normalizedRaw) };
20892
+ case "enum":
20893
+ if (!spec.choices.includes(normalizedRaw)) {
20894
+ return {
20895
+ ok: false,
20896
+ error: {
20897
+ key,
20898
+ message: `Env ${key}: must be one of [${spec.choices.join(", ")}]`,
20899
+ raw,
20900
+ kind: "invalid_enum"
20901
+ }
20902
+ };
20903
+ }
20904
+ return { ok: true, value: normalizedRaw };
20905
+ default:
20906
+ return { ok: true, value: normalizedRaw };
20907
+ }
20908
+ };
20909
+ var resolve = (key, spec = exports2.StrictEnvType.String, options) => {
20910
+ const result = parseEnvValue(key, spec, process.env[key], options?.default, options);
20911
+ if (!result.ok) {
20912
+ throw new StrictEnvValidationError([result.error]);
20913
+ }
20914
+ return result.value;
20915
+ };
20916
+ var resolveAll = (schema) => {
20917
+ const envs = {};
20918
+ const errors = [];
20919
+ for (const key of Object.keys(schema)) {
20920
+ const { spec, options } = resolveSchemaEntry(schema[key]);
20921
+ const result = parseEnvValue(key, spec, process.env[key], options?.default, options);
20922
+ if (!result.ok) {
20923
+ errors.push(result.error);
20924
+ continue;
20925
+ }
20926
+ envs[key] = result.value;
20927
+ }
20928
+ if (errors.length > 0)
20929
+ throw new StrictEnvValidationError(errors);
20930
+ return envs;
20931
+ };
20932
+ exports2.StrictEnvResolver = {
20933
+ /** Reads and parses a single environment variable. See {@link resolve}. */
20934
+ resolve,
20935
+ /** Reads and parses multiple environment variables in one pass. See {@link resolveAll}. */
20936
+ resolveAll
20937
+ };
20938
+ }
20939
+ });
20940
+
20941
+ // node_modules/aws-lambda-secret-fetcher/lib/index.js
20942
+ var require_lib4 = __commonJS({
20701
20943
  "node_modules/aws-lambda-secret-fetcher/lib/index.js"(exports2) {
20702
20944
  "use strict";
20703
20945
  Object.defineProperty(exports2, "__esModule", { value: true });
20704
20946
  exports2.secretFetcher = void 0;
20705
20947
  var fetch_retrier_1 = require_lib();
20948
+ var quiet_json_parser_1 = require_lib2();
20949
+ var strict_env_resolver_1 = require_lib3();
20706
20950
  var getSecretValue = async (name, options = {}) => {
20707
20951
  const { extensionHttpPort, timeoutMs = 2e3, retries = 3, baseBackoffMs = 300 } = options;
20708
20952
  const port = resolveExtensionHttpPort(extensionHttpPort);
20953
+ const sessionToken = resolveAwsSessionToken();
20709
20954
  const url = `http://localhost:${port}/secretsmanager/get?secretId=${encodeURIComponent(name)}`;
20710
20955
  const requestOptions = {
20711
20956
  headers: {
20712
- "X-Aws-Parameters-Secrets-Token": process.env.AWS_SESSION_TOKEN ?? ""
20957
+ "X-Aws-Parameters-Secrets-Token": sessionToken
20713
20958
  },
20714
20959
  retries,
20715
20960
  timeoutMs,
20716
20961
  baseBackoffMs,
20717
20962
  shouldRetry: (res, body) => {
20718
- if ([429, 500, 502, 503, 504].includes(res.status))
20963
+ if ((0, fetch_retrier_1.defaultShouldRetry)(res, body)) {
20719
20964
  return true;
20720
- if (res.status === 400 && /not\s+ready.*traffic/i.test(body))
20965
+ }
20966
+ if (res.status === 400 && /not\s+ready.*traffic/i.test(body)) {
20721
20967
  return true;
20968
+ }
20722
20969
  return false;
20723
20970
  }
20724
20971
  };
@@ -20728,21 +20975,34 @@ var require_lib2 = __commonJS({
20728
20975
  throw new Error("Invalid secret response format");
20729
20976
  }
20730
20977
  const data = raw;
20731
- const secretString = data.SecretString;
20732
- if (looksLikeJson(secretString)) {
20733
- return JSON.parse(secretString);
20978
+ return (0, quiet_json_parser_1.quietParse)(data.SecretString, data.SecretString);
20979
+ };
20980
+ var AWS_SESSION_TOKEN_GUIDANCE = "AWS_SESSION_TOKEN is not set. This library only works inside an AWS Lambda execution environment where the runtime provides AWS_SESSION_TOKEN for the Parameters and Secrets Extension. Attach the extension layer and run your code as a Lambda function handler.";
20981
+ var MIN_TCP_PORT = 1;
20982
+ var MAX_TCP_PORT = 65535;
20983
+ var resolveAwsSessionToken = () => {
20984
+ try {
20985
+ return strict_env_resolver_1.StrictEnvResolver.resolve("AWS_SESSION_TOKEN", strict_env_resolver_1.StrictEnvType.String, { trim: true });
20986
+ } catch (e) {
20987
+ if (e instanceof strict_env_resolver_1.StrictEnvValidationError && e.errors.length === 1 && e.errors[0]?.key === "AWS_SESSION_TOKEN" && e.errors[0]?.kind === "missing") {
20988
+ throw new Error(AWS_SESSION_TOKEN_GUIDANCE);
20989
+ }
20990
+ throw e;
20734
20991
  }
20735
- return secretString;
20736
20992
  };
20737
20993
  var resolveExtensionHttpPort = (overridePort) => {
20738
- const fromOverride = overridePort === void 0 ? void 0 : String(overridePort);
20739
- const fromEnv = process.env.PARAMETERS_SECRETS_EXTENSION_HTTP_PORT;
20740
- const candidate = (fromOverride ?? fromEnv ?? "2773").trim();
20994
+ const port = overridePort === void 0 ? strict_env_resolver_1.StrictEnvResolver.resolve("PARAMETERS_SECRETS_EXTENSION_HTTP_PORT", strict_env_resolver_1.StrictEnvType.Number, { default: 2773 }) : parseExtensionHttpPortOverride(overridePort);
20995
+ return assertValidTcpPort(port);
20996
+ };
20997
+ var parseExtensionHttpPortOverride = (overridePort) => {
20998
+ const candidate = String(overridePort).trim();
20741
20999
  if (!/^\d+$/.test(candidate)) {
20742
21000
  throw new Error("Invalid extension HTTP port: must be a number");
20743
21001
  }
20744
- const port = Number.parseInt(candidate, 10);
20745
- if (port < 1 || port > 65535) {
21002
+ return Number.parseInt(candidate, 10);
21003
+ };
21004
+ var assertValidTcpPort = (port) => {
21005
+ if (port < MIN_TCP_PORT || port > MAX_TCP_PORT) {
20746
21006
  throw new Error("Invalid extension HTTP port: must be between 1 and 65535");
20747
21007
  }
20748
21008
  return String(port);
@@ -20753,19 +21013,217 @@ var require_lib2 = __commonJS({
20753
21013
  const v = value;
20754
21014
  return typeof v.SecretString === "string" && typeof v.Name === "string" && typeof v.ARN === "string" && (v.VersionId === void 0 || typeof v.VersionId === "string");
20755
21015
  };
20756
- var looksLikeJson = (str) => {
20757
- return typeof str === "string" && str.trim().startsWith("{");
20758
- };
20759
21016
  exports2.secretFetcher = {
20760
21017
  getSecretValue
20761
21018
  };
20762
21019
  }
20763
21020
  });
20764
21021
 
21022
+ // node_modules/strict-env-resolver/lib/index.js
21023
+ var require_lib5 = __commonJS({
21024
+ "node_modules/strict-env-resolver/lib/index.js"(exports2) {
21025
+ "use strict";
21026
+ Object.defineProperty(exports2, "__esModule", { value: true });
21027
+ exports2.StrictEnvResolver = exports2.StrictEnvType = exports2.StrictEnvValidationError = exports2.StrictEnvError = void 0;
21028
+ var TRUE_BOOLEAN_PATTERN = /^(1|true|yes|on)$/i;
21029
+ var parseNumber = (raw) => {
21030
+ const n = Number(raw);
21031
+ if (!Number.isFinite(n)) {
21032
+ return void 0;
21033
+ }
21034
+ return n;
21035
+ };
21036
+ var parseBooleanEnvValue = (normalizedRaw) => TRUE_BOOLEAN_PATTERN.test(normalizedRaw);
21037
+ var StrictEnvError = class extends Error {
21038
+ /**
21039
+ * @param message - Error message.
21040
+ */
21041
+ constructor(message) {
21042
+ super(message);
21043
+ this.name = "StrictEnvError";
21044
+ }
21045
+ };
21046
+ exports2.StrictEnvError = StrictEnvError;
21047
+ var StrictEnvValidationError = class _StrictEnvValidationError extends StrictEnvError {
21048
+ /**
21049
+ * Formats validation errors into a human-readable error message.
21050
+ *
21051
+ * @template K - Environment variable key type.
21052
+ * @param errors - Validation error entries to format.
21053
+ * @returns Multi-line summary listing each key and message.
21054
+ */
21055
+ static format(errors) {
21056
+ const lines = errors.map((e) => `- ${e.key}: ${e.message}${e.raw == null ? "" : ` (raw="${e.raw}")`}`);
21057
+ return `Invalid environment variables (${errors.length}):
21058
+ ${lines.join("\n")}`;
21059
+ }
21060
+ /**
21061
+ * Creates a new validation error from one or more `StrictEnvValidationEntry` entries.
21062
+ *
21063
+ * @param errors - One or more structured validation errors.
21064
+ */
21065
+ constructor(errors) {
21066
+ const msg = _StrictEnvValidationError.format(errors);
21067
+ super(msg);
21068
+ this.name = "StrictEnvValidationError";
21069
+ this.errors = errors;
21070
+ this.keys = errors.map((e) => e.key);
21071
+ }
21072
+ };
21073
+ exports2.StrictEnvValidationError = StrictEnvValidationError;
21074
+ var createNumberSpec = (constraints) => ({
21075
+ type: "number",
21076
+ ...constraints?.min !== void 0 ? { min: constraints.min } : {},
21077
+ ...constraints?.max !== void 0 ? { max: constraints.max } : {},
21078
+ ...constraints?.integer !== void 0 ? { integer: constraints.integer } : {}
21079
+ });
21080
+ var NumberSpec = Object.assign((constraints) => createNumberSpec(constraints), { type: "number" });
21081
+ exports2.StrictEnvType = {
21082
+ /** Spec for a string value (returned as-is unless `trim: true` is set in options). */
21083
+ String: { type: "string" },
21084
+ /**
21085
+ * Spec for a finite numeric value (`Number()` parsing; rejects `NaN` and `Infinity`).
21086
+ * Use as `StrictEnvType.Number`, or call as `StrictEnvType.Number({ min, max, integer })`.
21087
+ */
21088
+ Number: NumberSpec,
21089
+ /**
21090
+ * Spec for a positive integer (`>= 1`). Sugar for `Number({ min: 1, integer: true })`.
21091
+ */
21092
+ PositiveInt: createNumberSpec({ min: 1, integer: true }),
21093
+ /**
21094
+ * Spec for a negative integer (`<= -1`). Sugar for `Number({ max: -1, integer: true })`.
21095
+ */
21096
+ NegativeInt: createNumberSpec({ max: -1, integer: true }),
21097
+ /** Spec for a boolean value (`1`/`true`/`yes`/`on` → `true`; other non-empty values → `false`). */
21098
+ Boolean: { type: "boolean" },
21099
+ /**
21100
+ * Returns a spec that restricts the value to one of the given choices.
21101
+ *
21102
+ * @param choices - Allowed string literals.
21103
+ * @returns Enum spec for use with `resolve` or `resolveAll`.
21104
+ */
21105
+ Enum: (choices) => ({ type: "enum", choices })
21106
+ };
21107
+ var defaultTrimForSpec = (spec) => spec.type !== "string";
21108
+ var normalizeEnvRaw = (raw, trim) => {
21109
+ if (raw == null) {
21110
+ return void 0;
21111
+ }
21112
+ if (!trim) {
21113
+ return raw;
21114
+ }
21115
+ return raw.trim();
21116
+ };
21117
+ var validateNumberConstraints = (key, raw, n, constraints) => {
21118
+ if (constraints.integer === true && !Number.isInteger(n)) {
21119
+ return { key, message: `Env ${key}: expected integer, got "${raw}"`, raw, kind: "invalid_number" };
21120
+ }
21121
+ if (constraints.min !== void 0 && n < constraints.min) {
21122
+ return {
21123
+ key,
21124
+ message: `Env ${key}: must be >= ${constraints.min}, got ${n}`,
21125
+ raw,
21126
+ kind: "invalid_number"
21127
+ };
21128
+ }
21129
+ if (constraints.max !== void 0 && n > constraints.max) {
21130
+ return {
21131
+ key,
21132
+ message: `Env ${key}: must be <= ${constraints.max}, got ${n}`,
21133
+ raw,
21134
+ kind: "invalid_number"
21135
+ };
21136
+ }
21137
+ return void 0;
21138
+ };
21139
+ var resolveSchemaEntry = (entry) => ({
21140
+ spec: Array.isArray(entry) ? entry[0] : entry,
21141
+ options: Array.isArray(entry) ? entry[1] : void 0
21142
+ });
21143
+ var parseEnvValue = (key, spec, raw, defaultValue, options) => {
21144
+ const trim = options?.trim ?? defaultTrimForSpec(spec);
21145
+ const normalizedRaw = normalizeEnvRaw(raw, trim);
21146
+ const hasDefault = defaultValue !== void 0;
21147
+ if (normalizedRaw == null || normalizedRaw === "") {
21148
+ if (hasDefault) {
21149
+ return { ok: true, value: defaultValue };
21150
+ }
21151
+ return {
21152
+ ok: false,
21153
+ error: { key, message: `Missing required environment variable: ${key}`, raw, kind: "missing" }
21154
+ };
21155
+ }
21156
+ switch (spec.type) {
21157
+ case "number": {
21158
+ const n = parseNumber(normalizedRaw);
21159
+ if (n === void 0) {
21160
+ return {
21161
+ ok: false,
21162
+ error: { key, message: `Env ${key}: expected number, got "${raw}"`, raw, kind: "invalid_number" }
21163
+ };
21164
+ }
21165
+ const constraintError = validateNumberConstraints(key, raw, n, spec);
21166
+ if (constraintError !== void 0) {
21167
+ return { ok: false, error: constraintError };
21168
+ }
21169
+ return { ok: true, value: n };
21170
+ }
21171
+ case "boolean":
21172
+ return { ok: true, value: parseBooleanEnvValue(normalizedRaw) };
21173
+ case "enum":
21174
+ if (!spec.choices.includes(normalizedRaw)) {
21175
+ return {
21176
+ ok: false,
21177
+ error: {
21178
+ key,
21179
+ message: `Env ${key}: must be one of [${spec.choices.join(", ")}]`,
21180
+ raw,
21181
+ kind: "invalid_enum"
21182
+ }
21183
+ };
21184
+ }
21185
+ return { ok: true, value: normalizedRaw };
21186
+ default:
21187
+ return { ok: true, value: normalizedRaw };
21188
+ }
21189
+ };
21190
+ var resolve = (key, spec = exports2.StrictEnvType.String, options) => {
21191
+ const result = parseEnvValue(key, spec, process.env[key], options?.default, options);
21192
+ if (!result.ok) {
21193
+ throw new StrictEnvValidationError([result.error]);
21194
+ }
21195
+ return result.value;
21196
+ };
21197
+ var resolveAll = (schema) => {
21198
+ const envs = {};
21199
+ const errors = [];
21200
+ for (const key of Object.keys(schema)) {
21201
+ const { spec, options } = resolveSchemaEntry(schema[key]);
21202
+ const result = parseEnvValue(key, spec, process.env[key], options?.default, options);
21203
+ if (!result.ok) {
21204
+ errors.push(result.error);
21205
+ continue;
21206
+ }
21207
+ envs[key] = result.value;
21208
+ }
21209
+ if (errors.length > 0)
21210
+ throw new StrictEnvValidationError(errors);
21211
+ return envs;
21212
+ };
21213
+ exports2.StrictEnvResolver = {
21214
+ /** Reads and parses a single environment variable. See {@link resolve}. */
21215
+ resolve,
21216
+ /** Reads and parses multiple environment variables in one pass. See {@link resolveAll}. */
21217
+ resolveAll
21218
+ };
21219
+ }
21220
+ });
21221
+
20765
21222
  // src/funcs/auto-start-prevent.lambda.ts
20766
21223
  var auto_start_prevent_lambda_exports = {};
20767
21224
  __export(auto_start_prevent_lambda_exports, {
20768
- handler: () => handler
21225
+ handler: () => handler,
21226
+ processAutoStartPrevent: () => processAutoStartPrevent
20769
21227
  });
20770
21228
  module.exports = __toCommonJS(auto_start_prevent_lambda_exports);
20771
21229
 
@@ -24286,36 +24744,10 @@ var DEFAULT_CONFIG = {
24286
24744
  // src/funcs/auto-start-prevent.lambda.ts
24287
24745
  var import_client_rds = require("@aws-sdk/client-rds");
24288
24746
  var import_web_api = __toESM(require_dist5());
24289
- var import_aws_lambda_secret_fetcher = __toESM(require_lib2());
24290
- var isRawEvent = (input) => typeof input === "object" && input != null && "detail" in input && "detail-type" in input;
24291
- var paramsFromEnv = () => {
24292
- const tagKey = process.env.TAG_KEY;
24293
- const tagValuesJson = process.env.TAG_VALUES;
24294
- if (!tagKey || !tagValuesJson) {
24295
- throw new Error("missing environment variables TAG_KEY or TAG_VALUES.");
24296
- }
24297
- let tagValues;
24298
- try {
24299
- tagValues = JSON.parse(tagValuesJson);
24300
- } catch {
24301
- throw new Error("TAG_VALUES must be a JSON array of strings.");
24302
- }
24303
- if (!Array.isArray(tagValues)) {
24304
- throw new Error("TAG_VALUES must be a JSON array of strings.");
24305
- }
24306
- return { tagKey, tagValues };
24307
- };
24308
- var normalizeInput = (input) => {
24309
- if (isRawEvent(input)) {
24310
- return { event: input, params: paramsFromEnv() };
24311
- }
24312
- const candidate = input;
24313
- if (typeof candidate === "object" && candidate != null && candidate.event != null && candidate.params != null) {
24314
- return candidate;
24315
- }
24316
- throw new Error("Invalid input: expected RDS event or { event, params }.");
24317
- };
24318
- var rdsClient = new import_client_rds.RDSClient({});
24747
+ var import_aws_lambda_secret_fetcher = __toESM(require_lib4());
24748
+ var import_strict_env_resolver = __toESM(require_lib5());
24749
+
24750
+ // src/funcs/auto-start-prevent.predicates.ts
24319
24751
  var TRANSITIONAL_STATUSES = /* @__PURE__ */ new Set([
24320
24752
  "starting",
24321
24753
  "configuring-enhanced-monitoring",
@@ -24323,6 +24755,31 @@ var TRANSITIONAL_STATUSES = /* @__PURE__ */ new Set([
24323
24755
  "modifying",
24324
24756
  "stopping"
24325
24757
  ]);
24758
+ var isTransitionalStatus = (status) => TRANSITIONAL_STATUSES.has(status);
24759
+ var isSlackSecret = (value) => {
24760
+ if (typeof value !== "object" || value == null) {
24761
+ return false;
24762
+ }
24763
+ if (!("token" in value) || !("channel" in value)) {
24764
+ return false;
24765
+ }
24766
+ return typeof value.token === "string" && value.token.length > 0 && typeof value.channel === "string" && value.channel.length > 0;
24767
+ };
24768
+ var isAutoStartPreventInput = (input) => {
24769
+ if (typeof input !== "object" || input == null) {
24770
+ return false;
24771
+ }
24772
+ if (!("event" in input) || !("params" in input)) {
24773
+ return false;
24774
+ }
24775
+ return input.event != null && input.params != null;
24776
+ };
24777
+ var normalizeInput = (input) => {
24778
+ if (isAutoStartPreventInput(input)) {
24779
+ return input;
24780
+ }
24781
+ throw new Error("Invalid input: expected { event, params }.");
24782
+ };
24326
24783
  var matchTag = (params, tags) => {
24327
24784
  if (!tags || tags.length === 0) {
24328
24785
  return false;
@@ -24333,29 +24790,175 @@ var matchTag = (params, tags) => {
24333
24790
  }
24334
24791
  return params.tagValues.includes(value);
24335
24792
  };
24336
- var handler = withDurableExecution(
24337
- async (input, context) => {
24338
- const { event, params } = normalizeInput(input);
24339
- const { detail, "detail-type": detailType } = event;
24340
- const slackSecretName = process.env.SLACK_SECRET_NAME;
24341
- if (!slackSecretName) {
24342
- throw new Error("missing environment variable SLACK_SECRET_NAME.");
24343
- }
24344
- const slackSecretValue = await context.step("fetch-slack-secret", async () => {
24345
- return import_aws_lambda_secret_fetcher.secretFetcher.getSecretValue(slackSecretName);
24346
- });
24347
- if (!slackSecretValue?.token || !slackSecretValue?.channel) {
24348
- throw new Error("Slack secret must contain token and channel.");
24793
+ var isDbInstanceAutoStart = (detailType, detail) => detailType === "RDS DB Instance Event" && detail.SourceType === "DB_INSTANCE" && detail.EventID === "RDS-EVENT-0154";
24794
+ var isDbClusterAutoStart = (detailType, detail) => detailType === "RDS DB Cluster Event" && detail.SourceType === "CLUSTER" && detail.EventID === "RDS-EVENT-0153";
24795
+ var waitStrategyUntilStable = (state) => {
24796
+ if (isTransitionalStatus(state.status)) {
24797
+ return { shouldContinue: true, delay: { minutes: 5 } };
24798
+ }
24799
+ return { shouldContinue: false };
24800
+ };
24801
+ var waitStrategyUntilStopped = (state) => {
24802
+ if (state.status === "stopped") {
24803
+ return { shouldContinue: false };
24804
+ }
24805
+ if (isTransitionalStatus(state.status)) {
24806
+ return { shouldContinue: true, delay: { minutes: 5 } };
24807
+ }
24808
+ throw new Error(`Unexpected status while waiting for stop: ${state.status}`);
24809
+ };
24810
+ var decideAfterTagMatch = (status) => {
24811
+ if (status === "available") {
24812
+ return { kind: "stop" };
24813
+ }
24814
+ if (status === "stopped") {
24815
+ return {
24816
+ kind: "no-op",
24817
+ result: {
24818
+ action: "no-op",
24819
+ reason: "already stopped",
24820
+ status
24821
+ }
24822
+ };
24823
+ }
24824
+ return {
24825
+ kind: "error",
24826
+ message: `DB status is not stopped after processing: ${status}`
24827
+ };
24828
+ };
24829
+ var tagMismatchNoOp = (status) => ({
24830
+ action: "no-op",
24831
+ reason: "tag not matched or not found",
24832
+ status
24833
+ });
24834
+ var parseRdsSourceArn = (sourceArn) => {
24835
+ const parts = sourceArn.split(":");
24836
+ return {
24837
+ region: parts[3] ?? "",
24838
+ account: parts[4] ?? ""
24839
+ };
24840
+ };
24841
+ var buildSlackStopNotification = (args) => ({
24842
+ channel: args.channel,
24843
+ attachments: [
24844
+ {
24845
+ color: "#36a64f",
24846
+ pretext: `\u{1F634} Successfully stopped the automatically running RDS ${args.sourceType} ${args.sourceIdentifier}.`,
24847
+ fields: [
24848
+ {
24849
+ title: "Account",
24850
+ value: args.account,
24851
+ short: true
24852
+ },
24853
+ {
24854
+ title: "Region",
24855
+ value: args.region,
24856
+ short: true
24857
+ },
24858
+ {
24859
+ title: "Type",
24860
+ value: args.sourceType,
24861
+ short: true
24862
+ },
24863
+ {
24864
+ title: "Identifier",
24865
+ value: args.sourceIdentifier,
24866
+ short: true
24867
+ }
24868
+ ]
24349
24869
  }
24350
- const isInstance = detailType === "RDS DB Instance Event" && detail.SourceType === "DB_INSTANCE" && detail.EventID === "RDS-EVENT-0154";
24351
- const isCluster = detailType === "RDS DB Cluster Event" && detail.SourceType === "CLUSTER" && detail.EventID === "RDS-EVENT-0153";
24352
- if (!isInstance && !isCluster) {
24353
- throw new Error(
24354
- `Unsupported event: detail-type=${detailType}, SourceType=${detail.SourceType}, EventID=${detail.EventID}`
24870
+ ]
24871
+ });
24872
+ var buildStoppedResult = (args) => ({
24873
+ action: "stopped",
24874
+ finalStatus: args.finalStatus,
24875
+ account: args.account,
24876
+ region: args.region,
24877
+ identifier: args.identifier
24878
+ });
24879
+
24880
+ // src/funcs/auto-start-prevent.lambda.ts
24881
+ var rdsClient = new import_client_rds.RDSClient({});
24882
+ var processAutoStartPrevent = async (input, context) => {
24883
+ const { event, params } = normalizeInput(input);
24884
+ const { detail, "detail-type": detailType } = event;
24885
+ const slackSecretName = import_strict_env_resolver.StrictEnvResolver.resolve("SLACK_SECRET_NAME", import_strict_env_resolver.StrictEnvType.String, {
24886
+ trim: true
24887
+ });
24888
+ const slackSecretValue = await context.step("fetch-slack-secret", async () => {
24889
+ return import_aws_lambda_secret_fetcher.secretFetcher.getSecretValue(slackSecretName);
24890
+ });
24891
+ if (!isSlackSecret(slackSecretValue)) {
24892
+ throw new Error("Slack secret must be JSON with non-empty token and channel.");
24893
+ }
24894
+ const isInstance = isDbInstanceAutoStart(detailType, detail);
24895
+ const isCluster = isDbClusterAutoStart(detailType, detail);
24896
+ if (!isInstance && !isCluster) {
24897
+ throw new Error(
24898
+ `Unsupported event: detail-type=${detailType}, SourceType=${detail.SourceType}, EventID=${detail.EventID}`
24899
+ );
24900
+ }
24901
+ await context.wait({ minutes: 1 });
24902
+ const firstDescribe = await context.waitForCondition(
24903
+ async (_state, _ctx) => {
24904
+ if (isInstance) {
24905
+ const res2 = await rdsClient.send(
24906
+ new import_client_rds.DescribeDBInstancesCommand({
24907
+ DBInstanceIdentifier: detail.SourceIdentifier
24908
+ })
24909
+ );
24910
+ const db = res2.DBInstances?.[0];
24911
+ return {
24912
+ status: db?.DBInstanceStatus ?? "unknown",
24913
+ identifier: db?.DBInstanceIdentifier ?? detail.SourceIdentifier,
24914
+ tags: db?.TagList ?? []
24915
+ };
24916
+ }
24917
+ const res = await rdsClient.send(
24918
+ new import_client_rds.DescribeDBClustersCommand({
24919
+ DBClusterIdentifier: detail.SourceIdentifier
24920
+ })
24355
24921
  );
24922
+ const cluster = res.DBClusters?.[0];
24923
+ return {
24924
+ status: cluster?.Status ?? "unknown",
24925
+ identifier: cluster?.DBClusterIdentifier ?? detail.SourceIdentifier,
24926
+ tags: cluster?.TagList ?? []
24927
+ };
24928
+ },
24929
+ {
24930
+ initialState: {
24931
+ status: "starting",
24932
+ identifier: detail.SourceIdentifier
24933
+ },
24934
+ waitStrategy: waitStrategyUntilStable
24935
+ }
24936
+ );
24937
+ if (!matchTag(params, firstDescribe.tags)) {
24938
+ return tagMismatchNoOp(firstDescribe.status);
24939
+ }
24940
+ let didStop = false;
24941
+ let finalStatus = firstDescribe.status;
24942
+ const afterTagMatch = decideAfterTagMatch(firstDescribe.status);
24943
+ if (afterTagMatch.kind === "stop") {
24944
+ if (isInstance) {
24945
+ await context.step("stop-db-instance", async () => {
24946
+ await rdsClient.send(
24947
+ new import_client_rds.StopDBInstanceCommand({
24948
+ DBInstanceIdentifier: detail.SourceIdentifier
24949
+ })
24950
+ );
24951
+ });
24952
+ } else {
24953
+ await context.step("stop-db-cluster", async () => {
24954
+ await rdsClient.send(
24955
+ new import_client_rds.StopDBClusterCommand({
24956
+ DBClusterIdentifier: detail.SourceIdentifier
24957
+ })
24958
+ );
24959
+ });
24356
24960
  }
24357
- await context.wait({ minutes: 1 });
24358
- const firstDescribe = await context.waitForCondition(
24961
+ const stopped = await context.waitForCondition(
24359
24962
  async (_state, _ctx) => {
24360
24963
  if (isInstance) {
24361
24964
  const res2 = await rdsClient.send(
@@ -24366,8 +24969,7 @@ var handler = withDurableExecution(
24366
24969
  const db = res2.DBInstances?.[0];
24367
24970
  return {
24368
24971
  status: db?.DBInstanceStatus ?? "unknown",
24369
- identifier: db?.DBInstanceIdentifier ?? detail.SourceIdentifier,
24370
- tags: db?.TagList ?? []
24972
+ identifier: db?.DBInstanceIdentifier ?? detail.SourceIdentifier
24371
24973
  };
24372
24974
  }
24373
24975
  const res = await rdsClient.send(
@@ -24378,157 +24980,56 @@ var handler = withDurableExecution(
24378
24980
  const cluster = res.DBClusters?.[0];
24379
24981
  return {
24380
24982
  status: cluster?.Status ?? "unknown",
24381
- identifier: cluster?.DBClusterIdentifier ?? detail.SourceIdentifier,
24382
- tags: cluster?.TagList ?? []
24983
+ identifier: cluster?.DBClusterIdentifier ?? detail.SourceIdentifier
24383
24984
  };
24384
24985
  },
24385
24986
  {
24386
24987
  initialState: {
24387
- status: "starting",
24388
- identifier: detail.SourceIdentifier
24988
+ status: firstDescribe.status,
24989
+ identifier: firstDescribe.identifier
24389
24990
  },
24390
- waitStrategy: (state) => {
24391
- if (TRANSITIONAL_STATUSES.has(state.status)) {
24392
- return { shouldContinue: true, delay: { minutes: 5 } };
24393
- }
24394
- return { shouldContinue: false };
24395
- }
24991
+ waitStrategy: waitStrategyUntilStopped
24396
24992
  }
24397
24993
  );
24398
- if (!matchTag(params, firstDescribe.tags)) {
24399
- return {
24400
- action: "no-op",
24401
- reason: "tag not matched or not found",
24402
- status: firstDescribe.status
24403
- };
24404
- }
24405
- let didStop = false;
24406
- let finalStatus = firstDescribe.status;
24407
- if (firstDescribe.status === "available") {
24408
- if (isInstance) {
24409
- await context.step("stop-db-instance", async () => {
24410
- await rdsClient.send(
24411
- new import_client_rds.StopDBInstanceCommand({
24412
- DBInstanceIdentifier: detail.SourceIdentifier
24413
- })
24414
- );
24415
- });
24416
- } else {
24417
- await context.step("stop-db-cluster", async () => {
24418
- await rdsClient.send(
24419
- new import_client_rds.StopDBClusterCommand({
24420
- DBClusterIdentifier: detail.SourceIdentifier
24421
- })
24422
- );
24423
- });
24424
- }
24425
- const stopped = await context.waitForCondition(
24426
- async (_state, _ctx) => {
24427
- if (isInstance) {
24428
- const res2 = await rdsClient.send(
24429
- new import_client_rds.DescribeDBInstancesCommand({
24430
- DBInstanceIdentifier: detail.SourceIdentifier
24431
- })
24432
- );
24433
- const db = res2.DBInstances?.[0];
24434
- return {
24435
- status: db?.DBInstanceStatus ?? "unknown",
24436
- identifier: db?.DBInstanceIdentifier ?? detail.SourceIdentifier
24437
- };
24438
- }
24439
- const res = await rdsClient.send(
24440
- new import_client_rds.DescribeDBClustersCommand({
24441
- DBClusterIdentifier: detail.SourceIdentifier
24442
- })
24443
- );
24444
- const cluster = res.DBClusters?.[0];
24445
- return {
24446
- status: cluster?.Status ?? "unknown",
24447
- identifier: cluster?.DBClusterIdentifier ?? detail.SourceIdentifier
24448
- };
24449
- },
24450
- {
24451
- initialState: {
24452
- status: firstDescribe.status,
24453
- identifier: firstDescribe.identifier
24454
- },
24455
- waitStrategy: (state) => {
24456
- if (state.status === "stopped") {
24457
- return { shouldContinue: false };
24458
- }
24459
- if (TRANSITIONAL_STATUSES.has(state.status)) {
24460
- return { shouldContinue: true, delay: { minutes: 5 } };
24461
- }
24462
- throw new Error(`Unexpected status while waiting for stop: ${state.status}`);
24463
- }
24464
- }
24465
- );
24466
- didStop = true;
24467
- finalStatus = stopped.status;
24468
- }
24469
- if (!didStop) {
24470
- if (finalStatus === "stopped") {
24471
- return {
24472
- action: "no-op",
24473
- reason: "already stopped",
24474
- status: finalStatus
24475
- };
24476
- }
24477
- throw new Error(`DB status is not stopped after processing: ${finalStatus}`);
24478
- }
24479
- if (finalStatus !== "stopped") {
24480
- throw new Error(`DB status is not stopped after processing: ${finalStatus}`);
24481
- }
24482
- const sourceArnParts = detail.SourceArn.split(":");
24483
- const region = sourceArnParts[3];
24484
- const account = sourceArnParts[4];
24485
- const client = new import_web_api.WebClient(slackSecretValue.token);
24486
- const channel = slackSecretValue.channel;
24487
- await context.step("post-slack-messages", async () => {
24488
- return client.chat.postMessage({
24489
- channel,
24490
- attachments: [
24491
- {
24492
- color: "#36a64f",
24493
- pretext: `\u{1F634} Successfully stopped the automatically running RDS ${detail.SourceType} ${detail.SourceIdentifier}.`,
24494
- fields: [
24495
- {
24496
- title: "Account",
24497
- value: account,
24498
- short: true
24499
- },
24500
- {
24501
- title: "Region",
24502
- value: region,
24503
- short: true
24504
- },
24505
- {
24506
- title: "Type",
24507
- value: detail.SourceType,
24508
- short: true
24509
- },
24510
- {
24511
- title: "Identifier",
24512
- value: detail.SourceIdentifier,
24513
- short: true
24514
- }
24515
- ]
24516
- }
24517
- ]
24518
- });
24519
- });
24520
- return {
24521
- action: "stopped",
24522
- finalStatus,
24523
- account,
24524
- region,
24525
- identifier: detail.SourceIdentifier
24526
- };
24527
- }
24528
- );
24994
+ didStop = true;
24995
+ finalStatus = stopped.status;
24996
+ }
24997
+ if (!didStop) {
24998
+ if (afterTagMatch.kind === "no-op") {
24999
+ return afterTagMatch.result;
25000
+ }
25001
+ if (afterTagMatch.kind === "error") {
25002
+ throw new Error(afterTagMatch.message);
25003
+ }
25004
+ }
25005
+ if (finalStatus !== "stopped") {
25006
+ throw new Error(`DB status is not stopped after processing: ${finalStatus}`);
25007
+ }
25008
+ const { region, account } = parseRdsSourceArn(detail.SourceArn);
25009
+ const client = new import_web_api.WebClient(slackSecretValue.token);
25010
+ await context.step("post-slack-messages", async () => {
25011
+ return client.chat.postMessage(
25012
+ buildSlackStopNotification({
25013
+ channel: slackSecretValue.channel,
25014
+ sourceType: detail.SourceType,
25015
+ sourceIdentifier: detail.SourceIdentifier,
25016
+ account,
25017
+ region
25018
+ })
25019
+ );
25020
+ });
25021
+ return buildStoppedResult({
25022
+ finalStatus,
25023
+ account,
25024
+ region,
25025
+ identifier: detail.SourceIdentifier
25026
+ });
25027
+ };
25028
+ var handler = withDurableExecution(processAutoStartPrevent);
24529
25029
  // Annotate the CommonJS export names for ESM import in node:
24530
25030
  0 && (module.exports = {
24531
- handler
25031
+ handler,
25032
+ processAutoStartPrevent
24532
25033
  });
24533
25034
  /*! Bundled license information:
24534
25035