cdk-local 0.29.1 → 0.31.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.
@@ -91,17 +91,6 @@ function appOptions() {
91
91
  * Context options.
92
92
  */
93
93
  const contextOptions = [new Option("-c, --context <key=value...>", "Set context values (can be specified multiple times)")];
94
- /**
95
- * `-i, --interactive` — present an arrow-key picker to choose the
96
- * target(s) for this command instead of typing a CDK path / logical ID.
97
- * Added to the four run commands (NOT `list`, which lists everything).
98
- * Requires a TTY; in a non-interactive shell the command errors with a
99
- * clear message. The required-target commands (`invoke` / `run-task` /
100
- * `start-service`) also auto-launch the picker when the target is
101
- * omitted in a TTY; `start-api` shows it only with the explicit flag
102
- * (a bare `start-api` keeps serving every discovered API).
103
- */
104
- const interactiveOption = new Option("-i, --interactive", "Pick the target(s) from an interactive list instead of passing them as arguments (requires a TTY)").default(false);
105
94
  const IAM_ROLE_ARN_REGEX = /^arn:[^:]+:iam::\d+:role\//;
106
95
  function parseAssumeRoleToken(raw, previous) {
107
96
  const acc = previous ?? { perLambda: {} };
@@ -2000,7 +1989,7 @@ function readApiCdkPath(logicalId, template) {
2000
1989
 
2001
1990
  //#endregion
2002
1991
  //#region src/local/target-lister.ts
2003
- function makeEntry(stackName, logicalId, cdkPath) {
1992
+ function makeEntry(stackName, logicalId, cdkPath, kind) {
2004
1993
  const entry = {
2005
1994
  logicalId,
2006
1995
  stackName,
@@ -2008,8 +1997,17 @@ function makeEntry(stackName, logicalId, cdkPath) {
2008
1997
  };
2009
1998
  const display = cdkPath ? cdkPath.replace(/\/Resource$/, "") : void 0;
2010
1999
  if (display) entry.displayPath = display;
2000
+ if (kind) entry.kind = kind;
2011
2001
  return entry;
2012
2002
  }
2003
+ /** Map a discovered route's `source` to the human-readable surface kind. */
2004
+ function apiKindLabel(source) {
2005
+ switch (source) {
2006
+ case "http-api": return "HTTP API v2";
2007
+ case "rest-v1": return "REST API v1";
2008
+ case "function-url": return "Function URL";
2009
+ }
2010
+ }
2013
2011
  function scanByType(stacks, type) {
2014
2012
  const entries = [];
2015
2013
  for (const stack of stacks) {
@@ -2038,22 +2036,22 @@ function scanByType(stacks, type) {
2038
2036
  */
2039
2037
  function listApiSurfaces(stacks) {
2040
2038
  const byKey = /* @__PURE__ */ new Map();
2041
- const add = (stackName, logicalId, cdkPath) => {
2039
+ const add = (stackName, logicalId, cdkPath, kind) => {
2042
2040
  const key = `${stackName}:${logicalId}`;
2043
- if (!byKey.has(key)) byKey.set(key, makeEntry(stackName, logicalId, cdkPath));
2041
+ if (!byKey.has(key)) byKey.set(key, makeEntry(stackName, logicalId, cdkPath, kind));
2044
2042
  };
2045
2043
  try {
2046
2044
  for (const route of discoverRoutes(stacks)) {
2047
2045
  if (!route.apiStackName) continue;
2048
2046
  const logicalId = route.source === "function-url" ? route.lambdaLogicalId : route.apiLogicalId;
2049
2047
  if (!logicalId) continue;
2050
- add(route.apiStackName, logicalId, route.apiCdkPath);
2048
+ add(route.apiStackName, logicalId, route.apiCdkPath, apiKindLabel(route.source));
2051
2049
  }
2052
2050
  } catch (err) {
2053
2051
  getLogger().warn(`Could not enumerate REST / HTTP / Function URL targets: ${err instanceof Error ? err.message : String(err)}`);
2054
2052
  }
2055
2053
  const { apis, errors } = discoverWebSocketApis(stacks);
2056
- for (const api of apis) add(api.apiStackName, api.apiLogicalId, api.apiCdkPath);
2054
+ for (const api of apis) add(api.apiStackName, api.apiLogicalId, api.apiCdkPath, "WebSocket");
2057
2055
  for (const e of errors) getLogger().warn(`Could not enumerate a WebSocket API target: ${e}`);
2058
2056
  return [...byKey.values()];
2059
2057
  }
@@ -2099,7 +2097,7 @@ function toOption(entry) {
2099
2097
  value,
2100
2098
  label: value
2101
2099
  };
2102
- if (entry.displayPath) option.hint = entry.qualifiedId;
2100
+ if (entry.kind) option.hint = entry.kind;
2103
2101
  return option;
2104
2102
  }
2105
2103
  /**
@@ -2123,19 +2121,25 @@ async function pickOneTarget(message, entries) {
2123
2121
  * The key hint is baked into the message because multi-select's
2124
2122
  * space-to-toggle is not discoverable — users expect enter to pick the
2125
2123
  * highlighted row and miss that nothing is selected yet.
2124
+ *
2125
+ * When `preselectAll` is true, every row starts selected (via
2126
+ * `@clack/prompts` `initialValues`) so a bare Enter confirms the whole
2127
+ * set — used by `start-api`, whose long-standing default is "serve every
2128
+ * discovered API". The user deselects rows to serve a subset.
2126
2129
  */
2127
- async function pickManyTargets(message, entries) {
2130
+ async function pickManyTargets(message, entries, options = {}) {
2131
+ const opts = entries.map(toOption);
2128
2132
  const chosen = await multiselect({
2129
2133
  message: `${message} (space to select, enter to confirm)`,
2130
- options: entries.map(toOption),
2131
- required: true
2134
+ options: opts,
2135
+ required: true,
2136
+ ...options.preselectAll && { initialValues: opts.map((o) => o.value) }
2132
2137
  });
2133
2138
  if (isCancel(chosen)) throw new TargetSelectionCancelledError();
2134
2139
  return chosen;
2135
2140
  }
2136
- function ensureCanPrompt(interactive, onMissing) {
2141
+ function ensureCanPrompt(onMissing) {
2137
2142
  if (isInteractive()) return;
2138
- if (interactive) throw new InteractiveTtyRequiredError("`-i/--interactive` requires an interactive terminal, but stdin/stdout is not a TTY.");
2139
2143
  throw onMissing();
2140
2144
  }
2141
2145
  function ensureHasCandidates(count, noun) {
@@ -2144,17 +2148,15 @@ function ensureHasCandidates(count, noun) {
2144
2148
  }
2145
2149
  /**
2146
2150
  * Resolve a single positional target, prompting interactively when the
2147
- * user passed `-i/--interactive` or omitted the target in a TTY.
2151
+ * target is omitted in a TTY.
2148
2152
  *
2149
- * - `provided` set and no `-i` → returned as-is (no prompt).
2150
- * - `-i` set → always prompt (any `provided` value is ignored).
2153
+ * - `provided` set → returned as-is (no prompt).
2151
2154
  * - omitted, TTY → prompt.
2152
2155
  * - omitted, no TTY → `onMissing()` (the command's required-arg error).
2153
2156
  */
2154
2157
  async function resolveSingleTarget(provided, params) {
2155
- if (provided && !params.interactive) return provided;
2156
- if (provided && params.interactive) getLogger().warn(`-i/--interactive ignores the provided target '${provided}' — pick one from the list instead.`);
2157
- ensureCanPrompt(params.interactive, params.onMissing);
2158
+ if (provided) return provided;
2159
+ ensureCanPrompt(params.onMissing);
2158
2160
  ensureHasCandidates(params.entries.length, params.noun);
2159
2161
  return pickOneTarget(params.message, params.entries);
2160
2162
  }
@@ -2164,9 +2166,8 @@ async function resolveSingleTarget(provided, params) {
2164
2166
  * rules as {@link resolveSingleTarget}.
2165
2167
  */
2166
2168
  async function resolveMultiTarget(provided, params) {
2167
- if (provided.length > 0 && !params.interactive) return provided;
2168
- if (provided.length > 0 && params.interactive) getLogger().warn(`-i/--interactive ignores the provided target(s) [${provided.join(", ")}] — pick from the list instead.`);
2169
- ensureCanPrompt(params.interactive, params.onMissing);
2169
+ if (provided.length > 0) return provided;
2170
+ ensureCanPrompt(params.onMissing);
2170
2171
  ensureHasCandidates(params.entries.length, params.noun);
2171
2172
  return pickManyTargets(params.message, params.entries);
2172
2173
  }
@@ -7303,11 +7304,10 @@ async function localInvokeCommand(target, options, extraStateProviders) {
7303
7304
  };
7304
7305
  const { stacks } = await synthesizer.synthesize(synthOpts);
7305
7306
  const lambda = resolveLambdaTarget(await resolveSingleTarget(target, {
7306
- interactive: options.interactive,
7307
7307
  entries: listTargets(stacks).lambdas,
7308
7308
  message: "Select a Lambda function to invoke",
7309
7309
  noun: "Lambda functions",
7310
- onMissing: () => new CdkLocalError(`${getEmbedConfig().cliName} invoke requires a <target> (a Lambda display path or logical ID). Run \`${getEmbedConfig().cliName} list\` to see them, or pass -i to pick interactively.`, "LOCAL_INVOKE_TARGET_REQUIRED")
7310
+ onMissing: () => new CdkLocalError(`${getEmbedConfig().cliName} invoke requires a <target> (a Lambda display path or logical ID). Run \`${getEmbedConfig().cliName} list\` to see them, or run it in a TTY to pick interactively.`, "LOCAL_INVOKE_TARGET_REQUIRED")
7311
7311
  }), stacks);
7312
7312
  const targetLabel = lambda.kind === "zip" ? lambda.runtime : "container image";
7313
7313
  logger.info(`Target: ${lambda.stack.stackName}/${lambda.logicalId} (${targetLabel})`);
@@ -7781,7 +7781,7 @@ function pickReferencedLogicalId(intrinsic) {
7781
7781
  }
7782
7782
  function createLocalInvokeCommand(opts = {}) {
7783
7783
  setEmbedConfig(opts.embedConfig);
7784
- const invoke = new Command("invoke").description("Run a Lambda function locally in a Docker container (RIE-backed). Target accepts a CDK display path (MyStack/MyApi/Handler) or stack-qualified logical ID (MyStack:MyApiHandler1234ABCD). Single-stack apps may omit the stack prefix. Omit <target> in an interactive terminal (or pass -i) to pick the Lambda from a list.").argument("[target]", "CDK display path or stack-qualified logical ID of the Lambda to invoke (omit to pick interactively in a TTY)").addOption(new Option("-e, --event <file>", "JSON event payload file (default: {})")).addOption(new Option("--event-stdin", "Read event JSON from stdin").default(false)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}})")).addOption(new Option("--no-pull", "Skip docker pull (use cached image) — no-op for IMAGE local-build path; `docker build` does not pull base layers by default")).addOption(new Option("--no-build", "Skip docker build on the IMAGE local-build path (use the previously-built tag). Requires the deterministic tag to already be in the local registry; errors with an actionable message when missing. No-op for ZIP Lambdas and the IMAGE ECR-pull path. Compatible with --no-pull.")).addOption(new Option("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(new Option("--container-host <host>", "Host to bind the RIE port to").default("127.0.0.1")).addOption(new Option("--assume-role [arn]", "Assume the Lambda's deployed execution role and forward STS-issued temp credentials to the container so the handler runs with the deployed function's narrow permissions. Three forms: (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) auto-resolves the function's execution role ARN from state (requires an active state source); (3) `--no-assume-role` explicitly opts out. Off by default — when omitted, the developer's shell credentials are forwarded unchanged (SAM-compatible default). STS failures degrade to a warn + dev-creds fallback.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers. Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name; pass an explicit value when CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).action(withErrorHandling(async (target, options) => {
7784
+ const invoke = new Command("invoke").description("Run a Lambda function locally in a Docker container (RIE-backed). Target accepts a CDK display path (MyStack/MyApi/Handler) or stack-qualified logical ID (MyStack:MyApiHandler1234ABCD). Single-stack apps may omit the stack prefix. Omit <target> in an interactive terminal to pick the Lambda from a list.").argument("[target]", "CDK display path or stack-qualified logical ID of the Lambda to invoke (omit to pick interactively in a TTY)").addOption(new Option("-e, --event <file>", "JSON event payload file (default: {})")).addOption(new Option("--event-stdin", "Read event JSON from stdin").default(false)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}})")).addOption(new Option("--no-pull", "Skip docker pull (use cached image) — no-op for IMAGE local-build path; `docker build` does not pull base layers by default")).addOption(new Option("--no-build", "Skip docker build on the IMAGE local-build path (use the previously-built tag). Requires the deterministic tag to already be in the local registry; errors with an actionable message when missing. No-op for ZIP Lambdas and the IMAGE ECR-pull path. Compatible with --no-pull.")).addOption(new Option("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(new Option("--container-host <host>", "Host to bind the RIE port to").default("127.0.0.1")).addOption(new Option("--assume-role [arn]", "Assume the Lambda's deployed execution role and forward STS-issued temp credentials to the container so the handler runs with the deployed function's narrow permissions. Three forms: (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) auto-resolves the function's execution role ARN from state (requires an active state source); (3) `--no-assume-role` explicitly opts out. Off by default — when omitted, the developer's shell credentials are forwarded unchanged (SAM-compatible default). STS failures degrade to a warn + dev-creds fallback.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers. Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name; pass an explicit value when CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).action(withErrorHandling(async (target, options) => {
7785
7785
  await localInvokeCommand(target, options, opts.extraStateProviders);
7786
7786
  }));
7787
7787
  [
@@ -7789,7 +7789,6 @@ function createLocalInvokeCommand(opts = {}) {
7789
7789
  ...appOptions(),
7790
7790
  ...contextOptions
7791
7791
  ].forEach((option) => invoke.addOption(option));
7792
- invoke.addOption(interactiveOption);
7793
7792
  invoke.addOption(deprecatedRegionOption);
7794
7793
  return invoke;
7795
7794
  }
@@ -14659,6 +14658,27 @@ function filterRoutesByApiIdentifier(routes, identifier) {
14659
14658
  return routes.filter((rwa) => routeMatchesIdentifier(rwa.route, identifier));
14660
14659
  }
14661
14660
  /**
14661
+ * Filter the route list to the UNION of several user-supplied
14662
+ * identifiers — the variadic `cdkl start-api <target...>` shape, where
14663
+ * passing two or more API identifiers serves exactly that subset (each
14664
+ * on its own port, via {@link groupRoutesByServer}).
14665
+ *
14666
+ * A route is kept when it matches ANY of the identifiers (same matching
14667
+ * rules as {@link filterRoutesByApiIdentifier}). Output order is the
14668
+ * input route order, so {@link groupRoutesByServer}'s stable grouping is
14669
+ * preserved. An empty `identifiers` list returns every route unchanged
14670
+ * (the "serve all" default path never calls this with an empty set, but
14671
+ * the no-op behavior keeps the helper total).
14672
+ *
14673
+ * Returns an empty array when no route matches any identifier — the
14674
+ * caller surfaces a "no API matched" error with the available
14675
+ * identifiers (see {@link availableApiIdentifiers}).
14676
+ */
14677
+ function filterRoutesByApiIdentifiers(routes, identifiers) {
14678
+ if (identifiers.length === 0) return [...routes];
14679
+ return routes.filter((rwa) => identifiers.some((id) => routeMatchesIdentifier(rwa.route, id)));
14680
+ }
14681
+ /**
14662
14682
  * Predicate behind {@link filterRoutesByApiIdentifier} and
14663
14683
  * {@link availableApiIdentifiers}'s primary-form selection. Exported
14664
14684
  * for test coverage only — the production code path goes through
@@ -14948,20 +14968,20 @@ function createAuthorizerCache(opts = {}) {
14948
14968
 
14949
14969
  //#endregion
14950
14970
  //#region src/cli/commands/local-start-api.ts
14951
- async function localStartApiCommand(target, options, extraStateProviders) {
14971
+ async function localStartApiCommand(targets, options, extraStateProviders) {
14952
14972
  const logger = getLogger();
14953
14973
  if (options.verbose) logger.setLevel("debug");
14954
- let apiFilter = target;
14974
+ let apiFilters = [...targets];
14955
14975
  if (options.api !== void 0) {
14956
- if (target !== void 0) throw new Error(`Cannot specify both positional target ('${target}') and --api flag ('${options.api}'). Use one or the other. The positional form is preferred — '--api' is a deprecated alias.`);
14976
+ if (targets.length > 0) throw new Error(`Cannot specify both positional target(s) ([${targets.join(", ")}]) and --api flag ('${options.api}'). Use one or the other. The positional form is preferred — '--api' is a deprecated alias.`);
14957
14977
  logger.warn(`[deprecated] --api <id> will be removed in a future major release. Use the positional argument instead: '${getEmbedConfig().cliName} start-api <id>'.`);
14958
- apiFilter = options.api;
14978
+ apiFilters = [options.api];
14959
14979
  }
14960
- assertStartApiInteractiveAllowed(options.interactive, apiFilter, options.allStacks);
14961
- let effectiveTarget = target;
14980
+ const shouldPromptBare = shouldPromptBareMultiSelect(apiFilters, options.allStacks, isInteractive());
14981
+ let effectiveTargets = [...apiFilters];
14962
14982
  const interactivePicked = { value: false };
14963
- const allStacksConflictList = allStacksConflicts(options, target, apiFilter);
14964
- if (allStacksConflictList.length > 0) throw new Error(`--all-stacks serves every stack's API and cannot be combined with a single-target selector (${allStacksConflictList.join(", ")}). Drop --all-stacks to target one stack, or drop the selector to serve them all. The bare --from-cfn-stack flag (no value) IS compatible with --all-stacks.`);
14983
+ const allStacksConflictList = allStacksConflicts(options, targets, apiFilters);
14984
+ if (allStacksConflictList.length > 0) throw new Error(`--all-stacks serves every stack's API and cannot be combined with a target subset selector (${allStacksConflictList.join(", ")}). Drop --all-stacks to target specific APIs, or drop the selector to serve them all. The bare --from-cfn-stack flag (no value) IS compatible with --all-stacks.`);
14965
14985
  warnIfDeprecatedRegion(options);
14966
14986
  await applyRoleArnIfSet({
14967
14987
  roleArn: options.roleArn,
@@ -14982,6 +15002,7 @@ async function localStartApiCommand(target, options, extraStateProviders) {
14982
15002
  let sigV4CredentialsLoader;
14983
15003
  const sigV4WarnedForeignIds = /* @__PURE__ */ new Set();
14984
15004
  const fromCfnTipEmitted = { value: false };
15005
+ const unmatchedTargetWarned = /* @__PURE__ */ new Set();
14985
15006
  /**
14986
15007
  * One synth + discover + build pass. Returns the next-state
14987
15008
  * material. Reused on initial boot AND every hot-reload firing.
@@ -15005,17 +15026,17 @@ async function localStartApiCommand(target, options, extraStateProviders) {
15005
15026
  ...Object.keys(context).length > 0 && { context }
15006
15027
  };
15007
15028
  const { stacks } = await synthesizer.synthesize(synthOpts);
15008
- if (options.interactive && !interactivePicked.value) {
15029
+ if (shouldPromptBare && !interactivePicked.value) {
15009
15030
  const apis = listTargets(stacks).apis;
15010
15031
  if (apis.length === 0) throw new Error(`No APIs found in this CDK app to choose from. Run \`${getEmbedConfig().cliName} list\` to see what is available.`);
15011
- const picked = await pickOneTarget("Select an API to serve", apis);
15012
- apiFilter = picked;
15013
- effectiveTarget = picked;
15032
+ const picked = await pickManyTargets("Select APIs to serve", apis, { preselectAll: true });
15033
+ apiFilters = picked;
15034
+ effectiveTargets = picked;
15014
15035
  interactivePicked.value = true;
15015
15036
  }
15016
15037
  const cfnStackFallback = typeof options.fromCfnStack === "string" ? options.fromCfnStack : void 0;
15017
- const targetStackPrefix = effectiveTarget?.includes("/") === true ? effectiveTarget.slice(0, effectiveTarget.indexOf("/")) : void 0;
15018
- const targetStacks = pickTargetStacks(stacks, options.stack, cfnStackFallback, targetStackPrefix, options.allStacks);
15038
+ const targetStackPrefix = deriveSynthStackPrefix(effectiveTargets);
15039
+ const targetStacks = pickTargetStacks(stacks, options.stack, cfnStackFallback, targetStackPrefix, options.allStacks || shouldSynthAllStacks(effectiveTargets, options.stack, cfnStackFallback));
15019
15040
  if (targetStacks.length === 0) throw new Error("No stacks matched. Pass --stack <name> (or --from-cfn-stack <name>) or run from a single-stack app.");
15020
15041
  const routedStackNames = targetStacks.map((s) => s.stackName);
15021
15042
  tryEmitFromCfnRedundancyTipOnce(options.fromCfnStack, routedStackNames, fromCfnTipEmitted, (routedStackName) => {
@@ -15041,12 +15062,15 @@ async function localStartApiCommand(target, options, extraStateProviders) {
15041
15062
  }
15042
15063
  attachStageContext(routes, stageMap);
15043
15064
  let routesWithAuth = attachAuthorizers(targetStacks, routes);
15044
- if (apiFilter !== void 0) {
15045
- if (!apiFilter.includes(":") && !apiFilter.includes("/") && targetStacks.length > 1) throw new Error(`Multiple stacks in app, target '${apiFilter}' is missing a stack prefix. Use 'StackName:${apiFilter}' or 'StackName/${apiFilter}' (Construct path form). Available stacks: ${targetStacks.map((s) => s.stackName).join(", ")}.`);
15046
- const filtered = filterRoutesByApiIdentifier(routesWithAuth, apiFilter);
15047
- if (filtered.length === 0) {
15065
+ if (apiFilters.length > 0) {
15066
+ const { filtered, unmatched } = resolveApiTargetSubset(routesWithAuth, apiFilters, targetStacks.map((s) => s.stackName));
15067
+ if (unmatched.length > 0) {
15048
15068
  const available = availableApiIdentifiers(routesWithAuth).join(", ") || "(none)";
15049
- throw new Error(`Target '${apiFilter}' did not match any discovered API. Available identifiers: ${available}.`);
15069
+ for (const id of unmatched) {
15070
+ if (unmatchedTargetWarned.has(id)) continue;
15071
+ unmatchedTargetWarned.add(id);
15072
+ logger.warn(`Target '${id}' did not match any discovered API; it is ignored. Available identifiers: ${available}.`);
15073
+ }
15050
15074
  }
15051
15075
  routesWithAuth = filtered;
15052
15076
  }
@@ -15437,7 +15461,7 @@ function pickTargetStacks(stacks, pattern, cfnStackFallback, targetFallback, all
15437
15461
  }
15438
15462
  /**
15439
15463
  * Issue #55: `--all-stacks` serves every stack's API as a union, so it
15440
- * cannot be combined with a selector that names exactly ONE target.
15464
+ * cannot be combined with a selector that names a target subset.
15441
15465
  * Returns the human-readable list of conflicting selectors (empty when
15442
15466
  * `--all-stacks` is off or there is no conflict).
15443
15467
  *
@@ -15451,31 +15475,121 @@ function pickTargetStacks(stacks, pattern, cfnStackFallback, targetFallback, all
15451
15475
  *
15452
15476
  * @internal exported for unit tests.
15453
15477
  */
15454
- function allStacksConflicts(options, target, apiFilter) {
15478
+ function allStacksConflicts(options, targets, apiFilters) {
15455
15479
  if (!options.allStacks) return [];
15456
15480
  const conflicts = [];
15457
- if (apiFilter !== void 0) conflicts.push(target !== void 0 ? `target '${target}'` : `--api '${options.api}'`);
15481
+ if (apiFilters.length > 0) conflicts.push(targets.length > 0 ? `target(s) [${targets.join(", ")}]` : `--api '${options.api}'`);
15458
15482
  if (options.stack !== void 0) conflicts.push(`--stack '${options.stack}'`);
15459
15483
  if (typeof options.fromCfnStack === "string") conflicts.push(`--from-cfn-stack '${options.fromCfnStack}'`);
15460
15484
  return conflicts;
15461
15485
  }
15462
15486
  /**
15463
- * Validate `-i/--interactive` for `start-api`. The picker is opt-in here
15464
- * (a bare `start-api` serves every API), so `-i` is mutually exclusive
15465
- * with any single-target selector (`apiFilter` = positional target OR
15466
- * `--api`) and with `--all-stacks`, and it requires a TTY. Throws when
15467
- * the combination is invalid; otherwise returns and the prompt runs
15468
- * later inside `synthesizeAndBuild`.
15487
+ * Resolve the variadic `cdkl start-api <target...>` subset against the
15488
+ * discovered route surface the pure core of the subset-serving path.
15489
+ *
15490
+ * Behavior:
15491
+ * - Rejects a BARE logical id (no `:`, no `/`) when the app has more than
15492
+ * one stack: a bare id is ambiguous because two stacks can carry the
15493
+ * same logical id (mirrors `cdkl invoke` / `cdkl run-task`'s resolver).
15494
+ * THROWS with the disambiguation hint.
15495
+ * - Filters routes to the UNION of the identifiers via
15496
+ * {@link filterRoutesByApiIdentifiers}. THROWS when the union is empty
15497
+ * (no identifier matched anything), listing the available identifiers.
15498
+ * - Returns the surviving union in `filtered` and the identifiers that
15499
+ * matched nothing in `unmatched`. A single typo among valid ids keeps
15500
+ * the siblings in `filtered` and surfaces the typo via `unmatched`;
15501
+ * the caller is responsible for warning (so the warning can be gated
15502
+ * one-shot across `--watch` reloads — see the call site).
15503
+ *
15504
+ * `availableApiIdentifiers(routes)` is computed ONCE here (not per-id) so
15505
+ * the resolution is O(N·M) rather than O(N²·M).
15506
+ *
15507
+ * @internal exported for unit tests + library consumers (re-exported from
15508
+ * the package entry).
15509
+ */
15510
+ function resolveApiTargetSubset(routes, identifiers, stackNames) {
15511
+ if (stackNames.length > 1) {
15512
+ for (const id of identifiers) if (!id.includes(":") && !id.includes("/")) throw new Error(`Multiple stacks in app, target '${id}' is missing a stack prefix. Use 'StackName:${id}' or 'StackName/${id}' (Construct path form). Available stacks: ${stackNames.join(", ")}.`);
15513
+ }
15514
+ const filtered = filterRoutesByApiIdentifiers(routes, identifiers);
15515
+ if (filtered.length === 0) {
15516
+ const available = availableApiIdentifiers(routes).join(", ") || "(none)";
15517
+ throw new Error(`Target(s) [${identifiers.join(", ")}] did not match any discovered API. Available identifiers: ${available}.`);
15518
+ }
15519
+ return {
15520
+ filtered,
15521
+ unmatched: identifiers.filter((id) => filterRoutesByApiIdentifiers(routes, [id]).length === 0)
15522
+ };
15523
+ }
15524
+ /**
15525
+ * Derive the single synth stack prefix shared by every supplied target,
15526
+ * for the synth-scope optimization (item 5 of the start-api subset UX).
15527
+ *
15528
+ * Each target's stack prefix is the segment before its first `/` (the
15529
+ * `<StackName>/<construct>` Construct-path form). Returns:
15530
+ * - `undefined` when `targets` is empty (serve-all path — no prefix).
15531
+ * - `undefined` when ANY target lacks a `/` (bare logical id — the synth
15532
+ * target can't be inferred from it, so fall back to the existing
15533
+ * single-stack auto-pick / multi-stack rejection path).
15534
+ * - `undefined` when targets span MORE THAN ONE distinct prefix (the
15535
+ * subset crosses stacks, so synth must cover all of them — see
15536
+ * {@link shouldSynthAllStacks}).
15537
+ * - the shared prefix when every target carries the SAME `<StackName>/`
15538
+ * prefix — keeping the single-stack synth optimization.
15539
+ *
15540
+ * @internal exported for unit tests.
15541
+ */
15542
+ function deriveSynthStackPrefix(targets) {
15543
+ if (targets.length === 0) return void 0;
15544
+ const prefixes = /* @__PURE__ */ new Set();
15545
+ for (const t of targets) {
15546
+ const slash = t.indexOf("/");
15547
+ if (slash === -1) return void 0;
15548
+ prefixes.add(t.slice(0, slash));
15549
+ }
15550
+ return prefixes.size === 1 ? [...prefixes][0] : void 0;
15551
+ }
15552
+ /**
15553
+ * Decide whether synth should cover ALL stacks for the given target
15554
+ * subset (item 5). Synth is scoped to one stack only when a single stack
15555
+ * can be pinned; otherwise we synth every stack and the union is filtered
15556
+ * down by `apiFilters` afterwards.
15557
+ *
15558
+ * Returns `true` (synth all) when there ARE explicit targets but no
15559
+ * single stack can be pinned from them — i.e. `--stack` is unset, an
15560
+ * explicit `--from-cfn-stack <name>` is unset, AND
15561
+ * {@link deriveSynthStackPrefix} can't resolve one shared prefix (targets
15562
+ * span stacks, or any target is a bare logical id). Returns `false` when
15563
+ * there are no targets (serve-all already synths everything via the
15564
+ * regular path) or a stack is otherwise pinned.
15565
+ *
15566
+ * @internal exported for unit tests.
15567
+ */
15568
+ function shouldSynthAllStacks(targets, stackPattern, cfnStackFallback) {
15569
+ if (targets.length === 0) return false;
15570
+ if (stackPattern !== void 0 || cfnStackFallback !== void 0) return false;
15571
+ return deriveSynthStackPrefix(targets) === void 0;
15572
+ }
15573
+ /**
15574
+ * Decide whether bare `start-api` should open the pre-selected-all
15575
+ * multi-select picker. The picker runs ONLY when:
15576
+ * - no explicit API subset was named (`apiFilters` empty — neither
15577
+ * positional `<targets...>` nor the deprecated `--api`),
15578
+ * - `--all-stacks` was not passed (that path already serves every API),
15579
+ * - AND stdin/stdout is a TTY.
15580
+ *
15581
+ * In a non-TTY (CI / pipe) this returns `false`, and the caller serves
15582
+ * EVERY discovered API without prompting — start-api's one intentional
15583
+ * asymmetry vs invoke / run-task (which error when bare in a non-TTY),
15584
+ * because start-api legitimately has a "serve all" default.
15469
15585
  *
15470
- * Extracted as a pure-ish function (TTY is read via {@link isInteractive})
15471
- * so the error contract is unit-testable without booting the server.
15586
+ * Extracted as a pure function (TTY is passed in) so the decision is
15587
+ * unit-testable without booting the server or juggling global TTY state.
15472
15588
  *
15473
15589
  * @internal exported for unit tests.
15474
15590
  */
15475
- function assertStartApiInteractiveAllowed(interactive, apiFilter, allStacks) {
15476
- if (!interactive) return;
15477
- if (apiFilter !== void 0 || allStacks) throw new Error("`-i/--interactive` cannot be combined with a positional target, --api, or --all-stacks; it interactively picks one API to serve. Drop the selector, or drop -i.");
15478
- if (!isInteractive()) throw new InteractiveTtyRequiredError("`-i/--interactive` requires an interactive terminal, but stdin/stdout is not a TTY.");
15591
+ function shouldPromptBareMultiSelect(apiFilters, allStacks, isTty) {
15592
+ return apiFilters.length === 0 && !allStacks && isTty;
15479
15593
  }
15480
15594
  /**
15481
15595
  * Decide whether the `--from-cfn-stack <name>` redundancy tip should
@@ -16563,15 +16677,14 @@ function resolveMtlsConfig(options) {
16563
16677
  */
16564
16678
  function createLocalStartApiCommand(opts = {}) {
16565
16679
  setEmbedConfig(opts.embedConfig);
16566
- const startApi = new Command("start-api").description("Run a long-running local HTTP server that maps API Gateway routes (REST v1, HTTP API, Function URL) to Lambda invocations against the AWS Lambda Runtime Interface Emulator (Docker required). Supports Lambda TOKEN/REQUEST authorizers, Cognito User Pool / HTTP v2 JWT authorizers, and AWS_IAM auth (REST v1 `AuthorizationType: AWS_IAM` and Function URL `AuthType: AWS_IAM` — SigV4 signature verification only; IAM policy evaluation is NOT emulated). When JWKS is unreachable, JWT authorizers fall back to pass-through (every token accepted) with a warn line — local dev fallback. VPC-config Lambdas run locally and surface a warn line at startup; their containers do NOT get attached to the deployed VPC subnets, so calls to private RDS / ElastiCache will fail.").argument("[target]", `Optional API filter. Accepts the bare CDK logical id ('MyHttpApi'; single-stack apps only), stack-qualified logical id ('MyStack:MyHttpApi'), full CDK Construct path ('MyStack/MyHttpApi/Resource'), or an ancestor Construct path that prefix-matches ('MyStack/MyHttpApi'). When omitted, every discovered API gets its own server (pass -i to pick one interactively instead). Mirrors \`${getEmbedConfig().cliName} invoke\` / \`${getEmbedConfig().cliName} run-task\` target syntax.`).addOption(new Option("--port <port>", "HTTP server port (default: auto-allocate)").default("0")).addOption(new Option("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option("--stack <name>", "Stack to start (single-stack apps auto-detect)")).addOption(new Option("--all-stacks", "Serve every stack's API in a multi-stack app (each API on its own port) instead of erroring out. Mutually exclusive with a positional target, --stack, and an explicit --from-cfn-stack <name>; the bare --from-cfn-stack flag stays compatible (binds each routed stack to its own CFn stack).").default(false)).addOption(new Option("--warm", "Pre-start one container per Lambda at server boot").default(false)).addOption(new Option("--per-lambda-concurrency <n>", "Pool size cap per Lambda (default 2, max 4)").default("2")).addOption(new Option("--no-pull", "Skip docker pull (cached image)")).addOption(new Option("--container-host <host>", "IP the host uses to bind/probe the RIE port (must be a numeric IP — `docker run -p <ip>:<port>:8080` rejects hostnames). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--debug-port-base <port>", "Reserve a contiguous --debug-port range (one per Lambda)")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--assume-role <arn-or-pair>", "Assume the Lambda's execution role and forward STS-issued temp creds. Bare <arn> = global default; <LogicalId>=<arn> = per-Lambda override (repeatable). Per-Lambda > global > unset (developer creds passed through).").argParser((raw, prev) => parseAssumeRoleToken(raw, prev))).addOption(new Option("--watch", "Hot-reload: re-synth + re-discover routes when the CDK app's source changes (honors cdk.json watch.include/exclude; cdk.out, node_modules, .git are always excluded). Off by default; the server keeps the previous version serving when synth fails mid-reload.").default(false)).addOption(new Option("--stage <name>", "Select an API Gateway Stage by its 'StageName'. Default: the first Stage attached to each API. Drives event.stageVariables for both REST v1 and HTTP API v2. NOTE: For HTTP API v2 routes, requestContext.stage is always '$default' regardless of this flag (AWS-side limitation — HTTP API only exposes one stage to the integration event); only event.stageVariables is affected for v2 routes. For REST v1 routes the selected StageName is also threaded into requestContext.stage.")).addOption(new Option("--api <id>", "DEPRECATED — use the positional <target> argument instead. Same accepted forms (bare logical id, stack-qualified, Construct path, ancestor prefix). Will be removed in a future major release.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers (issue #448). Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in Lambda env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name per routed stack; pass an explicit value when a single CFn stack should serve every routed stack. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--mtls-truststore <path>", `PEM-encoded CA bundle for client-certificate verification (mutual TLS). When set, the local server switches from HTTP to HTTPS and the TLS handshake rejects clients whose certificate doesn't chain to one of these CAs. Verified certs are surfaced on the Lambda event under requestContext.identity.clientCert (REST v1) / requestContext.authentication.clientCert (HTTP API v2). Must be set together with --mtls-cert + --mtls-key; partial flag sets are rejected. Generate a CA + server + client cert for local dev: openssl req -x509 -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.pem -subj "/CN=${getEmbedConfig().resourceNamePrefix}-ca" -days 365; openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-csr.pem -subj "/CN=localhost"; openssl x509 -req -in server-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365; openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-csr.pem -subj "/CN=client"; openssl x509 -req -in client-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365; curl --cacert ca.pem --cert client-cert.pem --key client-key.pem https://localhost:<port>/...`)).addOption(new Option("--mtls-cert <path>", "PEM-encoded server certificate for mutual TLS. Self-signed is fine for local dev. Must be set together with --mtls-truststore + --mtls-key.")).addOption(new Option("--mtls-key <path>", "PEM-encoded server private key matching --mtls-cert. Must be set together with --mtls-truststore + --mtls-cert.")).addOption(new Option("--strict-sigv4", "Opt-in: DENY AWS_IAM SigV4 requests that cannot be cryptographically verified (foreign access-key-id — e.g. a federated / Cognito Identity Pool / cross-account signer — OR no local AWS credentials configured) instead of the default warn-and-pass. DEFAULT off: cdk-local warn-and-passes unverifiable IAM requests with a placeholder principalId so local dev exercises app logic without reproducing an auth boundary it cannot fully emulate. OAC-fronted Function URLs always warn-and-pass regardless.").default(false)).action(withErrorHandling(async (target, options) => {
16567
- await localStartApiCommand(target, options, opts.extraStateProviders);
16680
+ const startApi = new Command("start-api").description("Run a long-running local HTTP server that maps API Gateway routes (REST v1, HTTP API, Function URL) to Lambda invocations against the AWS Lambda Runtime Interface Emulator (Docker required). Supports Lambda TOKEN/REQUEST authorizers, Cognito User Pool / HTTP v2 JWT authorizers, and AWS_IAM auth (REST v1 `AuthorizationType: AWS_IAM` and Function URL `AuthType: AWS_IAM` — SigV4 signature verification only; IAM policy evaluation is NOT emulated). When JWKS is unreachable, JWT authorizers fall back to pass-through (every token accepted) with a warn line — local dev fallback. VPC-config Lambdas run locally and surface a warn line at startup; their containers do NOT get attached to the deployed VPC subnets, so calls to private RDS / ElastiCache will fail.").argument("[targets...]", `Optional API subset filter. Pass one or more identifiers to serve exactly that subset (the union; each on its own port). Each accepts the bare CDK logical id ('MyHttpApi'; single-stack apps only), stack-qualified logical id ('MyStack:MyHttpApi'), full CDK Construct path ('MyStack/MyHttpApi/Resource'), or an ancestor Construct path that prefix-matches ('MyStack/MyHttpApi'). When omitted in a TTY, a multi-select picker opens with every API pre-selected (Enter serves all, deselect to pick a subset); when omitted in a non-TTY (CI / pipe) every discovered API is served. Mirrors \`${getEmbedConfig().cliName} invoke\` / \`${getEmbedConfig().cliName} run-task\` target syntax.`).addOption(new Option("--port <port>", "HTTP server port (default: auto-allocate)").default("0")).addOption(new Option("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option("--stack <name>", "Stack to start (single-stack apps auto-detect)")).addOption(new Option("--all-stacks", "Serve every stack's API in a multi-stack app (each API on its own port) instead of erroring out. Mutually exclusive with a positional target subset, --stack, and an explicit --from-cfn-stack <name>; the bare --from-cfn-stack flag stays compatible (binds each routed stack to its own CFn stack).").default(false)).addOption(new Option("--warm", "Pre-start one container per Lambda at server boot").default(false)).addOption(new Option("--per-lambda-concurrency <n>", "Pool size cap per Lambda (default 2, max 4)").default("2")).addOption(new Option("--no-pull", "Skip docker pull (cached image)")).addOption(new Option("--container-host <host>", "IP the host uses to bind/probe the RIE port (must be a numeric IP — `docker run -p <ip>:<port>:8080` rejects hostnames). Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--debug-port-base <port>", "Reserve a contiguous --debug-port range (one per Lambda)")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--assume-role <arn-or-pair>", "Assume the Lambda's execution role and forward STS-issued temp creds. Bare <arn> = global default; <LogicalId>=<arn> = per-Lambda override (repeatable). Per-Lambda > global > unset (developer creds passed through).").argParser((raw, prev) => parseAssumeRoleToken(raw, prev))).addOption(new Option("--watch", "Hot-reload: re-synth + re-discover routes when the CDK app's source changes (honors cdk.json watch.include/exclude; cdk.out, node_modules, .git are always excluded). Off by default; the server keeps the previous version serving when synth fails mid-reload.").default(false)).addOption(new Option("--stage <name>", "Select an API Gateway Stage by its 'StageName'. Default: the first Stage attached to each API. Drives event.stageVariables for both REST v1 and HTTP API v2. NOTE: For HTTP API v2 routes, requestContext.stage is always '$default' regardless of this flag (AWS-side limitation — HTTP API only exposes one stage to the integration event); only event.stageVariables is affected for v2 routes. For REST v1 routes the selected StageName is also threaded into requestContext.stage.")).addOption(new Option("--api <id>", "DEPRECATED — use the positional <targets...> argument instead. Accepts a SINGLE identifier; for a subset pass multiple positional targets. Same accepted forms (bare logical id, stack-qualified, Construct path, ancestor prefix). Will be removed in a future major release.")).addOption(new Option("--layer-role-arn <arn>", "Role to sts:AssumeRole before calling lambda:GetLayerVersion on every literal-ARN entry in Properties.Layers (issue #448). Use only when the dev credentials cannot read the layer — typically cross-account layers. AWS-published public layers (e.g. Lambda Powertools) are readable from every account and need no role.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in Lambda env vars with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (`cdk deploy`). Bare form uses the resolved stack name per routed stack; pass an explicit value when a single CFn stack should serve every routed stack. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--mtls-truststore <path>", `PEM-encoded CA bundle for client-certificate verification (mutual TLS). When set, the local server switches from HTTP to HTTPS and the TLS handshake rejects clients whose certificate doesn't chain to one of these CAs. Verified certs are surfaced on the Lambda event under requestContext.identity.clientCert (REST v1) / requestContext.authentication.clientCert (HTTP API v2). Must be set together with --mtls-cert + --mtls-key; partial flag sets are rejected. Generate a CA + server + client cert for local dev: openssl req -x509 -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.pem -subj "/CN=${getEmbedConfig().resourceNamePrefix}-ca" -days 365; openssl req -newkey rsa:2048 -nodes -keyout server-key.pem -out server-csr.pem -subj "/CN=localhost"; openssl x509 -req -in server-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365; openssl req -newkey rsa:2048 -nodes -keyout client-key.pem -out client-csr.pem -subj "/CN=client"; openssl x509 -req -in client-csr.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365; curl --cacert ca.pem --cert client-cert.pem --key client-key.pem https://localhost:<port>/...`)).addOption(new Option("--mtls-cert <path>", "PEM-encoded server certificate for mutual TLS. Self-signed is fine for local dev. Must be set together with --mtls-truststore + --mtls-key.")).addOption(new Option("--mtls-key <path>", "PEM-encoded server private key matching --mtls-cert. Must be set together with --mtls-truststore + --mtls-cert.")).addOption(new Option("--strict-sigv4", "Opt-in: DENY AWS_IAM SigV4 requests that cannot be cryptographically verified (foreign access-key-id — e.g. a federated / Cognito Identity Pool / cross-account signer — OR no local AWS credentials configured) instead of the default warn-and-pass. DEFAULT off: cdk-local warn-and-passes unverifiable IAM requests with a placeholder principalId so local dev exercises app logic without reproducing an auth boundary it cannot fully emulate. OAC-fronted Function URLs always warn-and-pass regardless.").default(false)).action(withErrorHandling(async (targets, options) => {
16681
+ await localStartApiCommand(targets, options, opts.extraStateProviders);
16568
16682
  }));
16569
16683
  [
16570
16684
  ...commonOptions(),
16571
16685
  ...appOptions(),
16572
16686
  ...contextOptions
16573
16687
  ].forEach((opt) => startApi.addOption(opt));
16574
- startApi.addOption(interactiveOption);
16575
16688
  startApi.addOption(deprecatedRegionOption);
16576
16689
  return startApi;
16577
16690
  }
@@ -17627,11 +17740,10 @@ async function localRunTaskCommand(target, options, extraStateProviders) {
17627
17740
  };
17628
17741
  const { stacks } = await synthesizer.synthesize(synthOpts);
17629
17742
  const resolvedTarget = await resolveSingleTarget(target, {
17630
- interactive: options.interactive,
17631
17743
  entries: listTargets(stacks).ecsTaskDefinitions,
17632
17744
  message: "Select an ECS task definition to run",
17633
17745
  noun: "ECS task definitions",
17634
- onMissing: () => new CdkLocalError(`${getEmbedConfig().cliName} run-task requires a <target> (an ECS task definition display path or logical ID). Run \`${getEmbedConfig().cliName} list\` to see them, or pass -i to pick interactively.`, "LOCAL_RUN_TASK_TARGET_REQUIRED")
17746
+ onMissing: () => new CdkLocalError(`${getEmbedConfig().cliName} run-task requires a <target> (an ECS task definition display path or logical ID). Run \`${getEmbedConfig().cliName} list\` to see them, or run it in a TTY to pick interactively.`, "LOCAL_RUN_TASK_TARGET_REQUIRED")
17635
17747
  });
17636
17748
  const candidate = pickCandidateStack$1(parseEcsTarget(resolvedTarget).stackPattern, stacks);
17637
17749
  stateProvider = createLocalStateProvider(options, candidate?.stackName ?? "", await resolveCfnFallbackRegion(options, candidate?.region), extraStateProviders);
@@ -17858,7 +17970,7 @@ async function resolveSidecarCredentials(options, assumedCredentials) {
17858
17970
  }
17859
17971
  function createLocalRunTaskCommand(opts = {}) {
17860
17972
  setEmbedConfig(opts.embedConfig);
17861
- const cmd = new Command("run-task").description("Run an AWS::ECS::TaskDefinition locally — pulls/builds images, sets up a per-task docker network with the AWS-published metadata-endpoints sidecar, and starts every container in dependsOn order. Target accepts a CDK display path (MyStack/MyService/TaskDef) or stack-qualified logical ID (MyStack:MyServiceTaskDefXYZ1234). Single-stack apps may omit the stack prefix. Omit <target> in an interactive terminal (or pass -i) to pick the task definition from a list.").argument("[target]", "CDK display path or stack-qualified logical ID of the AWS::ECS::TaskDefinition to run (omit to pick interactively in a TTY)").addOption(new Option("--cluster <name>", "Cluster name surfaced to ECS_CONTAINER_METADATA_URI_V4 and used as the docker network prefix").default(getEmbedConfig().resourceNamePrefix)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--host-port <containerPort=hostPort...>", "Publish a container port on a specific host port (e.g. 80=8080); repeatable. Default: host port == container port. Use this on macOS to map a privileged container port (< 1024) to a non-privileged host port and avoid the Docker Desktop admin-password prompt.")).addOption(new Option("--assume-task-role [arn]", "Assume the task definition's TaskRoleArn (or the supplied ARN) and forward STS-issued temp credentials via the metadata sidecar so containers run with the deployed function role. Bare flag uses the template's TaskRoleArn; pass an explicit ARN to override.")).addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--keep-running", "Don't docker rm -f the user containers on task exit (network + sidecar are still torn down). Use when you want to docker exec into a stopped container for post-mortems.").default(false)).addOption(new Option("--detach", "Start the containers in the background and exit (skip log streaming + auto teardown). Useful in CI smoke tests; caller manages container lifecycle.").default(false)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).action(withErrorHandling(async (target, options) => {
17973
+ const cmd = new Command("run-task").description("Run an AWS::ECS::TaskDefinition locally — pulls/builds images, sets up a per-task docker network with the AWS-published metadata-endpoints sidecar, and starts every container in dependsOn order. Target accepts a CDK display path (MyStack/MyService/TaskDef) or stack-qualified logical ID (MyStack:MyServiceTaskDefXYZ1234). Single-stack apps may omit the stack prefix. Omit <target> in an interactive terminal to pick the task definition from a list.").argument("[target]", "CDK display path or stack-qualified logical ID of the AWS::ECS::TaskDefinition to run (omit to pick interactively in a TTY)").addOption(new Option("--cluster <name>", "Cluster name surfaced to ECS_CONTAINER_METADATA_URI_V4 and used as the docker network prefix").default(getEmbedConfig().resourceNamePrefix)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--host-port <containerPort=hostPort...>", "Publish a container port on a specific host port (e.g. 80=8080); repeatable. Default: host port == container port. Use this on macOS to map a privileged container port (< 1024) to a non-privileged host port and avoid the Docker Desktop admin-password prompt.")).addOption(new Option("--assume-task-role [arn]", "Assume the task definition's TaskRoleArn (or the supplied ARN) and forward STS-issued temp credentials via the metadata sidecar so containers run with the deployed function role. Bare flag uses the template's TaskRoleArn; pass an explicit ARN to override.")).addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Issues sts:AssumeRole via the default credential chain and uses the temporary credentials for ecr:GetAuthorizationToken + docker pull. Required when the caller does not have direct cross-account access to the target repository. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--keep-running", "Don't docker rm -f the user containers on task exit (network + sidecar are still torn down). Use when you want to docker exec into a stopped container for post-mortems.").default(false)).addOption(new Option("--detach", "Start the containers in the background and exit (skip log streaming + auto teardown). Useful in CI smoke tests; caller manages container lifecycle.").default(false)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).action(withErrorHandling(async (target, options) => {
17862
17974
  await localRunTaskCommand(target, options, opts.extraStateProviders);
17863
17975
  }));
17864
17976
  [
@@ -17866,7 +17978,6 @@ function createLocalRunTaskCommand(opts = {}) {
17866
17978
  ...appOptions(),
17867
17979
  ...contextOptions
17868
17980
  ].forEach((opt) => cmd.addOption(opt));
17869
- cmd.addOption(interactiveOption);
17870
17981
  cmd.addOption(deprecatedRegionOption);
17871
17982
  return cmd;
17872
17983
  }
@@ -19040,11 +19151,10 @@ async function localStartServiceCommand(targets, options, extraStateProviders) {
19040
19151
  };
19041
19152
  const { stacks } = await synthesizer.synthesize(synthOpts);
19042
19153
  const resolvedTargets = await resolveMultiTarget(targets, {
19043
- interactive: options.interactive,
19044
19154
  entries: listTargets(stacks).ecsServices,
19045
19155
  message: "Select one or more ECS services to run",
19046
19156
  noun: "ECS services",
19047
- onMissing: () => new LocalStartServiceError(`${getEmbedConfig().cliName} start-service requires at least one <target>. Pass one or more service paths like 'Stack/Orders' 'Stack/Frontend', or run it in a TTY (or with -i) to pick interactively.`)
19157
+ onMissing: () => new LocalStartServiceError(`${getEmbedConfig().cliName} start-service requires at least one <target>. Pass one or more service paths like 'Stack/Orders' 'Stack/Frontend', or run it in a TTY to pick interactively.`)
19048
19158
  });
19049
19159
  rejectExplicitCfnStackWithMultipleStacks(options, resolvedTargets.length);
19050
19160
  perTarget = resolvedTargets.map((t) => ({
@@ -19336,7 +19446,7 @@ async function resolveSharedSidecarCredentials(options) {
19336
19446
  }
19337
19447
  function createLocalStartServiceCommand(opts = {}) {
19338
19448
  setEmbedConfig(opts.embedConfig);
19339
- const cmd = new Command("start-service").description(`Run one or more AWS::ECS::Service resources locally as a long-running emulator. Spins up DesiredCount task replicas per service (clamped by --max-tasks) using the same per-task docker network + metadata sidecar pattern as \`${getEmbedConfig().cliName} run-task\`, then keeps each replica running and restarts it on exit per --restart-policy. ^C tears every replica + sidecar + network down. Each <target> accepts a CDK display path (MyStack/MyService) or stack-qualified logical ID (MyStack:MyServiceXYZ); single-stack apps may omit the stack prefix. When two or more <target>s are supplied, every service is booted into a shared Cloud Map / Service Connect registry so peer services discover each other via docker --add-host overlay. Omit <targets> in an interactive terminal (or pass -i) to multi-select the services from a list.`).argument("[targets...]", "One or more CDK display paths or stack-qualified logical IDs of the AWS::ECS::Service resources to run (omit to multi-select interactively in a TTY)").addOption(new Option("--cluster <name>", "Cluster name surfaced to ECS_CONTAINER_METADATA_URI_V4 and used as the docker network prefix").default(getEmbedConfig().resourceNamePrefix)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--host-port <containerPort=hostPort...>", "Publish a container port on a specific host port (e.g. 80=8080); repeatable. Default: host port == container port. Use this on macOS to map a privileged container port (< 1024) to a non-privileged host port and avoid the Docker Desktop admin-password prompt. (Single-replica services only — multi-replica services do not publish host ports.)")).addOption(new Option("--assume-task-role [arn]", "Assume the task definition's TaskRoleArn (or the supplied ARN) and forward STS-issued temp credentials via the metadata sidecar so containers run with the deployed task role. Bare flag uses the template's TaskRoleArn; pass an explicit ARN to override.")).addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--max-tasks <n>", `Hard cap on local replica count. Caps the template DesiredCount so local dev machines don't run an unbounded number of containers. Cannot exceed ${83} due to the per-replica link-local /24 subnet allocator's range.`).default(3).argParser(parseMaxTasks)).addOption(new Option("--restart-policy <policy>", "How to react when an essential container exits. 'on-failure' (default) restarts only on non-zero exit; 'always' restarts on every exit; 'none' shuts the replica down and runs the service degraded.").default("on-failure").argParser(parseRestartPolicy)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).action(withErrorHandling(async (targets, options) => {
19449
+ const cmd = new Command("start-service").description(`Run one or more AWS::ECS::Service resources locally as a long-running emulator. Spins up DesiredCount task replicas per service (clamped by --max-tasks) using the same per-task docker network + metadata sidecar pattern as \`${getEmbedConfig().cliName} run-task\`, then keeps each replica running and restarts it on exit per --restart-policy. ^C tears every replica + sidecar + network down. Each <target> accepts a CDK display path (MyStack/MyService) or stack-qualified logical ID (MyStack:MyServiceXYZ); single-stack apps may omit the stack prefix. When two or more <target>s are supplied, every service is booted into a shared Cloud Map / Service Connect registry so peer services discover each other via docker --add-host overlay. Omit <targets> in an interactive terminal to multi-select the services from a list.`).argument("[targets...]", "One or more CDK display paths or stack-qualified logical IDs of the AWS::ECS::Service resources to run (omit to multi-select interactively in a TTY)").addOption(new Option("--cluster <name>", "Cluster name surfaced to ECS_CONTAINER_METADATA_URI_V4 and used as the docker network prefix").default(getEmbedConfig().resourceNamePrefix)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--host-port <containerPort=hostPort...>", "Publish a container port on a specific host port (e.g. 80=8080); repeatable. Default: host port == container port. Use this on macOS to map a privileged container port (< 1024) to a non-privileged host port and avoid the Docker Desktop admin-password prompt. (Single-replica services only — multi-replica services do not publish host ports.)")).addOption(new Option("--assume-task-role [arn]", "Assume the task definition's TaskRoleArn (or the supplied ARN) and forward STS-issued temp credentials via the metadata sidecar so containers run with the deployed task role. Bare flag uses the template's TaskRoleArn; pass an explicit ARN to override.")).addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--max-tasks <n>", `Hard cap on local replica count. Caps the template DesiredCount so local dev machines don't run an unbounded number of containers. Cannot exceed ${83} due to the per-replica link-local /24 subnet allocator's range.`).default(3).argParser(parseMaxTasks)).addOption(new Option("--restart-policy <policy>", "How to react when an essential container exits. 'on-failure' (default) restarts only on non-zero exit; 'always' restarts on every exit; 'none' shuts the replica down and runs the service degraded.").default("on-failure").argParser(parseRestartPolicy)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).action(withErrorHandling(async (targets, options) => {
19340
19450
  await localStartServiceCommand(targets, options, opts.extraStateProviders);
19341
19451
  }));
19342
19452
  [
@@ -19344,7 +19454,6 @@ function createLocalStartServiceCommand(opts = {}) {
19344
19454
  ...appOptions(),
19345
19455
  ...contextOptions
19346
19456
  ].forEach((opt) => cmd.addOption(opt));
19347
- cmd.addOption(interactiveOption);
19348
19457
  cmd.addOption(deprecatedRegionOption);
19349
19458
  return cmd;
19350
19459
  }
@@ -19388,7 +19497,7 @@ function formatTargetListing(listing, cliName, options = {}) {
19388
19497
  const long = options.long ?? false;
19389
19498
  return "\n" + [
19390
19499
  formatSection("Lambda Functions", `${cliName} invoke <target>`, listing.lambdas, long),
19391
- formatSection("APIs", `${cliName} start-api [target]`, listing.apis, long),
19500
+ formatSection("APIs", `${cliName} start-api [target...]`, listing.apis, long),
19392
19501
  formatSection("ECS Services", `${cliName} start-service <target...>`, listing.ecsServices, long),
19393
19502
  formatSection("ECS Task Definitions", `${cliName} run-task <target>`, listing.ecsTaskDefinitions, long)
19394
19503
  ].filter((lines) => lines.length > 0).map((lines) => lines.join("\n")).join("\n\n");
@@ -19398,14 +19507,14 @@ function formatSection(title, command, entries, long) {
19398
19507
  const lines = [`${title} -> ${command}`];
19399
19508
  for (const entry of entries) {
19400
19509
  const primary = entry.displayPath ?? entry.qualifiedId;
19401
- lines.push(` ${primary}`);
19510
+ lines.push(entry.kind ? ` ${primary} (${entry.kind})` : ` ${primary}`);
19402
19511
  if (long && entry.displayPath) lines.push(` ${entry.qualifiedId}`);
19403
19512
  }
19404
19513
  return lines;
19405
19514
  }
19406
19515
  function createLocalListCommand(opts = {}) {
19407
19516
  setEmbedConfig(opts.embedConfig);
19408
- const cmd = new Command("list").alias("ls").description("List the runnable targets in the synthesized CDK app, grouped by the command that runs them: Lambda functions (invoke), API Gateway REST v1 / HTTP v2 / Function URL / WebSocket surfaces (start-api), ECS services (start-service), and ECS task definitions (run-task). Each target is shown by its CDK display path; pass -l to also print the stack-qualified logical ID. Tip: you usually do not need to copy these — just run the command (e.g. `invoke`) and pick from the list, or pass -i.").addOption(new Option("-l, --long", "Also print each target's stack-qualified logical ID (<Stack>:<LogicalId>) beneath it").default(false)).action(withErrorHandling(async (options) => {
19517
+ const cmd = new Command("list").alias("ls").description("List the runnable targets in the synthesized CDK app, grouped by the command that runs them: Lambda functions (invoke), API Gateway REST v1 / HTTP v2 / Function URL / WebSocket surfaces (start-api), ECS services (start-service), and ECS task definitions (run-task). Each target is shown by its CDK display path; pass -l to also print the stack-qualified logical ID. Tip: you usually do not need to copy these — just run the command (e.g. `invoke`) with no target in a terminal and pick from the list.").addOption(new Option("-l, --long", "Also print each target's stack-qualified logical ID (<Stack>:<LogicalId>) beneath it").default(false)).action(withErrorHandling(async (options) => {
19409
19518
  await localListCommand(options);
19410
19519
  }));
19411
19520
  [
@@ -19418,5 +19527,5 @@ function createLocalListCommand(opts = {}) {
19418
19527
  }
19419
19528
 
19420
19529
  //#endregion
19421
- export { resolveEnvVars as $, matchRoute as A, handleConnectionsRequest as B, evaluateCachedLambdaPolicy as C, buildCorsConfigByApiId as D, applyCorsResponseHeaders as E, HOST_GATEWAY_MIN_VERSION as F, createLocalInvokeCommand as G, buildConnectEvent as H, probeHostGatewaySupport as I, resolveRuntimeImage as J, resolveRuntimeCodeMountPath as K, bufferToBody as L, applyAuthorizerOverlay as M, buildHttpApiV2Event as N, buildCorsConfigFromCloudFrontChain as O, buildRestV1Event as P, substituteEnvVarsFromStateAsync as Q, ConnectionRegistry as R, computeRequestIdentityHash as S, invokeTokenAuthorizer as T, buildDisconnectEvent as U, parseConnectionsPath as V, buildMessageEvent as W, substituteAgainstStateAsync as X, substituteAgainstState as Y, substituteEnvVarsFromState as Z, buildJwksUrlFromIssuer as _, discoverWebSocketApisOrThrow as _t, getContainerNetworkIp as a, createLocalStateProvider as at, verifyJwtAuthorizer as b, pickRefLogicalId as bt, createAuthorizerCache as c, resolveCfnFallbackRegion as ct, availableApiIdentifiers as d, CfnLocalStateProvider as dt, materializeLayerFromArn as et, filterRoutesByApiIdentifier as f, collectSsmParameterRefs as ft, buildCognitoJwksUrl as g, discoverWebSocketApis as gt, resolveServiceIntegrationParameters as h, listTargets as ht, CloudMapRegistry as i, LocalStateSourceError as it, translateLambdaResponse as j, matchPreflight as k, attachStageContext as l, resolveCfnRegion as lt, resolveSelectionExpression as m, countTargets as mt, formatTargetListing as n, substituteImagePlaceholders as nt, createLocalRunTaskCommand as o, isCfnFlagPresent as ot, groupRoutesByServer as p, resolveSsmParameters as pt, resolveRuntimeFileExtension as q, createLocalStartServiceCommand as r, tryResolveImageFnJoin as rt, createLocalStartApiCommand as s, rejectExplicitCfnStackWithMultipleStacks as st, createLocalListCommand as t, derivePseudoParametersFromRegion as tt, buildStageMap as u, resolveCfnStackName as ut, createJwksCache as v, parseSelectionExpressionPath as vt, invokeRequestAuthorizer as w, buildMethodArn as x, resolveLambdaArnIntrinsic as xt, verifyCognitoJwt as y, discoverRoutes as yt, buildMgmtEndpointEnvUrl as z };
19422
- //# sourceMappingURL=local-list-BUr5m_wb.js.map
19530
+ export { createLocalInvokeCommand as $, buildCorsConfigByApiId as A, resolveLambdaArnIntrinsic as At, selectIntegrationResponse as B, verifyJwtAuthorizer as C, countTargets as Ct, invokeRequestAuthorizer as D, parseSelectionExpressionPath as Dt, evaluateCachedLambdaPolicy as E, discoverWebSocketApisOrThrow as Et, applyAuthorizerOverlay as F, bufferToBody as G, VtlEvaluationError as H, buildHttpApiV2Event as I, handleConnectionsRequest as J, ConnectionRegistry as K, buildRestV1Event as L, matchPreflight as M, matchRoute as N, invokeTokenAuthorizer as O, discoverRoutes as Ot, translateLambdaResponse as P, buildMessageEvent as Q, evaluateResponseParameters as R, verifyCognitoJwt as S, resolveSsmParameters as St, computeRequestIdentityHash as T, discoverWebSocketApis as Tt, HOST_GATEWAY_MIN_VERSION as U, tryParseStatus as V, probeHostGatewaySupport as W, buildConnectEvent as X, parseConnectionsPath as Y, buildDisconnectEvent as Z, resolveSelectionExpression as _, resolveCfnFallbackRegion as _t, CloudMapRegistry as a, substituteAgainstStateAsync as at, buildJwksUrlFromIssuer as b, CfnLocalStateProvider as bt, createLocalStartApiCommand as c, resolveEnvVars as ct, attachStageContext as d, substituteImagePlaceholders as dt, resolveRuntimeCodeMountPath as et, buildStageMap as f, tryResolveImageFnJoin as ft, groupRoutesByServer as g, rejectExplicitCfnStackWithMultipleStacks as gt, filterRoutesByApiIdentifiers as h, isCfnFlagPresent as ht, buildCloudMapIndex as i, substituteAgainstState as it, buildCorsConfigFromCloudFrontChain as j, applyCorsResponseHeaders as k, pickRefLogicalId as kt, resolveApiTargetSubset as l, materializeLayerFromArn as lt, filterRoutesByApiIdentifier as m, createLocalStateProvider as mt, formatTargetListing as n, resolveRuntimeImage as nt, getContainerNetworkIp as o, substituteEnvVarsFromState as ot, availableApiIdentifiers as p, LocalStateSourceError as pt, buildMgmtEndpointEnvUrl as q, createLocalStartServiceCommand as r, EcsTaskResolutionError as rt, createLocalRunTaskCommand as s, substituteEnvVarsFromStateAsync as st, createLocalListCommand as t, resolveRuntimeFileExtension as tt, createAuthorizerCache as u, derivePseudoParametersFromRegion as ut, resolveServiceIntegrationParameters as v, resolveCfnRegion as vt, buildMethodArn as w, listTargets as wt, createJwksCache as x, collectSsmParameterRefs as xt, buildCognitoJwksUrl as y, resolveCfnStackName as yt, pickResponseTemplate as z };
19531
+ //# sourceMappingURL=local-list-DHtTSGOt.js.map