cdk-local 0.5.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/dist/cli.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{local-start-service-2tcrICJq.js → local-start-service-DDjMUt0E.js} +93 -8
- package/dist/{local-start-service-2tcrICJq.js.map → local-start-service-DDjMUt0E.js.map} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,13 +78,18 @@ cdkl start-api
|
|
|
78
78
|
cdkl start-api MyStack/MyApi
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
In a multi-stack app, a bare `cdkl start-api` errors out rather than serving every stack's API at once (so a side-stack's API is never booted by accident).
|
|
81
|
+
In a multi-stack app, a bare `cdkl start-api` errors out rather than serving every stack's API at once (so a side-stack's API is never booted by accident). Either serve them all explicitly, or pick one stack with the first selector you supply:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Serve every stack's API (each on its own port)
|
|
85
|
+
cdkl start-api --all-stacks
|
|
86
|
+
```
|
|
82
87
|
|
|
83
88
|
- `--stack <name>` — the synth stack name, matched against your CDK app.
|
|
84
89
|
- `--from-cfn-stack <name>` — the deployed CloudFormation stack name; doubles as the stack selector (see [section 2](#2-bound-to-a-deployed-stack)).
|
|
85
90
|
- a stack-qualified target like `MyStack/MyApi` — the `MyStack` prefix selects the stack.
|
|
86
91
|
|
|
87
|
-
See [docs/cli-reference.md](docs/cli-reference.md) for the full precedence rules.
|
|
92
|
+
`--all-stacks` is mutually exclusive with those single-target selectors (the bare `--from-cfn-stack` flag stays compatible). See [docs/cli-reference.md](docs/cli-reference.md) for the full precedence rules.
|
|
88
93
|
|
|
89
94
|
#### ECS — `run-task` / `start-service`
|
|
90
95
|
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as createLocalInvokeCommand, n as createLocalRunTaskCommand, r as createLocalStartApiCommand, t as createLocalStartServiceCommand } from "./local-start-service-
|
|
2
|
+
import { i as createLocalInvokeCommand, n as createLocalRunTaskCommand, r as createLocalStartApiCommand, t as createLocalStartServiceCommand } from "./local-start-service-DDjMUt0E.js";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
|
|
5
5
|
//#region src/cli/index.ts
|
|
6
6
|
const program = new Command();
|
|
7
|
-
program.name("cdkl").description("Run AWS CDK stacks locally with Docker.").version("0.
|
|
7
|
+
program.name("cdkl").description("Run AWS CDK stacks locally with Docker.").version("0.7.0");
|
|
8
8
|
program.addCommand(createLocalInvokeCommand());
|
|
9
9
|
program.addCommand(createLocalStartApiCommand());
|
|
10
10
|
program.addCommand(createLocalRunTaskCommand());
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types/state.ts","../src/local/state-resolver.ts","../src/local/local-state-provider.ts","../src/cli/commands/local-state-source.ts","../src/local/embed-config.ts","../src/cli/commands/local-invoke.ts","../src/cli/commands/local-start-api.ts","../src/cli/commands/local-run-task.ts","../src/cli/commands/local-start-service.ts","../src/local/cfn-local-state-provider.ts"],"mappings":";;;;UAuLiB,aAAA;EAEf,UAAA;EAGA,YAAA;EAGA,UAAA,EAAY,MAAA;EAcZ,kBAAA,GAAqB,MAAA;EAGrB,UAAA,GAAa,MAAA;EAGb,YAAA;EAGA,QAAA,GAAW,MAAA;EAmBX,cAAA;EAMA,mBAAA;EAyBA,aAAA;AAAA;;;UCxIe,gBAAA;EACf,SAAA;EACA,MAAA;EACA,SAAA;EACA,SAAA;AAAA;AAAA,UAqBe,kBAAA;EAOf,aAAA,CAAc,UAAA,WAAqB,OAAA;EAQnC,qBAAA,CACE,aAAA,UACA,cAAA,UACA,UAAA,WACC,OAAA;AAAA;AAAA,UAGY,mBAAA;EAEf,SAAA,EAAW,MAAA,SAAe,aAAA;EAE1B,gBAAA,GAAmB,gBAAA;EAOnB,kBAAA,GAAqB,kBAAA;EAOrB,cAAA;AAAA;;;UCrJe,gBAAA;EAQf,SAAA,EAAW,MAAA,SAAe,aAAA;EAO1B,OAAA,EAAS,MAAA;EAOT,MAAA;AAAA;AAAA,UAsBe,kBAAA;EAAA,SAMN,KAAA;EAQT,IAAA,CAAK,SAAA,UAAmB,WAAA,uBAAkC,OAAA,CAAQ,gBAAA;EAalE,uBAAA,CAAwB,cAAA,WAAyB,OAAA,CAAQ,kBAAA;EAKzD,OAAA;AAAA;;;UC9Ee,uBAAA;EAOf,YAAA;EAEA,MAAA;EAEA,OAAA;EAMA,WAAA;EAAA,CAEC,GAAA;AAAA;AAAA,KAQS,yBAAA,IAA6B,OAAA,EAAS,uBAAA,KAA4B,kBAAA;AAAA,KAUlE,mBAAA,GAAsB,MAAA,SAAe,yBAAA;AAAA,iBAUjC,mBAAA,CAAoB,YAAA,oBAAgC,SAAA;AAAA,iBAapD,gBAAA,CAAiB,IAAA,EAAM,IAAA,CAAK,uBAAA;AAAA,iBAgB5B,gBAAA,CACd,OAAA,EAAS,IAAA,CAAK,uBAAA,6BACd,WAAA;AAAA,cAqBW,qBAAA,SAA8B,KAAA;cAC7B,OAAA;AAAA;AAAA,iBAkBE,wCAAA,CACd,OAAA,EAAS,IAAA,CAAK,uBAAA,mBACd,gBAAA;AAAA,iBAiCc,wBAAA,CACd,OAAA,EAAS,uBAAA,EACT,SAAA,UACA,WAAA,sBACA,mBAAA,GAAsB,mBAAA,GACrB,kBAAA;;;UCtLc,mBAAA;EAMf,OAAA;EAOA,UAAA;EAMA,WAAA;EAOA,kBAAA;EAMA,gBAAA;EAMA,SAAA;AAAA;;;UC8Ee,+BAAA;EACf,mBAAA,GAAsB,mBAAA;EAEtB,WAAA,GAAc,mBAAA;AAAA;AAAA,iBA22BA,wBAAA,CAAyB,IAAA,GAAM,+BAAA,GAAuC,OAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types/state.ts","../src/local/state-resolver.ts","../src/local/local-state-provider.ts","../src/cli/commands/local-state-source.ts","../src/local/embed-config.ts","../src/cli/commands/local-invoke.ts","../src/cli/commands/local-start-api.ts","../src/cli/commands/local-run-task.ts","../src/cli/commands/local-start-service.ts","../src/local/cfn-local-state-provider.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as LocalStateSourceError, c as rejectExplicitCfnStackWithMultipleStacks, d as CfnLocalStateProvider, i as createLocalInvokeCommand, l as resolveCfnRegion, n as createLocalRunTaskCommand, o as createLocalStateProvider, r as createLocalStartApiCommand, s as isCfnFlagPresent, t as createLocalStartServiceCommand, u as resolveCfnStackName } from "./local-start-service-
|
|
1
|
+
import { a as LocalStateSourceError, c as rejectExplicitCfnStackWithMultipleStacks, d as CfnLocalStateProvider, i as createLocalInvokeCommand, l as resolveCfnRegion, n as createLocalRunTaskCommand, o as createLocalStateProvider, r as createLocalStartApiCommand, s as isCfnFlagPresent, t as createLocalStartServiceCommand, u as resolveCfnStackName } from "./local-start-service-DDjMUt0E.js";
|
|
2
2
|
|
|
3
3
|
export { CfnLocalStateProvider, LocalStateSourceError, createLocalInvokeCommand, createLocalRunTaskCommand, createLocalStartApiCommand, createLocalStartServiceCommand, createLocalStateProvider, isCfnFlagPresent, rejectExplicitCfnStackWithMultipleStacks, resolveCfnRegion, resolveCfnStackName };
|
|
@@ -14201,6 +14201,8 @@ async function localStartApiCommand(target, options, extraStateProviders) {
|
|
|
14201
14201
|
logger.warn(`[deprecated] --api <id> will be removed in a future major release. Use the positional argument instead: '${getEmbedConfig().cliName} start-api <id>'.`);
|
|
14202
14202
|
apiFilter = options.api;
|
|
14203
14203
|
}
|
|
14204
|
+
const allStacksConflictList = allStacksConflicts(options, target, apiFilter);
|
|
14205
|
+
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.`);
|
|
14204
14206
|
warnIfDeprecatedRegion(options);
|
|
14205
14207
|
await applyRoleArnIfSet({
|
|
14206
14208
|
roleArn: options.roleArn,
|
|
@@ -14247,7 +14249,7 @@ async function localStartApiCommand(target, options, extraStateProviders) {
|
|
|
14247
14249
|
const { stacks } = await synthesizer.synthesize(synthOpts);
|
|
14248
14250
|
const cfnStackFallback = typeof options.fromCfnStack === "string" ? options.fromCfnStack : void 0;
|
|
14249
14251
|
const targetStackPrefix = target?.includes("/") === true ? target.slice(0, target.indexOf("/")) : void 0;
|
|
14250
|
-
const targetStacks = pickTargetStacks(stacks, options.stack, cfnStackFallback, targetStackPrefix);
|
|
14252
|
+
const targetStacks = pickTargetStacks(stacks, options.stack, cfnStackFallback, targetStackPrefix, options.allStacks);
|
|
14251
14253
|
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.");
|
|
14252
14254
|
const routedStackNames = targetStacks.map((s) => s.stackName);
|
|
14253
14255
|
tryEmitFromCfnRedundancyTipOnce(options.fromCfnStack, routedStackNames, fromCfnTipEmitted, (routedStackName) => {
|
|
@@ -14310,7 +14312,9 @@ async function localStartApiCommand(target, options, extraStateProviders) {
|
|
|
14310
14312
|
skipPull: options.pull === false,
|
|
14311
14313
|
...options.layerRoleArn !== void 0 && { layerRoleArn: options.layerRoleArn },
|
|
14312
14314
|
...profileCredentials && { profileCredentials },
|
|
14313
|
-
...profileCredsFile && { profileCredsFile }
|
|
14315
|
+
...profileCredsFile && { profileCredsFile },
|
|
14316
|
+
...profileCredentials?.region && { profileRegion: profileCredentials.region },
|
|
14317
|
+
...options.stackRegion && { stackRegionOverride: options.stackRegion }
|
|
14314
14318
|
});
|
|
14315
14319
|
specs.set(logicalId, spec);
|
|
14316
14320
|
}
|
|
@@ -14629,12 +14633,37 @@ async function localStartApiCommand(target, options, extraStateProviders) {
|
|
|
14629
14633
|
* routing rules.
|
|
14630
14634
|
*/
|
|
14631
14635
|
/** @internal exported for unit tests. */
|
|
14632
|
-
function pickTargetStacks(stacks, pattern, cfnStackFallback, targetFallback) {
|
|
14636
|
+
function pickTargetStacks(stacks, pattern, cfnStackFallback, targetFallback, allStacks) {
|
|
14637
|
+
if (allStacks) return stacks;
|
|
14633
14638
|
const effective = pattern ?? cfnStackFallback ?? targetFallback;
|
|
14634
14639
|
if (effective) return matchStacks(stacks, [effective]);
|
|
14635
14640
|
if (stacks.length === 1) return stacks;
|
|
14636
14641
|
if (stacks.length === 0) return [];
|
|
14637
|
-
throw new Error(`Multi-stack app: pass --stack <name>, --from-cfn-stack <name>,
|
|
14642
|
+
throw new Error(`Multi-stack app: pass --stack <name>, --from-cfn-stack <name>, a stack-qualified target like "<StackName>/<construct>", or --all-stacks to serve every stack. Available stacks: ${stacks.map((s) => s.stackName).join(", ")}.`);
|
|
14643
|
+
}
|
|
14644
|
+
/**
|
|
14645
|
+
* Issue #55: `--all-stacks` serves every stack's API as a union, so it
|
|
14646
|
+
* cannot be combined with a selector that names exactly ONE target.
|
|
14647
|
+
* Returns the human-readable list of conflicting selectors (empty when
|
|
14648
|
+
* `--all-stacks` is off or there is no conflict).
|
|
14649
|
+
*
|
|
14650
|
+
* The bare `--from-cfn-stack` flag (Commander maps it to boolean `true`)
|
|
14651
|
+
* is NOT a conflict — it binds each routed stack to its own CFn stack,
|
|
14652
|
+
* which is exactly the multi-stack union case. Only an explicit
|
|
14653
|
+
* `--from-cfn-stack <name>` (a string) names a single stack and conflicts.
|
|
14654
|
+
*
|
|
14655
|
+
* Extracted as a pure function so it can be unit-tested without booting
|
|
14656
|
+
* the full server.
|
|
14657
|
+
*
|
|
14658
|
+
* @internal exported for unit tests.
|
|
14659
|
+
*/
|
|
14660
|
+
function allStacksConflicts(options, target, apiFilter) {
|
|
14661
|
+
if (!options.allStacks) return [];
|
|
14662
|
+
const conflicts = [];
|
|
14663
|
+
if (apiFilter !== void 0) conflicts.push(target !== void 0 ? `target '${target}'` : `--api '${options.api}'`);
|
|
14664
|
+
if (options.stack !== void 0) conflicts.push(`--stack '${options.stack}'`);
|
|
14665
|
+
if (typeof options.fromCfnStack === "string") conflicts.push(`--from-cfn-stack '${options.fromCfnStack}'`);
|
|
14666
|
+
return conflicts;
|
|
14638
14667
|
}
|
|
14639
14668
|
/**
|
|
14640
14669
|
* Decide whether the `--from-cfn-stack <name>` redundancy tip should
|
|
@@ -14807,7 +14836,7 @@ function warnIamRoutes(routesWithAuth) {
|
|
|
14807
14836
|
* missing, runtime not supported).
|
|
14808
14837
|
*/
|
|
14809
14838
|
async function buildContainerSpec(args) {
|
|
14810
|
-
const { logicalId, stacks, overrides, assumeRole, containerHost, debugPort, stsRegion, inlineTmpDirs, layerTmpDirs, stateByStack, skipPull, layerRoleArn, profileCredentials, profileCredsFile } = args;
|
|
14839
|
+
const { logicalId, stacks, overrides, assumeRole, containerHost, debugPort, stsRegion, inlineTmpDirs, layerTmpDirs, stateByStack, skipPull, layerRoleArn, profileCredentials, profileCredsFile, profileRegion, stackRegionOverride } = args;
|
|
14811
14840
|
const lambda = resolveLambdaByLogicalId(logicalId, stacks);
|
|
14812
14841
|
let codeDir;
|
|
14813
14842
|
let optDir;
|
|
@@ -14868,6 +14897,14 @@ async function buildContainerSpec(args) {
|
|
|
14868
14897
|
dockerEnv["AWS_PROFILE"] = profileCredsFile.profileName;
|
|
14869
14898
|
}
|
|
14870
14899
|
}
|
|
14900
|
+
if (!dockerEnv["AWS_REGION"]) {
|
|
14901
|
+
const fallbackRegion = resolveContainerFallbackRegion({
|
|
14902
|
+
stackRegionOverride,
|
|
14903
|
+
synthRegion: lambda.stack.region,
|
|
14904
|
+
profileRegion
|
|
14905
|
+
});
|
|
14906
|
+
if (fallbackRegion) dockerEnv["AWS_REGION"] = fallbackRegion;
|
|
14907
|
+
}
|
|
14871
14908
|
if (debugPort !== void 0) dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
|
|
14872
14909
|
const tmpfs = lambda.ephemeralStorageMb !== void 0 ? {
|
|
14873
14910
|
target: "/tmp",
|
|
@@ -15269,6 +15306,18 @@ function forwardAwsEnv(env) {
|
|
|
15269
15306
|
* common dev session; long-running `--watch` sessions that outlive
|
|
15270
15307
|
* the creds need a cdk-local restart (deferred refresh out of scope for
|
|
15271
15308
|
* v1, see issue #654).
|
|
15309
|
+
*
|
|
15310
|
+
* Also resolves the profile's configured `region` (from `~/.aws/config`'s
|
|
15311
|
+
* `region = ...` for this profile) off the same client config. The
|
|
15312
|
+
* synthesized credentials file we mount into the container carries only
|
|
15313
|
+
* the credential triple — no `region =` — so without this the container
|
|
15314
|
+
* boots with creds but no region, and a handler's ambient-region SDK call
|
|
15315
|
+
* (`new XxxClient({})`) fails with "Region is missing". The caller seeds
|
|
15316
|
+
* the container's `AWS_REGION` fallback with it (see
|
|
15317
|
+
* {@link resolveContainerFallbackRegion}). Region resolution is
|
|
15318
|
+
* best-effort: a profile with no region (or any resolution failure)
|
|
15319
|
+
* yields `region: undefined` rather than throwing — a missing region is
|
|
15320
|
+
* not a missing-credentials error.
|
|
15272
15321
|
*/
|
|
15273
15322
|
async function resolveProfileCredentials(profile) {
|
|
15274
15323
|
const { STSClient } = await import("@aws-sdk/client-sts");
|
|
@@ -15277,16 +15326,52 @@ async function resolveProfileCredentials(profile) {
|
|
|
15277
15326
|
const credsProvider = sts.config.credentials;
|
|
15278
15327
|
const creds = typeof credsProvider === "function" ? await credsProvider() : credsProvider;
|
|
15279
15328
|
if (!creds || !creds.accessKeyId || !creds.secretAccessKey) throw new Error(`--profile '${profile}': credential provider chain resolved without usable credentials. Check \`aws sso login --profile ` + profile + "` for SSO profiles, or `~/.aws/credentials` / `~/.aws/config` for regular profiles.");
|
|
15329
|
+
let region;
|
|
15330
|
+
try {
|
|
15331
|
+
const regionProvider = sts.config.region;
|
|
15332
|
+
const resolved = typeof regionProvider === "function" ? await regionProvider() : regionProvider;
|
|
15333
|
+
if (typeof resolved === "string" && resolved.length > 0) region = resolved;
|
|
15334
|
+
} catch {
|
|
15335
|
+
region = void 0;
|
|
15336
|
+
}
|
|
15280
15337
|
return {
|
|
15281
15338
|
accessKeyId: creds.accessKeyId,
|
|
15282
15339
|
secretAccessKey: creds.secretAccessKey,
|
|
15283
|
-
...creds.sessionToken && { sessionToken: creds.sessionToken }
|
|
15340
|
+
...creds.sessionToken && { sessionToken: creds.sessionToken },
|
|
15341
|
+
...region && { region }
|
|
15284
15342
|
};
|
|
15285
15343
|
} finally {
|
|
15286
15344
|
sts.destroy();
|
|
15287
15345
|
}
|
|
15288
15346
|
}
|
|
15289
15347
|
/**
|
|
15348
|
+
* Resolve the fallback `AWS_REGION` for a Lambda container when neither
|
|
15349
|
+
* the assume-role STS region nor a forwarded `AWS_REGION` /
|
|
15350
|
+
* `AWS_DEFAULT_REGION` env var already set one.
|
|
15351
|
+
*
|
|
15352
|
+
* Precedence mirrors where the deployed function would actually run, so a
|
|
15353
|
+
* handler's ambient-region SDK call (`new XxxClient({})`) reaches the same
|
|
15354
|
+
* region locally as the resources it is bound to:
|
|
15355
|
+
*
|
|
15356
|
+
* 1. `--stack-region` — explicit; also drives the `--from-cfn-stack` CFn
|
|
15357
|
+
* client, so the container matches the region the bound stack was read
|
|
15358
|
+
* from.
|
|
15359
|
+
* 2. the synth-derived stack region — `env.region` on the CDK stack, read
|
|
15360
|
+
* from the cloud assembly manifest (`StackInfo.region`). Previously
|
|
15361
|
+
* used only host-side for the `--from-cfn-stack` CFn client; never
|
|
15362
|
+
* injected into the container.
|
|
15363
|
+
* 3. the `--profile`'s configured region — `~/.aws/config`'s `region =`
|
|
15364
|
+
* for the profile. `--profile` injected credentials but not this.
|
|
15365
|
+
*
|
|
15366
|
+
* Returns `undefined` when none is known; the caller leaves `AWS_REGION`
|
|
15367
|
+
* unset so the SDK's own "Region is missing" surfaces (the correct signal
|
|
15368
|
+
* for a region-agnostic stack with no profile region and no `AWS_REGION`
|
|
15369
|
+
* env).
|
|
15370
|
+
*/
|
|
15371
|
+
function resolveContainerFallbackRegion(args) {
|
|
15372
|
+
return args.stackRegionOverride ?? args.synthRegion ?? args.profileRegion;
|
|
15373
|
+
}
|
|
15374
|
+
/**
|
|
15290
15375
|
* Issue an STS AssumeRole and return temporary credentials. Mirrors
|
|
15291
15376
|
* `cdkl invoke`'s helper byte-for-byte; lifted here so the
|
|
15292
15377
|
* start-api command stays self-contained.
|
|
@@ -15632,7 +15717,7 @@ function resolveMtlsConfig(options) {
|
|
|
15632
15717
|
*/
|
|
15633
15718
|
function createLocalStartApiCommand(opts = {}) {
|
|
15634
15719
|
setEmbedConfig(opts.embedConfig);
|
|
15635
|
-
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. 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("--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 cdk.out/ or asset directories change. 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("--allow-unverified-sigv4", "Opt-in: allow AWS_IAM SigV4 requests that cannot be cryptographically verified (foreign access-key-id, OR no local AWS credentials configured) to pass through with a placeholder principalId. DEFAULT off — fail-closed so unauthenticated bypass is impossible against `event.requestContext.identity.accessKey`-trusting handler code. Use only in dev loops where you understand the risk.").default(false)).action(withErrorHandling(async (target, options) => {
|
|
15720
|
+
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. 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 cdk.out/ or asset directories change. 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("--allow-unverified-sigv4", "Opt-in: allow AWS_IAM SigV4 requests that cannot be cryptographically verified (foreign access-key-id, OR no local AWS credentials configured) to pass through with a placeholder principalId. DEFAULT off — fail-closed so unauthenticated bypass is impossible against `event.requestContext.identity.accessKey`-trusting handler code. Use only in dev loops where you understand the risk.").default(false)).action(withErrorHandling(async (target, options) => {
|
|
15636
15721
|
await localStartApiCommand(target, options, opts.extraStateProviders);
|
|
15637
15722
|
}));
|
|
15638
15723
|
[
|
|
@@ -18199,4 +18284,4 @@ function createLocalStartServiceCommand(opts = {}) {
|
|
|
18199
18284
|
|
|
18200
18285
|
//#endregion
|
|
18201
18286
|
export { LocalStateSourceError as a, rejectExplicitCfnStackWithMultipleStacks as c, CfnLocalStateProvider as d, createLocalInvokeCommand as i, resolveCfnRegion as l, createLocalRunTaskCommand as n, createLocalStateProvider as o, createLocalStartApiCommand as r, isCfnFlagPresent as s, createLocalStartServiceCommand as t, resolveCfnStackName as u };
|
|
18202
|
-
//# sourceMappingURL=local-start-service-
|
|
18287
|
+
//# sourceMappingURL=local-start-service-DDjMUt0E.js.map
|