@go-to-k/cdkd 0.168.0 → 0.169.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 +9 -2
- package/dist/cli.js +103 -13
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -190,10 +190,12 @@ cdkd drift MyStack --revert --yes # AWS ← state
|
|
|
190
190
|
# Asset / destroy / unlock
|
|
191
191
|
cdkd publish-assets # synth + upload only (typical CI split)
|
|
192
192
|
cdkd destroy MyStack
|
|
193
|
+
cdkd orphan MyStack/MyBucket # drop one resource from state (AWS resource stays)
|
|
193
194
|
cdkd force-unlock MyStack # clear stale lock from an interrupted deploy
|
|
194
195
|
|
|
195
|
-
#
|
|
196
|
-
cdkd import MyStack --yes
|
|
196
|
+
# Migrate between cdkd and CloudFormation
|
|
197
|
+
cdkd import MyStack --yes # adopt existing AWS resources into cdkd state
|
|
198
|
+
cdkd export MyStack # hand a cdkd-managed stack back to CloudFormation
|
|
197
199
|
|
|
198
200
|
# State-bucket-only commands (no CDK app needed)
|
|
199
201
|
cdkd state info # bucket name, region, schema version
|
|
@@ -264,6 +266,11 @@ bind-mounted at `/opt`.
|
|
|
264
266
|
cdkd local start-api # one HTTP server per discovered API
|
|
265
267
|
cdkd local start-api MyStack/MyHttpApi --watch # filter + hot reload
|
|
266
268
|
cdkd local start-api --from-state # OR --from-cfn-stack
|
|
269
|
+
|
|
270
|
+
# Typical shape — the bare `--from-cfn-stack` flag auto-resolves to the
|
|
271
|
+
# routed stack's name (here `MyStack`). Pass an explicit value only when
|
|
272
|
+
# the deployed CFn stack name differs from the CDK stack name.
|
|
273
|
+
cdkd local start-api MyStack/MyHttpApi --from-cfn-stack
|
|
267
274
|
```
|
|
268
275
|
|
|
269
276
|
REST v1 + HTTP API v2 + Function URL with all integration kinds
|
package/dist/cli.js
CHANGED
|
@@ -36475,6 +36475,21 @@ function readCdkPath(resource) {
|
|
|
36475
36475
|
return typeof v === "string" ? v : "";
|
|
36476
36476
|
}
|
|
36477
36477
|
/**
|
|
36478
|
+
* Same lookup as `readCdkPath`, but returns `undefined` instead of an
|
|
36479
|
+
* empty string when no `aws:cdk:path` metadata is present.
|
|
36480
|
+
*
|
|
36481
|
+
* Use this variant when the caller passes the value into APIs whose
|
|
36482
|
+
* contract distinguishes "no path known" from "empty path". For example,
|
|
36483
|
+
* `resolveEnvVars(logicalId, displayPath, ...)` short-circuits the
|
|
36484
|
+
* display-path lookup when `displayPath` is `undefined`, but an empty
|
|
36485
|
+
* string `''` would still hit the loop and could spuriously match a
|
|
36486
|
+
* malformed override key.
|
|
36487
|
+
*/
|
|
36488
|
+
function readCdkPathOrUndefined(resource) {
|
|
36489
|
+
const path = readCdkPath(resource);
|
|
36490
|
+
return path === "" ? void 0 : path;
|
|
36491
|
+
}
|
|
36492
|
+
/**
|
|
36478
36493
|
* Build a `Map<cdkPath, logicalId>` from a synthesized template.
|
|
36479
36494
|
*
|
|
36480
36495
|
* Used by `cdkd orphan <constructPath>` to translate user-supplied
|
|
@@ -43668,21 +43683,37 @@ function looksLikeAccessDenied(err) {
|
|
|
43668
43683
|
* @param logicalId The function's CloudFormation logical ID. Used
|
|
43669
43684
|
* to look up function-specific overrides in the
|
|
43670
43685
|
* `--env-vars` file.
|
|
43686
|
+
* @param displayPath The function's CDK display path
|
|
43687
|
+
* (`Metadata['aws:cdk:path']`, e.g.
|
|
43688
|
+
* `"MyStack/MyHandler"`), or `undefined` when
|
|
43689
|
+
* the resource has no path metadata. Display-path
|
|
43690
|
+
* keys in the override file are matched against
|
|
43691
|
+
* this value in addition to `logicalId`. Pass
|
|
43692
|
+
* `undefined` rather than the logical ID when no
|
|
43693
|
+
* path is known, so the override lookup does not
|
|
43694
|
+
* accidentally double-match the same key.
|
|
43671
43695
|
* @param templateEnv The function's `Properties.Environment.Variables`
|
|
43672
43696
|
* object from the synthesized template, or
|
|
43673
43697
|
* `undefined` when the function has no env vars.
|
|
43674
43698
|
* @param overrides Parsed `--env-vars` file contents, or
|
|
43675
43699
|
* `undefined` when the flag was not passed.
|
|
43676
43700
|
*/
|
|
43677
|
-
function resolveEnvVars(logicalId, templateEnv, overrides) {
|
|
43701
|
+
function resolveEnvVars(logicalId, displayPath, templateEnv, overrides) {
|
|
43678
43702
|
const resolved = {};
|
|
43679
43703
|
const unresolved = [];
|
|
43680
43704
|
if (templateEnv) for (const [key, value] of Object.entries(templateEnv)) if (isLiteralEnvValue(value)) resolved[key] = String(value);
|
|
43681
43705
|
else unresolved.push(key);
|
|
43682
43706
|
if (overrides) {
|
|
43683
43707
|
applyOverrideMap$1(resolved, overrides.Parameters);
|
|
43684
|
-
const
|
|
43685
|
-
|
|
43708
|
+
for (const [key, val] of Object.entries(overrides)) {
|
|
43709
|
+
if (key === "Parameters") continue;
|
|
43710
|
+
if (!val || typeof val !== "object") continue;
|
|
43711
|
+
if (key === logicalId) {
|
|
43712
|
+
applyOverrideMap$1(resolved, val);
|
|
43713
|
+
continue;
|
|
43714
|
+
}
|
|
43715
|
+
if (displayPath && (displayPath === key || displayPath.startsWith(`${key}/`))) applyOverrideMap$1(resolved, val);
|
|
43716
|
+
}
|
|
43686
43717
|
}
|
|
43687
43718
|
return {
|
|
43688
43719
|
resolved,
|
|
@@ -55108,6 +55139,7 @@ async function localStartApiCommand(target, options) {
|
|
|
55108
55139
|
const jwksWarnedUrls = /* @__PURE__ */ new Set();
|
|
55109
55140
|
let sigV4CredentialsLoader;
|
|
55110
55141
|
const sigV4WarnedForeignIds = /* @__PURE__ */ new Set();
|
|
55142
|
+
const fromCfnTipEmitted = { value: false };
|
|
55111
55143
|
/**
|
|
55112
55144
|
* One synth + discover + build pass. Returns the next-state
|
|
55113
55145
|
* material. Reused on initial boot AND every hot-reload firing.
|
|
@@ -55133,8 +55165,14 @@ async function localStartApiCommand(target, options) {
|
|
|
55133
55165
|
...options.profile && { macroExpandS3ClientOpts: { profile: options.profile } }
|
|
55134
55166
|
};
|
|
55135
55167
|
const { stacks } = await synthesizer.synthesize(synthOpts);
|
|
55136
|
-
const
|
|
55137
|
-
|
|
55168
|
+
const cfnStackFallback = typeof options.fromCfnStack === "string" ? options.fromCfnStack : void 0;
|
|
55169
|
+
const targetStackPrefix = target?.includes("/") === true ? target.slice(0, target.indexOf("/")) : void 0;
|
|
55170
|
+
const targetStacks = pickTargetStacks(stacks, options.stack, cfnStackFallback, targetStackPrefix);
|
|
55171
|
+
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.");
|
|
55172
|
+
const routedStackNames = targetStacks.map((s) => s.stackName);
|
|
55173
|
+
tryEmitFromCfnRedundancyTipOnce(options.fromCfnStack, routedStackNames, fromCfnTipEmitted, (routedStackName) => {
|
|
55174
|
+
logger.info(`tip: --from-cfn-stack value matches the routed stack name (${routedStackName}); you can omit the value: \`cdkd local start-api ... --from-cfn-stack\` (bare flag) resolves to the same value.`);
|
|
55175
|
+
});
|
|
55138
55176
|
const routes = discoverRoutes(targetStacks);
|
|
55139
55177
|
const wsDiscovery = discoverWebSocketApis(targetStacks);
|
|
55140
55178
|
if (wsDiscovery.errors.length > 0) for (const e of wsDiscovery.errors) logger.warn(`WebSocket discovery: ${e}`);
|
|
@@ -55509,12 +55547,60 @@ async function localStartApiCommand(target, options) {
|
|
|
55509
55547
|
* Match the `--stack` pattern (or single-stack auto-detect) to a list
|
|
55510
55548
|
* of stacks the route-discovery walks. Mirrors the deploy/diff matcher
|
|
55511
55549
|
* routing rules.
|
|
55550
|
+
*
|
|
55551
|
+
* @internal exported for unit tests.
|
|
55512
55552
|
*/
|
|
55513
|
-
function pickTargetStacks(stacks, pattern) {
|
|
55514
|
-
|
|
55553
|
+
function pickTargetStacks(stacks, pattern, cfnStackFallback, targetFallback) {
|
|
55554
|
+
const effective = pattern ?? cfnStackFallback ?? targetFallback;
|
|
55555
|
+
if (effective) return matchStacks(stacks, [effective]);
|
|
55515
55556
|
if (stacks.length === 1) return stacks;
|
|
55516
55557
|
if (stacks.length === 0) return [];
|
|
55517
|
-
throw new Error(`Multi-stack app: pass --stack <name> to pick a target. Available stacks: ${stacks.map((s) => s.stackName).join(", ")}.`);
|
|
55558
|
+
throw new Error(`Multi-stack app: pass --stack <name>, --from-cfn-stack <name>, or a stack-qualified target like "<StackName>/<construct>" to pick a target. Available stacks: ${stacks.map((s) => s.stackName).join(", ")}.`);
|
|
55559
|
+
}
|
|
55560
|
+
/**
|
|
55561
|
+
* Decide whether the `--from-cfn-stack <name>` redundancy tip should
|
|
55562
|
+
* fire for the current invocation. Fires only when:
|
|
55563
|
+
* - `fromCfnStack` is a non-empty STRING (explicit value, not bare `true`)
|
|
55564
|
+
* - exactly ONE stack is routed
|
|
55565
|
+
* - the explicit value equals the routed stack's `stackName`
|
|
55566
|
+
*
|
|
55567
|
+
* Extracted as a pure function so it can be unit-tested without booting
|
|
55568
|
+
* the full server. See improvement A in the start-api UX PR.
|
|
55569
|
+
*
|
|
55570
|
+
* @internal exported for unit tests.
|
|
55571
|
+
*/
|
|
55572
|
+
function shouldEmitFromCfnRedundancyTip(fromCfnStack, routedStackNames) {
|
|
55573
|
+
if (typeof fromCfnStack !== "string") return false;
|
|
55574
|
+
if (fromCfnStack.length === 0) return false;
|
|
55575
|
+
if (routedStackNames.length !== 1) return false;
|
|
55576
|
+
return fromCfnStack === routedStackNames[0];
|
|
55577
|
+
}
|
|
55578
|
+
/**
|
|
55579
|
+
* One-shot wrapper around `shouldEmitFromCfnRedundancyTip` for the
|
|
55580
|
+
* `--watch` hot-reload path. `synthesizeAndBuild` re-runs on every
|
|
55581
|
+
* reload firing, so without a gate the tip would re-emit on every
|
|
55582
|
+
* reload — noisy. This helper consults the caller-supplied ref:
|
|
55583
|
+
* - If the predicate fires AND the ref is still `false`, calls `emit`
|
|
55584
|
+
* and flips the ref to `true`.
|
|
55585
|
+
* - On subsequent invocations the ref is `true` and the helper is a
|
|
55586
|
+
* no-op for the rest of the ref's lifetime.
|
|
55587
|
+
* - When the predicate does NOT fire (no `--from-cfn-stack` value /
|
|
55588
|
+
* intentionally-different value / multi-stack run), the ref stays
|
|
55589
|
+
* `false` so a future reload whose synthesized stacks change in a
|
|
55590
|
+
* way that DOES make the value redundant still emits the tip once.
|
|
55591
|
+
*
|
|
55592
|
+
* The ref is owned by `localStartApiCommand` (one per server boot), so
|
|
55593
|
+
* independent server invocations get independent flags.
|
|
55594
|
+
*
|
|
55595
|
+
* @internal exported for unit tests.
|
|
55596
|
+
*/
|
|
55597
|
+
function tryEmitFromCfnRedundancyTipOnce(fromCfnStack, routedStackNames, emittedRef, emit) {
|
|
55598
|
+
if (emittedRef.value) return;
|
|
55599
|
+
if (!shouldEmitFromCfnRedundancyTip(fromCfnStack, routedStackNames)) return;
|
|
55600
|
+
const routedStackName = routedStackNames[0];
|
|
55601
|
+
if (routedStackName === void 0) return;
|
|
55602
|
+
emit(routedStackName);
|
|
55603
|
+
emittedRef.value = true;
|
|
55518
55604
|
}
|
|
55519
55605
|
/**
|
|
55520
55606
|
* Distinct, stable list of Lambda logical IDs reachable through any
|
|
@@ -55656,10 +55742,12 @@ async function buildContainerSpec(args) {
|
|
|
55656
55742
|
for (const key of audit.resolvedKeys) getLogger().debug(`Lambda ${logicalId}: --from-state substituted env var ${key}`);
|
|
55657
55743
|
for (const { key, reason } of audit.unresolved) getLogger().warn(`Lambda ${logicalId}: --from-state could not substitute env var ${key} (${reason}). Override it via --env-vars or it will be dropped.`);
|
|
55658
55744
|
}
|
|
55659
|
-
const
|
|
55745
|
+
const lambdaCdkPath = readCdkPathOrUndefined(lambda.resource);
|
|
55746
|
+
const envResult = resolveEnvVars(logicalId, lambdaCdkPath, templateEnv, overrides);
|
|
55660
55747
|
for (const key of envResult.unresolved) {
|
|
55661
55748
|
if (stateAudit && stateAudit.unresolved.some((u) => u.key === key)) continue;
|
|
55662
|
-
|
|
55749
|
+
const overrideKeyExample = lambdaCdkPath?.replace(/\/Resource$/, "") ?? logicalId;
|
|
55750
|
+
getLogger().warn(`Lambda ${logicalId}: env var ${key} contains a CloudFormation intrinsic and was dropped. Override it with --env-vars (e.g. {"${overrideKeyExample}":{"${key}":"<literal>"}}) or pass --from-state to recover deployed values.`);
|
|
55663
55751
|
}
|
|
55664
55752
|
const dockerEnv = {
|
|
55665
55753
|
AWS_LAMBDA_FUNCTION_NAME: logicalId,
|
|
@@ -59180,10 +59268,12 @@ async function localInvokeCommand(target, options) {
|
|
|
59180
59268
|
stateProvider.dispose();
|
|
59181
59269
|
}
|
|
59182
59270
|
const overrides = readEnvOverridesFile(options.envVars);
|
|
59183
|
-
const
|
|
59271
|
+
const lambdaCdkPath = readCdkPathOrUndefined(lambda.resource);
|
|
59272
|
+
const envResult = resolveEnvVars(lambda.logicalId, lambdaCdkPath, templateEnv, overrides);
|
|
59184
59273
|
for (const key of envResult.unresolved) {
|
|
59185
59274
|
if (stateAudit && stateAudit.unresolved.some((u) => u.key === key)) continue;
|
|
59186
|
-
|
|
59275
|
+
const overrideKeyExample = lambdaCdkPath?.replace(/\/Resource$/, "") ?? lambda.logicalId;
|
|
59276
|
+
logger.warn(`Environment variable ${key} contains a CloudFormation intrinsic and was dropped. Override it with --env-vars (e.g. {"${overrideKeyExample}":{"${key}":"<literal>"}}), or pass --from-state (cdkd-deployed) / --from-cfn-stack (cdk-deployed) to recover deployed values.`);
|
|
59187
59277
|
}
|
|
59188
59278
|
let resolvedAssumeRoleArn;
|
|
59189
59279
|
if (typeof options.assumeRole === "string") resolvedAssumeRoleArn = options.assumeRole;
|
|
@@ -60927,7 +61017,7 @@ function reorderArgs(argv) {
|
|
|
60927
61017
|
*/
|
|
60928
61018
|
async function main() {
|
|
60929
61019
|
const program = new Command();
|
|
60930
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
61020
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.169.0");
|
|
60931
61021
|
program.addCommand(createBootstrapCommand());
|
|
60932
61022
|
program.addCommand(createSynthCommand());
|
|
60933
61023
|
program.addCommand(createListCommand());
|