@go-to-k/cdkd 0.69.0 → 0.70.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/dist/cli.js CHANGED
@@ -4374,16 +4374,16 @@ var require_printer = __commonJS({
4374
4374
  },
4375
4375
  // Document
4376
4376
  Document: {
4377
- leave: (node) => join7(node.definitions, "\n\n")
4377
+ leave: (node) => join8(node.definitions, "\n\n")
4378
4378
  },
4379
4379
  OperationDefinition: {
4380
4380
  leave(node) {
4381
- const varDefs = hasMultilineItems(node.variableDefinitions) ? wrap("(\n", join7(node.variableDefinitions, "\n"), "\n)") : wrap("(", join7(node.variableDefinitions, ", "), ")");
4382
- const prefix = wrap("", node.description, "\n") + join7(
4381
+ const varDefs = hasMultilineItems(node.variableDefinitions) ? wrap("(\n", join8(node.variableDefinitions, "\n"), "\n)") : wrap("(", join8(node.variableDefinitions, ", "), ")");
4382
+ const prefix = wrap("", node.description, "\n") + join8(
4383
4383
  [
4384
4384
  node.operation,
4385
- join7([node.name, varDefs]),
4386
- join7(node.directives, " ")
4385
+ join8([node.name, varDefs]),
4386
+ join8(node.directives, " ")
4387
4387
  ],
4388
4388
  " "
4389
4389
  );
@@ -4391,7 +4391,7 @@ var require_printer = __commonJS({
4391
4391
  }
4392
4392
  },
4393
4393
  VariableDefinition: {
4394
- leave: ({ variable, type, defaultValue, directives, description }) => wrap("", description, "\n") + variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ", join7(directives, " "))
4394
+ leave: ({ variable, type, defaultValue, directives, description }) => wrap("", description, "\n") + variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ", join8(directives, " "))
4395
4395
  },
4396
4396
  SelectionSet: {
4397
4397
  leave: ({ selections }) => block(selections)
@@ -4399,11 +4399,11 @@ var require_printer = __commonJS({
4399
4399
  Field: {
4400
4400
  leave({ alias, name, arguments: args, directives, selectionSet }) {
4401
4401
  const prefix = wrap("", alias, ": ") + name;
4402
- let argsLine = prefix + wrap("(", join7(args, ", "), ")");
4402
+ let argsLine = prefix + wrap("(", join8(args, ", "), ")");
4403
4403
  if (argsLine.length > MAX_LINE_LENGTH) {
4404
- argsLine = prefix + wrap("(\n", indent(join7(args, "\n")), "\n)");
4404
+ argsLine = prefix + wrap("(\n", indent(join8(args, "\n")), "\n)");
4405
4405
  }
4406
- return join7([argsLine, join7(directives, " "), selectionSet], " ");
4406
+ return join8([argsLine, join8(directives, " "), selectionSet], " ");
4407
4407
  }
4408
4408
  },
4409
4409
  Argument: {
@@ -4411,14 +4411,14 @@ var require_printer = __commonJS({
4411
4411
  },
4412
4412
  // Fragments
4413
4413
  FragmentSpread: {
4414
- leave: ({ name, directives }) => "..." + name + wrap(" ", join7(directives, " "))
4414
+ leave: ({ name, directives }) => "..." + name + wrap(" ", join8(directives, " "))
4415
4415
  },
4416
4416
  InlineFragment: {
4417
- leave: ({ typeCondition, directives, selectionSet }) => join7(
4417
+ leave: ({ typeCondition, directives, selectionSet }) => join8(
4418
4418
  [
4419
4419
  "...",
4420
4420
  wrap("on ", typeCondition),
4421
- join7(directives, " "),
4421
+ join8(directives, " "),
4422
4422
  selectionSet
4423
4423
  ],
4424
4424
  " "
@@ -4434,7 +4434,7 @@ var require_printer = __commonJS({
4434
4434
  description
4435
4435
  }) => wrap("", description, "\n") + // Note: fragment variable definitions are experimental and may be changed
4436
4436
  // or removed in the future.
4437
- `fragment ${name}${wrap("(", join7(variableDefinitions, ", "), ")")} on ${typeCondition} ${wrap("", join7(directives, " "), " ")}` + selectionSet
4437
+ `fragment ${name}${wrap("(", join8(variableDefinitions, ", "), ")")} on ${typeCondition} ${wrap("", join8(directives, " "), " ")}` + selectionSet
4438
4438
  },
4439
4439
  // Value
4440
4440
  IntValue: {
@@ -4456,17 +4456,17 @@ var require_printer = __commonJS({
4456
4456
  leave: ({ value }) => value
4457
4457
  },
4458
4458
  ListValue: {
4459
- leave: ({ values }) => "[" + join7(values, ", ") + "]"
4459
+ leave: ({ values }) => "[" + join8(values, ", ") + "]"
4460
4460
  },
4461
4461
  ObjectValue: {
4462
- leave: ({ fields }) => "{" + join7(fields, ", ") + "}"
4462
+ leave: ({ fields }) => "{" + join8(fields, ", ") + "}"
4463
4463
  },
4464
4464
  ObjectField: {
4465
4465
  leave: ({ name, value }) => name + ": " + value
4466
4466
  },
4467
4467
  // Directive
4468
4468
  Directive: {
4469
- leave: ({ name, arguments: args }) => "@" + name + wrap("(", join7(args, ", "), ")")
4469
+ leave: ({ name, arguments: args }) => "@" + name + wrap("(", join8(args, ", "), ")")
4470
4470
  },
4471
4471
  // Type
4472
4472
  NamedType: {
@@ -4480,61 +4480,61 @@ var require_printer = __commonJS({
4480
4480
  },
4481
4481
  // Type System Definitions
4482
4482
  SchemaDefinition: {
4483
- leave: ({ description, directives, operationTypes }) => wrap("", description, "\n") + join7(["schema", join7(directives, " "), block(operationTypes)], " ")
4483
+ leave: ({ description, directives, operationTypes }) => wrap("", description, "\n") + join8(["schema", join8(directives, " "), block(operationTypes)], " ")
4484
4484
  },
4485
4485
  OperationTypeDefinition: {
4486
4486
  leave: ({ operation, type }) => operation + ": " + type
4487
4487
  },
4488
4488
  ScalarTypeDefinition: {
4489
- leave: ({ description, name, directives }) => wrap("", description, "\n") + join7(["scalar", name, join7(directives, " ")], " ")
4489
+ leave: ({ description, name, directives }) => wrap("", description, "\n") + join8(["scalar", name, join8(directives, " ")], " ")
4490
4490
  },
4491
4491
  ObjectTypeDefinition: {
4492
- leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join7(
4492
+ leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join8(
4493
4493
  [
4494
4494
  "type",
4495
4495
  name,
4496
- wrap("implements ", join7(interfaces, " & ")),
4497
- join7(directives, " "),
4496
+ wrap("implements ", join8(interfaces, " & ")),
4497
+ join8(directives, " "),
4498
4498
  block(fields)
4499
4499
  ],
4500
4500
  " "
4501
4501
  )
4502
4502
  },
4503
4503
  FieldDefinition: {
4504
- leave: ({ description, name, arguments: args, type, directives }) => wrap("", description, "\n") + name + (hasMultilineItems(args) ? wrap("(\n", indent(join7(args, "\n")), "\n)") : wrap("(", join7(args, ", "), ")")) + ": " + type + wrap(" ", join7(directives, " "))
4504
+ leave: ({ description, name, arguments: args, type, directives }) => wrap("", description, "\n") + name + (hasMultilineItems(args) ? wrap("(\n", indent(join8(args, "\n")), "\n)") : wrap("(", join8(args, ", "), ")")) + ": " + type + wrap(" ", join8(directives, " "))
4505
4505
  },
4506
4506
  InputValueDefinition: {
4507
- leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") + join7(
4508
- [name + ": " + type, wrap("= ", defaultValue), join7(directives, " ")],
4507
+ leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") + join8(
4508
+ [name + ": " + type, wrap("= ", defaultValue), join8(directives, " ")],
4509
4509
  " "
4510
4510
  )
4511
4511
  },
4512
4512
  InterfaceTypeDefinition: {
4513
- leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join7(
4513
+ leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join8(
4514
4514
  [
4515
4515
  "interface",
4516
4516
  name,
4517
- wrap("implements ", join7(interfaces, " & ")),
4518
- join7(directives, " "),
4517
+ wrap("implements ", join8(interfaces, " & ")),
4518
+ join8(directives, " "),
4519
4519
  block(fields)
4520
4520
  ],
4521
4521
  " "
4522
4522
  )
4523
4523
  },
4524
4524
  UnionTypeDefinition: {
4525
- leave: ({ description, name, directives, types }) => wrap("", description, "\n") + join7(
4526
- ["union", name, join7(directives, " "), wrap("= ", join7(types, " | "))],
4525
+ leave: ({ description, name, directives, types }) => wrap("", description, "\n") + join8(
4526
+ ["union", name, join8(directives, " "), wrap("= ", join8(types, " | "))],
4527
4527
  " "
4528
4528
  )
4529
4529
  },
4530
4530
  EnumTypeDefinition: {
4531
- leave: ({ description, name, directives, values }) => wrap("", description, "\n") + join7(["enum", name, join7(directives, " "), block(values)], " ")
4531
+ leave: ({ description, name, directives, values }) => wrap("", description, "\n") + join8(["enum", name, join8(directives, " "), block(values)], " ")
4532
4532
  },
4533
4533
  EnumValueDefinition: {
4534
- leave: ({ description, name, directives }) => wrap("", description, "\n") + join7([name, join7(directives, " ")], " ")
4534
+ leave: ({ description, name, directives }) => wrap("", description, "\n") + join8([name, join8(directives, " ")], " ")
4535
4535
  },
4536
4536
  InputObjectTypeDefinition: {
4537
- leave: ({ description, name, directives, fields }) => wrap("", description, "\n") + join7(["input", name, join7(directives, " "), block(fields)], " ")
4537
+ leave: ({ description, name, directives, fields }) => wrap("", description, "\n") + join8(["input", name, join8(directives, " "), block(fields)], " ")
4538
4538
  },
4539
4539
  DirectiveDefinition: {
4540
4540
  leave: ({
@@ -4544,84 +4544,84 @@ var require_printer = __commonJS({
4544
4544
  directives,
4545
4545
  repeatable,
4546
4546
  locations
4547
- }) => wrap("", description, "\n") + "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(join7(args, "\n")), "\n)") : wrap("(", join7(args, ", "), ")")) + wrap(" ", join7(directives, " ")) + (repeatable ? " repeatable" : "") + " on " + join7(locations, " | ")
4547
+ }) => wrap("", description, "\n") + "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(join8(args, "\n")), "\n)") : wrap("(", join8(args, ", "), ")")) + wrap(" ", join8(directives, " ")) + (repeatable ? " repeatable" : "") + " on " + join8(locations, " | ")
4548
4548
  },
4549
4549
  SchemaExtension: {
4550
- leave: ({ directives, operationTypes }) => join7(
4551
- ["extend schema", join7(directives, " "), block(operationTypes)],
4550
+ leave: ({ directives, operationTypes }) => join8(
4551
+ ["extend schema", join8(directives, " "), block(operationTypes)],
4552
4552
  " "
4553
4553
  )
4554
4554
  },
4555
4555
  ScalarTypeExtension: {
4556
- leave: ({ name, directives }) => join7(["extend scalar", name, join7(directives, " ")], " ")
4556
+ leave: ({ name, directives }) => join8(["extend scalar", name, join8(directives, " ")], " ")
4557
4557
  },
4558
4558
  ObjectTypeExtension: {
4559
- leave: ({ name, interfaces, directives, fields }) => join7(
4559
+ leave: ({ name, interfaces, directives, fields }) => join8(
4560
4560
  [
4561
4561
  "extend type",
4562
4562
  name,
4563
- wrap("implements ", join7(interfaces, " & ")),
4564
- join7(directives, " "),
4563
+ wrap("implements ", join8(interfaces, " & ")),
4564
+ join8(directives, " "),
4565
4565
  block(fields)
4566
4566
  ],
4567
4567
  " "
4568
4568
  )
4569
4569
  },
4570
4570
  InterfaceTypeExtension: {
4571
- leave: ({ name, interfaces, directives, fields }) => join7(
4571
+ leave: ({ name, interfaces, directives, fields }) => join8(
4572
4572
  [
4573
4573
  "extend interface",
4574
4574
  name,
4575
- wrap("implements ", join7(interfaces, " & ")),
4576
- join7(directives, " "),
4575
+ wrap("implements ", join8(interfaces, " & ")),
4576
+ join8(directives, " "),
4577
4577
  block(fields)
4578
4578
  ],
4579
4579
  " "
4580
4580
  )
4581
4581
  },
4582
4582
  UnionTypeExtension: {
4583
- leave: ({ name, directives, types }) => join7(
4583
+ leave: ({ name, directives, types }) => join8(
4584
4584
  [
4585
4585
  "extend union",
4586
4586
  name,
4587
- join7(directives, " "),
4588
- wrap("= ", join7(types, " | "))
4587
+ join8(directives, " "),
4588
+ wrap("= ", join8(types, " | "))
4589
4589
  ],
4590
4590
  " "
4591
4591
  )
4592
4592
  },
4593
4593
  EnumTypeExtension: {
4594
- leave: ({ name, directives, values }) => join7(["extend enum", name, join7(directives, " "), block(values)], " ")
4594
+ leave: ({ name, directives, values }) => join8(["extend enum", name, join8(directives, " "), block(values)], " ")
4595
4595
  },
4596
4596
  InputObjectTypeExtension: {
4597
- leave: ({ name, directives, fields }) => join7(["extend input", name, join7(directives, " "), block(fields)], " ")
4597
+ leave: ({ name, directives, fields }) => join8(["extend input", name, join8(directives, " "), block(fields)], " ")
4598
4598
  },
4599
4599
  DirectiveExtension: {
4600
- leave: ({ name, directives }) => join7(["extend directive @" + name, join7(directives, " ")], " ")
4600
+ leave: ({ name, directives }) => join8(["extend directive @" + name, join8(directives, " ")], " ")
4601
4601
  },
4602
4602
  // Schema Coordinates
4603
4603
  TypeCoordinate: {
4604
4604
  leave: ({ name }) => name
4605
4605
  },
4606
4606
  MemberCoordinate: {
4607
- leave: ({ name, memberName }) => join7([name, wrap(".", memberName)])
4607
+ leave: ({ name, memberName }) => join8([name, wrap(".", memberName)])
4608
4608
  },
4609
4609
  ArgumentCoordinate: {
4610
- leave: ({ name, fieldName, argumentName }) => join7([name, wrap(".", fieldName), wrap("(", argumentName, ":)")])
4610
+ leave: ({ name, fieldName, argumentName }) => join8([name, wrap(".", fieldName), wrap("(", argumentName, ":)")])
4611
4611
  },
4612
4612
  DirectiveCoordinate: {
4613
- leave: ({ name }) => join7(["@", name])
4613
+ leave: ({ name }) => join8(["@", name])
4614
4614
  },
4615
4615
  DirectiveArgumentCoordinate: {
4616
- leave: ({ name, argumentName }) => join7(["@", name, wrap("(", argumentName, ":)")])
4616
+ leave: ({ name, argumentName }) => join8(["@", name, wrap("(", argumentName, ":)")])
4617
4617
  }
4618
4618
  };
4619
- function join7(maybeArray, separator = "") {
4619
+ function join8(maybeArray, separator = "") {
4620
4620
  var _maybeArray$filter$jo;
4621
4621
  return (_maybeArray$filter$jo = maybeArray === null || maybeArray === void 0 ? void 0 : maybeArray.filter((x) => x).join(separator)) !== null && _maybeArray$filter$jo !== void 0 ? _maybeArray$filter$jo : "";
4622
4622
  }
4623
4623
  function block(array) {
4624
- return wrap("{\n", indent(join7(array, "\n")), "\n}");
4624
+ return wrap("{\n", indent(join8(array, "\n")), "\n}");
4625
4625
  }
4626
4626
  function wrap(start, maybeString, end = "") {
4627
4627
  return maybeString != null && maybeString !== "" ? start + maybeString + end : "";
@@ -18319,6 +18319,13 @@ var AssetError = class _AssetError extends CdkdError {
18319
18319
  Object.setPrototypeOf(this, _AssetError.prototype);
18320
18320
  }
18321
18321
  };
18322
+ var LocalInvokeBuildError = class _LocalInvokeBuildError extends CdkdError {
18323
+ constructor(message, cause) {
18324
+ super(message, "LOCAL_INVOKE_BUILD_ERROR", cause);
18325
+ this.name = "LocalInvokeBuildError";
18326
+ Object.setPrototypeOf(this, _LocalInvokeBuildError.prototype);
18327
+ }
18328
+ };
18322
18329
  var ProvisioningError = class _ProvisioningError extends CdkdError {
18323
18330
  constructor(message, resourceType, logicalId, physicalId, cause) {
18324
18331
  super(message, "PROVISIONING_ERROR", cause);
@@ -23436,11 +23443,11 @@ async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
23436
23443
  return syncResult;
23437
23444
  const logger = getLogger();
23438
23445
  logger.debug("No state bucket specified, resolving default from account...");
23439
- const { GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
23446
+ const { GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
23440
23447
  const { S3Client: S3Client12 } = await import("@aws-sdk/client-s3");
23441
23448
  const { getAwsClients: getAwsClients2 } = await Promise.resolve().then(() => (init_aws_clients(), aws_clients_exports));
23442
23449
  const awsClients = getAwsClients2();
23443
- const identity = await awsClients.sts.send(new GetCallerIdentityCommand11({}));
23450
+ const identity = await awsClients.sts.send(new GetCallerIdentityCommand12({}));
23444
23451
  const accountId = identity.Account;
23445
23452
  const newName = getDefaultStateBucketName(accountId);
23446
23453
  const legacyName = getLegacyStateBucketName(accountId, region);
@@ -25322,14 +25329,57 @@ var FileAssetPublisher = class {
25322
25329
  };
25323
25330
 
25324
25331
  // src/assets/docker-asset-publisher.ts
25325
- import { execFile, spawn as spawn2 } from "node:child_process";
25326
- import { promisify } from "node:util";
25332
+ import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
25333
+ import { promisify as promisify2 } from "node:util";
25327
25334
  import {
25328
25335
  ECRClient,
25329
25336
  GetAuthorizationTokenCommand,
25330
25337
  DescribeImagesCommand as DescribeImagesCommand2
25331
25338
  } from "@aws-sdk/client-ecr";
25339
+
25340
+ // src/assets/docker-build.ts
25341
+ import { execFile } from "node:child_process";
25342
+ import { promisify } from "node:util";
25332
25343
  var execFileAsync = promisify(execFile);
25344
+ async function buildDockerImage(asset, cdkOutDir, tag, options) {
25345
+ const logger = getLogger().child("docker-build");
25346
+ const args = ["build", "-t", tag];
25347
+ if (options.platform) {
25348
+ args.push("--platform", options.platform);
25349
+ }
25350
+ if (asset.source.dockerFile) {
25351
+ args.push("-f", asset.source.dockerFile);
25352
+ }
25353
+ if (asset.source.dockerBuildArgs) {
25354
+ for (const [key, value] of Object.entries(asset.source.dockerBuildArgs)) {
25355
+ args.push("--build-arg", `${key}=${value}`);
25356
+ }
25357
+ }
25358
+ if (asset.source.dockerBuildTarget) {
25359
+ args.push("--target", asset.source.dockerBuildTarget);
25360
+ }
25361
+ if (asset.source.dockerOutputs) {
25362
+ for (const output of asset.source.dockerOutputs) {
25363
+ args.push("--output", output);
25364
+ }
25365
+ }
25366
+ const contextDir = `${cdkOutDir}/${asset.source.directory}`;
25367
+ args.push(contextDir);
25368
+ logger.debug(`docker ${args.join(" ")}`);
25369
+ try {
25370
+ await execFileAsync("docker", args, {
25371
+ maxBuffer: 50 * 1024 * 1024
25372
+ // 50MB for build output
25373
+ });
25374
+ } catch (error) {
25375
+ const err = error;
25376
+ const stderr = err.stderr || err.message || String(error);
25377
+ throw options.wrapError(stderr);
25378
+ }
25379
+ }
25380
+
25381
+ // src/assets/docker-asset-publisher.ts
25382
+ var execFileAsync2 = promisify2(execFile2);
25333
25383
  var DockerAssetPublisher = class {
25334
25384
  logger = getLogger().child("DockerAssetPublisher");
25335
25385
  /**
@@ -25412,38 +25462,17 @@ var DockerAssetPublisher = class {
25412
25462
  }
25413
25463
  }
25414
25464
  /**
25415
- * Build Docker image
25465
+ * Build Docker image — delegates to the shared `buildDockerImage`
25466
+ * helper so this code path stays in sync with `cdkd local invoke`'s
25467
+ * container-Lambda build path. `--platform` is currently not threaded
25468
+ * through here (publish-assets has no Architectures hint to consult);
25469
+ * a follow-up can lift this once the asset manifest carries a
25470
+ * platform field.
25416
25471
  */
25417
25472
  async buildImage(asset, cdkOutputDir, tag) {
25418
- const args = ["build", "-t", tag];
25419
- if (asset.source.dockerFile) {
25420
- args.push("-f", asset.source.dockerFile);
25421
- }
25422
- if (asset.source.dockerBuildArgs) {
25423
- for (const [key, value] of Object.entries(asset.source.dockerBuildArgs)) {
25424
- args.push("--build-arg", `${key}=${value}`);
25425
- }
25426
- }
25427
- if (asset.source.dockerBuildTarget) {
25428
- args.push("--target", asset.source.dockerBuildTarget);
25429
- }
25430
- if (asset.source.dockerOutputs) {
25431
- for (const output of asset.source.dockerOutputs) {
25432
- args.push("--output", output);
25433
- }
25434
- }
25435
- const contextDir = `${cdkOutputDir}/${asset.source.directory}`;
25436
- args.push(contextDir);
25437
- this.logger.debug(`docker ${args.join(" ")}`);
25438
- try {
25439
- await execFileAsync("docker", args, {
25440
- maxBuffer: 50 * 1024 * 1024
25441
- // 50MB for build output
25442
- });
25443
- } catch (error) {
25444
- const err = error;
25445
- throw new AssetError(`Docker build failed: ${err.stderr || err.message || String(error)}`);
25446
- }
25473
+ await buildDockerImage(asset, cdkOutputDir, tag, {
25474
+ wrapError: (stderr) => new AssetError(`Docker build failed: ${stderr}`)
25475
+ });
25447
25476
  }
25448
25477
  /**
25449
25478
  * Authenticate with ECR
@@ -25487,7 +25516,7 @@ var DockerAssetPublisher = class {
25487
25516
  * Tag Docker image
25488
25517
  */
25489
25518
  async tagImage(source, target) {
25490
- await execFileAsync("docker", ["tag", source, target]);
25519
+ await execFileAsync2("docker", ["tag", source, target]);
25491
25520
  }
25492
25521
  /**
25493
25522
  * Push Docker image
@@ -25495,7 +25524,7 @@ var DockerAssetPublisher = class {
25495
25524
  async pushImage(uri) {
25496
25525
  this.logger.debug(`Pushing: ${uri}`);
25497
25526
  try {
25498
- await execFileAsync("docker", ["push", uri], {
25527
+ await execFileAsync2("docker", ["push", uri], {
25499
25528
  maxBuffer: 50 * 1024 * 1024
25500
25529
  });
25501
25530
  } catch (error) {
@@ -25718,9 +25747,9 @@ var AssetPublisher = class {
25718
25747
  const region = options.region || process.env["AWS_REGION"] || "us-east-1";
25719
25748
  let accountId = options.accountId;
25720
25749
  if (!accountId) {
25721
- const { STSClient: STSClient10, GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
25722
- const stsClient = new STSClient10({ region });
25723
- const identity = await stsClient.send(new GetCallerIdentityCommand11({}));
25750
+ const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
25751
+ const stsClient = new STSClient11({ region });
25752
+ const identity = await stsClient.send(new GetCallerIdentityCommand12({}));
25724
25753
  accountId = identity.Account;
25725
25754
  stsClient.destroy();
25726
25755
  }
@@ -65303,11 +65332,11 @@ async function deployCommand(stacks, options) {
65303
65332
  addDependencies(stack.stackName);
65304
65333
  }
65305
65334
  }
65306
- const { STSClient: STSClient10, GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
65307
- const stsClient = new STSClient10({
65335
+ const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
65336
+ const stsClient = new STSClient11({
65308
65337
  region: options.region || process.env["AWS_REGION"] || "us-east-1"
65309
65338
  });
65310
- const callerIdentity = await stsClient.send(new GetCallerIdentityCommand11({}));
65339
+ const callerIdentity = await stsClient.send(new GetCallerIdentityCommand12({}));
65311
65340
  const accountId = callerIdentity.Account;
65312
65341
  stsClient.destroy();
65313
65342
  const assetPublisher = new AssetPublisher();
@@ -67780,9 +67809,9 @@ async function publishAssetsCommand(stacks, options) {
67780
67809
  );
67781
67810
  }
67782
67811
  const baseRegion = options.region || process.env["AWS_REGION"] || "us-east-1";
67783
- const { STSClient: STSClient10, GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
67784
- const stsClient = new STSClient10({ region: baseRegion });
67785
- const callerIdentity = await stsClient.send(new GetCallerIdentityCommand11({}));
67812
+ const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
67813
+ const stsClient = new STSClient11({ region: baseRegion });
67814
+ const callerIdentity = await stsClient.send(new GetCallerIdentityCommand12({}));
67786
67815
  const accountId = callerIdentity.Account;
67787
67816
  stsClient.destroy();
67788
67817
  const assetPublisher = new AssetPublisher();
@@ -69963,12 +69992,13 @@ async function captureObservedForImportedResources(stackState, providerRegistry,
69963
69992
  }
69964
69993
 
69965
69994
  // src/cli/commands/local-invoke.ts
69966
- import { mkdtempSync as mkdtempSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
69995
+ import { mkdtempSync as mkdtempSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
69967
69996
  import { tmpdir as tmpdir2 } from "node:os";
69997
+ import { dirname as dirname2 } from "node:path";
69968
69998
  import * as path from "node:path";
69969
69999
  import { Command as Command14, Option as Option7 } from "commander";
69970
70000
 
69971
- // src/local-invoke/lambda-resolver.ts
70001
+ // src/local/lambda-resolver.ts
69972
70002
  import { existsSync as existsSync4, statSync as statSync3 } from "node:fs";
69973
70003
  import { dirname, isAbsolute, resolve as resolve4 } from "node:path";
69974
70004
  var LocalInvokeResolutionError = class _LocalInvokeResolutionError extends Error {
@@ -70067,25 +70097,38 @@ function pickStack(parsed, stacks) {
70067
70097
  }
70068
70098
  function extractLambdaProperties(stack, logicalId, resource) {
70069
70099
  const props = resource.Properties ?? {};
70070
- const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
70071
- const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
70072
70100
  const memoryMb = typeof props["MemorySize"] === "number" ? props["MemorySize"] : 128;
70073
70101
  const timeoutSec = typeof props["Timeout"] === "number" ? props["Timeout"] : 3;
70102
+ const code = props["Code"] ?? {};
70103
+ const imageUri = extractImageUri(code["ImageUri"]);
70104
+ if (imageUri !== void 0) {
70105
+ return extractImageLambdaProperties({
70106
+ stack,
70107
+ logicalId,
70108
+ resource,
70109
+ memoryMb,
70110
+ timeoutSec,
70111
+ props,
70112
+ imageUri
70113
+ });
70114
+ }
70115
+ const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
70116
+ const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
70074
70117
  if (!runtime) {
70075
70118
  throw new LocalInvokeResolutionError(
70076
- `Lambda '${logicalId}' has no Runtime property. Container-image Lambdas (Code.ImageUri) are not supported in cdkd local invoke v1.`
70119
+ `Lambda '${logicalId}' has no Runtime property and no Code.ImageUri. cdkd cannot tell if this is a ZIP or a container Lambda.`
70077
70120
  );
70078
70121
  }
70079
70122
  if (!handler) {
70080
70123
  throw new LocalInvokeResolutionError(`Lambda '${logicalId}' has no Handler property.`);
70081
70124
  }
70082
- const code = props["Code"] ?? {};
70083
70125
  const inlineCode = typeof code["ZipFile"] === "string" ? code["ZipFile"] : void 0;
70084
70126
  let codePath = null;
70085
70127
  if (!inlineCode) {
70086
70128
  codePath = resolveAssetCodePath(stack, logicalId, resource);
70087
70129
  }
70088
70130
  return {
70131
+ kind: "zip",
70089
70132
  stack,
70090
70133
  logicalId,
70091
70134
  resource,
@@ -70097,6 +70140,62 @@ function extractLambdaProperties(stack, logicalId, resource) {
70097
70140
  ...inlineCode !== void 0 && { inlineCode }
70098
70141
  };
70099
70142
  }
70143
+ function extractImageUri(value) {
70144
+ if (typeof value === "string" && value.length > 0)
70145
+ return value;
70146
+ if (value && typeof value === "object" && !Array.isArray(value)) {
70147
+ const obj = value;
70148
+ const sub = obj["Fn::Sub"];
70149
+ if (typeof sub === "string" && sub.length > 0)
70150
+ return sub;
70151
+ if (Array.isArray(sub) && typeof sub[0] === "string")
70152
+ return sub[0];
70153
+ }
70154
+ return void 0;
70155
+ }
70156
+ function extractImageLambdaProperties(args) {
70157
+ const { stack, logicalId, resource, memoryMb, timeoutSec, props, imageUri } = args;
70158
+ const rawImageConfig = props["ImageConfig"] ?? {};
70159
+ const imageConfig = {};
70160
+ if (Array.isArray(rawImageConfig["Command"])) {
70161
+ imageConfig.command = rawImageConfig["Command"].filter(
70162
+ (s) => typeof s === "string"
70163
+ );
70164
+ }
70165
+ if (Array.isArray(rawImageConfig["EntryPoint"])) {
70166
+ imageConfig.entryPoint = rawImageConfig["EntryPoint"].filter(
70167
+ (s) => typeof s === "string"
70168
+ );
70169
+ }
70170
+ if (typeof rawImageConfig["WorkingDirectory"] === "string") {
70171
+ imageConfig.workingDirectory = rawImageConfig["WorkingDirectory"];
70172
+ }
70173
+ const arches = props["Architectures"];
70174
+ let architecture = "x86_64";
70175
+ if (Array.isArray(arches) && arches.length > 0) {
70176
+ const first = arches[0];
70177
+ if (first === "arm64")
70178
+ architecture = "arm64";
70179
+ else if (first === "x86_64")
70180
+ architecture = "x86_64";
70181
+ else {
70182
+ throw new LocalInvokeResolutionError(
70183
+ `Lambda '${logicalId}' has unsupported Architectures value '${String(first)}'. cdkd local invoke supports x86_64 and arm64.`
70184
+ );
70185
+ }
70186
+ }
70187
+ return {
70188
+ kind: "image",
70189
+ stack,
70190
+ logicalId,
70191
+ resource,
70192
+ memoryMb,
70193
+ timeoutSec,
70194
+ imageUri,
70195
+ imageConfig,
70196
+ architecture
70197
+ };
70198
+ }
70100
70199
  function resolveAssetCodePath(stack, logicalId, resource) {
70101
70200
  const meta = resource.Metadata;
70102
70201
  const assetPath = meta?.["aws:asset:path"];
@@ -70140,7 +70239,7 @@ function notFoundError(target, stack, resources) {
70140
70239
  return new LocalInvokeResolutionError(msg.trimEnd());
70141
70240
  }
70142
70241
 
70143
- // src/local-invoke/env-resolver.ts
70242
+ // src/local/env-resolver.ts
70144
70243
  function resolveEnvVars(logicalId, templateEnv, overrides) {
70145
70244
  const resolved = {};
70146
70245
  const unresolved = [];
@@ -70177,7 +70276,7 @@ function isLiteralEnvValue(value) {
70177
70276
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
70178
70277
  }
70179
70278
 
70180
- // src/local-invoke/state-resolver.ts
70279
+ // src/local/state-resolver.ts
70181
70280
  function substituteAgainstState(value, resources) {
70182
70281
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
70183
70282
  return { kind: "literal", value };
@@ -70354,7 +70453,7 @@ function substituteEnvVarsFromState(templateEnv, resources) {
70354
70453
  return { env, audit };
70355
70454
  }
70356
70455
 
70357
- // src/local-invoke/runtime-image.ts
70456
+ // src/local/runtime-image.ts
70358
70457
  var SUPPORTED_RUNTIMES = {
70359
70458
  "nodejs18.x": { image: "public.ecr.aws/lambda/nodejs:18", fileExtension: ".js" },
70360
70459
  "nodejs20.x": { image: "public.ecr.aws/lambda/nodejs:20", fileExtension: ".js" },
@@ -70381,7 +70480,7 @@ function resolveRuntimeSpec(runtime) {
70381
70480
  if (typeof runtime !== "string" || runtime.length === 0) {
70382
70481
  throw new UnsupportedRuntimeError(
70383
70482
  String(runtime),
70384
- "Lambda function has no Runtime property. Container-image Lambdas (Code.ImageUri) are not supported in cdkd local invoke v1."
70483
+ "Lambda function has no Runtime property. This branch is only reached for ZIP Lambdas; container-image Lambdas (Code.ImageUri) take a different code path that does not consult the Runtime property."
70385
70484
  );
70386
70485
  }
70387
70486
  const spec = SUPPORTED_RUNTIMES[runtime];
@@ -70399,11 +70498,11 @@ function resolveRuntimeSpec(runtime) {
70399
70498
  );
70400
70499
  }
70401
70500
 
70402
- // src/local-invoke/docker-runner.ts
70403
- import { execFile as execFile2, spawn as spawn3 } from "node:child_process";
70501
+ // src/local/docker-runner.ts
70502
+ import { execFile as execFile3, spawn as spawn3 } from "node:child_process";
70404
70503
  import { createServer } from "node:net";
70405
- import { promisify as promisify2 } from "node:util";
70406
- var execFileAsync2 = promisify2(execFile2);
70504
+ import { promisify as promisify3 } from "node:util";
70505
+ var execFileAsync3 = promisify3(execFile3);
70407
70506
  var DockerRunnerError = class _DockerRunnerError extends Error {
70408
70507
  constructor(message) {
70409
70508
  super(message);
@@ -70422,6 +70521,12 @@ async function pullImage(image, skipPull) {
70422
70521
  }
70423
70522
  async function runDetached(opts) {
70424
70523
  const args = ["run", "-d", "--rm"];
70524
+ if (opts.name) {
70525
+ args.push("--name", opts.name);
70526
+ }
70527
+ if (opts.platform) {
70528
+ args.push("--platform", opts.platform);
70529
+ }
70425
70530
  const host = opts.host ?? "127.0.0.1";
70426
70531
  args.push("-p", `${host}:${opts.hostPort}:8080`);
70427
70532
  if (opts.debugPort !== void 0) {
@@ -70434,11 +70539,19 @@ async function runDetached(opts) {
70434
70539
  for (const [k, v] of Object.entries(opts.env)) {
70435
70540
  args.push("-e", `${k}=${v}`);
70436
70541
  }
70437
- args.push(opts.image, ...opts.cmd);
70542
+ if (opts.workingDir) {
70543
+ args.push("--workdir", opts.workingDir);
70544
+ }
70545
+ let entryPointTail = [];
70546
+ if (opts.entryPoint && opts.entryPoint.length > 0) {
70547
+ args.push("--entrypoint", opts.entryPoint[0]);
70548
+ entryPointTail = opts.entryPoint.slice(1);
70549
+ }
70550
+ args.push(opts.image, ...entryPointTail, ...opts.cmd);
70438
70551
  const logger = getLogger().child("docker");
70439
- logger.debug(`docker ${args.join(" ")}`);
70552
+ logger.debug(`docker ${redactAwsCredentialsInArgs(args).join(" ")}`);
70440
70553
  try {
70441
- const { stdout } = await execFileAsync2("docker", args, {
70554
+ const { stdout } = await execFileAsync3("docker", args, {
70442
70555
  maxBuffer: 10 * 1024 * 1024
70443
70556
  });
70444
70557
  return stdout.trim();
@@ -70467,7 +70580,7 @@ async function removeContainer(containerId) {
70467
70580
  return;
70468
70581
  const logger = getLogger().child("docker");
70469
70582
  try {
70470
- await execFileAsync2("docker", ["rm", "-f", containerId]);
70583
+ await execFileAsync3("docker", ["rm", "-f", containerId]);
70471
70584
  logger.debug(`Removed container ${containerId}`);
70472
70585
  } catch (error) {
70473
70586
  const err = error;
@@ -70478,7 +70591,7 @@ async function removeContainer(containerId) {
70478
70591
  }
70479
70592
  async function ensureDockerAvailable() {
70480
70593
  try {
70481
- await execFileAsync2("docker", ["version", "--format", "{{.Server.Version}}"]);
70594
+ await execFileAsync3("docker", ["version", "--format", "{{.Server.Version}}"]);
70482
70595
  } catch (error) {
70483
70596
  const err = error;
70484
70597
  if (err.code === "ENOENT") {
@@ -70508,6 +70621,31 @@ function pickFreePort() {
70508
70621
  });
70509
70622
  });
70510
70623
  }
70624
+ var REDACTED_ENV_KEYS = /* @__PURE__ */ new Set([
70625
+ "AWS_ACCESS_KEY_ID",
70626
+ "AWS_SECRET_ACCESS_KEY",
70627
+ "AWS_SESSION_TOKEN"
70628
+ ]);
70629
+ function redactAwsCredentialsInArgs(args) {
70630
+ const out = [];
70631
+ for (let i = 0; i < args.length; i++) {
70632
+ const cur = args[i];
70633
+ const next = args[i + 1];
70634
+ if (cur === "-e" && typeof next === "string") {
70635
+ const eqIdx = next.indexOf("=");
70636
+ if (eqIdx > 0) {
70637
+ const key = next.substring(0, eqIdx);
70638
+ if (REDACTED_ENV_KEYS.has(key)) {
70639
+ out.push("-e", `${key}=***`);
70640
+ i++;
70641
+ continue;
70642
+ }
70643
+ }
70644
+ }
70645
+ out.push(cur);
70646
+ }
70647
+ return out;
70648
+ }
70511
70649
  function runForeground(cmd, args) {
70512
70650
  return new Promise((resolveProc, rejectProc) => {
70513
70651
  const proc = spawn3(cmd, args, { stdio: "inherit" });
@@ -70521,7 +70659,164 @@ function runForeground(cmd, args) {
70521
70659
  });
70522
70660
  }
70523
70661
 
70524
- // src/local-invoke/rie-client.ts
70662
+ // src/local/docker-image-builder.ts
70663
+ import { createHash as createHash2 } from "node:crypto";
70664
+ async function buildContainerImage(asset, cdkOutDir, options) {
70665
+ const tag = computeLocalTag(asset.source);
70666
+ const platform = architectureToPlatform(options.architecture);
70667
+ const logger = getLogger().child("local-invoke-build");
70668
+ logger.info(`Building container image (platform=${platform})...`);
70669
+ logger.debug(`Local tag: ${tag}`);
70670
+ await buildDockerImage(asset, cdkOutDir, tag, {
70671
+ platform,
70672
+ wrapError: (stderr) => new LocalInvokeBuildError(
70673
+ `docker build failed for container Lambda asset (${asset.source.directory}): ${stderr}`
70674
+ )
70675
+ });
70676
+ return tag;
70677
+ }
70678
+ function architectureToPlatform(architecture) {
70679
+ return architecture === "arm64" ? "linux/arm64" : "linux/amd64";
70680
+ }
70681
+ function computeLocalTag(source) {
70682
+ const hash = createHash2("sha256");
70683
+ hash.update(source.directory);
70684
+ hash.update("\0");
70685
+ hash.update(source.dockerFile ?? "");
70686
+ hash.update("\0");
70687
+ hash.update(source.dockerBuildTarget ?? "");
70688
+ hash.update("\0");
70689
+ if (source.dockerBuildArgs) {
70690
+ for (const [k, v] of Object.entries(source.dockerBuildArgs)) {
70691
+ hash.update(k);
70692
+ hash.update("=");
70693
+ hash.update(v);
70694
+ hash.update("\0");
70695
+ }
70696
+ }
70697
+ return `cdkd-local-invoke-${hash.digest("hex").slice(0, 16)}`;
70698
+ }
70699
+
70700
+ // src/local/ecr-puller.ts
70701
+ import { execFile as execFile4, spawn as spawn4 } from "node:child_process";
70702
+ import { promisify as promisify4 } from "node:util";
70703
+ import { ECRClient as ECRClient3, GetAuthorizationTokenCommand as GetAuthorizationTokenCommand2 } from "@aws-sdk/client-ecr";
70704
+ import { GetCallerIdentityCommand as GetCallerIdentityCommand11, STSClient as STSClient10 } from "@aws-sdk/client-sts";
70705
+ var execFileAsync4 = promisify4(execFile4);
70706
+ var ECR_URI_REGEX = /^(\d{12})\.dkr\.ecr\.([^.]+)\.amazonaws\.com(?:\.cn)?\/([^:]+):(.+)$/;
70707
+ function parseEcrUri(imageUri) {
70708
+ const m = ECR_URI_REGEX.exec(imageUri);
70709
+ if (!m)
70710
+ return void 0;
70711
+ return {
70712
+ accountId: m[1],
70713
+ region: m[2],
70714
+ repository: m[3],
70715
+ tag: m[4]
70716
+ };
70717
+ }
70718
+ async function pullEcrImage(imageUri, options) {
70719
+ const logger = getLogger().child("ecr-puller");
70720
+ const parsed = parseEcrUri(imageUri);
70721
+ if (!parsed) {
70722
+ throw new LocalInvokeBuildError(
70723
+ `Image URI '${imageUri}' is not an ECR URI. cdkd local invoke v1 only authenticates against ECR for the deployed-image fallback path.`
70724
+ );
70725
+ }
70726
+ const sts = new STSClient10({ region: parsed.region });
70727
+ let callerAccount;
70728
+ try {
70729
+ const identity = await sts.send(new GetCallerIdentityCommand11({}));
70730
+ if (!identity.Account) {
70731
+ throw new LocalInvokeBuildError(
70732
+ "STS GetCallerIdentity returned no Account. Verify your AWS credentials."
70733
+ );
70734
+ }
70735
+ callerAccount = identity.Account;
70736
+ } finally {
70737
+ sts.destroy();
70738
+ }
70739
+ if (callerAccount !== parsed.accountId) {
70740
+ throw new LocalInvokeBuildError(
70741
+ `Image URI '${imageUri}' is in account ${parsed.accountId}, but the caller is ${callerAccount}. Cross-account ECR pull is not supported in cdkd local invoke v1 \u2014 deferred to a follow-up PR. Workaround: assume a role in the target account before invoking, or build the image locally with \`cdkd local invoke -a cdk.out\` (no ECR pull).`
70742
+ );
70743
+ }
70744
+ const callerRegion = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"];
70745
+ if (callerRegion && callerRegion !== parsed.region) {
70746
+ throw new LocalInvokeBuildError(
70747
+ `Image URI '${imageUri}' is in region ${parsed.region}, but the caller's region is ${callerRegion}. Cross-region ECR pull is not supported in cdkd local invoke v1 \u2014 deferred to a follow-up PR. Workaround: re-run with AWS_REGION=${parsed.region} set, or build the image locally with -a cdk.out.`
70748
+ );
70749
+ }
70750
+ if (options.skipPull) {
70751
+ logger.info(`Skipping ECR pull (--no-pull). Verifying ${imageUri} is in local cache...`);
70752
+ await verifyImageInLocalCache(imageUri);
70753
+ return imageUri;
70754
+ }
70755
+ const ecr = new ECRClient3({ region: parsed.region });
70756
+ try {
70757
+ await ecrLogin(ecr, parsed.accountId, parsed.region);
70758
+ } finally {
70759
+ ecr.destroy();
70760
+ }
70761
+ logger.info(`Pulling ${imageUri}...`);
70762
+ await runForeground2("docker", ["pull", imageUri]);
70763
+ return imageUri;
70764
+ }
70765
+ async function ecrLogin(client, accountId, region) {
70766
+ const logger = getLogger().child("ecr-puller");
70767
+ logger.debug(`ECR login (account=${accountId}, region=${region})`);
70768
+ const response = await client.send(new GetAuthorizationTokenCommand2({}));
70769
+ const authData = response.authorizationData?.[0];
70770
+ if (!authData?.authorizationToken) {
70771
+ throw new LocalInvokeBuildError("Failed to get ECR authorization token");
70772
+ }
70773
+ const token = Buffer.from(authData.authorizationToken, "base64").toString();
70774
+ const [username, password] = token.split(":");
70775
+ const endpoint = authData.proxyEndpoint || `https://${accountId}.dkr.ecr.${region}.amazonaws.com`;
70776
+ await new Promise((resolve5, reject) => {
70777
+ const proc = spawn4("docker", ["login", "--username", username, "--password-stdin", endpoint], {
70778
+ stdio: ["pipe", "pipe", "pipe"]
70779
+ });
70780
+ let stderr = "";
70781
+ proc.stderr?.on("data", (data) => {
70782
+ stderr += data.toString();
70783
+ });
70784
+ proc.on("close", (code) => {
70785
+ if (code === 0)
70786
+ resolve5();
70787
+ else
70788
+ reject(new LocalInvokeBuildError(`ECR login failed: ${stderr.trim()}`));
70789
+ });
70790
+ proc.on("error", (err) => {
70791
+ reject(new LocalInvokeBuildError(`ECR login failed: ${err.message}`));
70792
+ });
70793
+ proc.stdin?.write(password);
70794
+ proc.stdin?.end();
70795
+ });
70796
+ }
70797
+ async function verifyImageInLocalCache(imageUri) {
70798
+ try {
70799
+ await execFileAsync4("docker", ["image", "inspect", imageUri]);
70800
+ } catch {
70801
+ throw new LocalInvokeBuildError(
70802
+ `Image '${imageUri}' is not in the local docker cache and --no-pull was set. Either remove --no-pull (cdkd will pull from ECR) or pre-pull the image manually with \`docker pull\`.`
70803
+ );
70804
+ }
70805
+ }
70806
+ function runForeground2(cmd, args) {
70807
+ return new Promise((resolve5, reject) => {
70808
+ const proc = spawn4(cmd, args, { stdio: "inherit" });
70809
+ proc.on("error", (err) => reject(new LocalInvokeBuildError(`${cmd} failed: ${err.message}`)));
70810
+ proc.on("close", (code) => {
70811
+ if (code === 0)
70812
+ resolve5();
70813
+ else
70814
+ reject(new LocalInvokeBuildError(`${cmd} exited with code ${code}`));
70815
+ });
70816
+ });
70817
+ }
70818
+
70819
+ // src/local/rie-client.ts
70525
70820
  import { setTimeout as delay } from "node:timers/promises";
70526
70821
  var INVOKE_PATH = "/2015-03-31/functions/function/invocations";
70527
70822
  async function waitForRieReady(host, port, timeoutMs = 5e3) {
@@ -70630,6 +70925,104 @@ async function fetchWithStartupRetry(url, body, signal) {
70630
70925
  throw lastError;
70631
70926
  }
70632
70927
 
70928
+ // src/assets/asset-manifest-loader.ts
70929
+ import { readFile } from "fs/promises";
70930
+ import { join as join6 } from "path";
70931
+ var AssetManifestLoader = class {
70932
+ logger = getLogger().child("AssetManifestLoader");
70933
+ /**
70934
+ * Load asset manifest from CDK output directory
70935
+ *
70936
+ * @param cdkOutputDir CDK output directory (e.g., "cdk.out")
70937
+ * @param stackName Stack name
70938
+ * @returns Asset manifest or null if not found
70939
+ */
70940
+ async loadManifest(cdkOutputDir, stackName) {
70941
+ const manifestPath = join6(cdkOutputDir, `${stackName}.assets.json`);
70942
+ try {
70943
+ this.logger.debug(`Loading asset manifest from: ${manifestPath}`);
70944
+ const content = await readFile(manifestPath, "utf-8");
70945
+ const manifest = JSON.parse(content);
70946
+ this.logger.debug(
70947
+ `Loaded asset manifest: ${Object.keys(manifest.files).length} file assets, ${Object.keys(manifest.dockerImages).length} docker image assets`
70948
+ );
70949
+ return manifest;
70950
+ } catch (error) {
70951
+ if (error.code === "ENOENT") {
70952
+ this.logger.debug(`Asset manifest not found: ${manifestPath}`);
70953
+ return null;
70954
+ }
70955
+ throw new Error(
70956
+ `Failed to load asset manifest from ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`
70957
+ );
70958
+ }
70959
+ }
70960
+ /**
70961
+ * Get file assets from manifest (excludes CloudFormation templates)
70962
+ *
70963
+ * @param manifest Asset manifest
70964
+ * @returns Map of asset hash to file asset
70965
+ */
70966
+ getFileAssets(manifest) {
70967
+ const fileAssets = /* @__PURE__ */ new Map();
70968
+ for (const [assetHash, asset] of Object.entries(manifest.files)) {
70969
+ if (asset.source.path.endsWith(".json") || asset.source.path.endsWith(".template.json")) {
70970
+ this.logger.debug(`Skipping CloudFormation template asset: ${asset.displayName}`);
70971
+ continue;
70972
+ }
70973
+ fileAssets.set(assetHash, asset);
70974
+ }
70975
+ this.logger.debug(`Found ${fileAssets.size} file assets (excluding templates)`);
70976
+ return fileAssets;
70977
+ }
70978
+ /**
70979
+ * Get asset source path (absolute path)
70980
+ *
70981
+ * @param cdkOutputDir CDK output directory
70982
+ * @param asset File asset
70983
+ * @returns Absolute path to asset source
70984
+ */
70985
+ getAssetSourcePath(cdkOutputDir, asset) {
70986
+ return join6(cdkOutputDir, asset.source.path);
70987
+ }
70988
+ /**
70989
+ * Resolve asset destination values (replace ${AWS::AccountId}, ${AWS::Region}, etc.)
70990
+ *
70991
+ * @param value Value with placeholders
70992
+ * @param accountId AWS account ID
70993
+ * @param region AWS region
70994
+ * @param partition AWS partition (default: "aws")
70995
+ * @returns Resolved value
70996
+ */
70997
+ resolveAssetDestinationValue(value, accountId, region, partition = "aws") {
70998
+ return value.replace(/\$\{AWS::AccountId\}/g, accountId).replace(/\$\{AWS::Region\}/g, region).replace(/\$\{AWS::Partition\}/g, partition);
70999
+ }
71000
+ };
71001
+ function getDockerImageBySourceHash(manifest, imageUri) {
71002
+ const dockerImages = manifest.dockerImages ?? {};
71003
+ const entries = Object.entries(dockerImages);
71004
+ if (entries.length === 0)
71005
+ return void 0;
71006
+ const hash = extractHashFromImageUri(imageUri);
71007
+ if (hash !== void 0) {
71008
+ const asset = dockerImages[hash];
71009
+ if (asset) {
71010
+ return { hash, asset };
71011
+ }
71012
+ }
71013
+ if (entries.length === 1) {
71014
+ const [singleHash, singleAsset] = entries[0];
71015
+ return { hash: singleHash, asset: singleAsset };
71016
+ }
71017
+ return void 0;
71018
+ }
71019
+ function extractHashFromImageUri(imageUri) {
71020
+ if (imageUri.includes("@sha256:"))
71021
+ return void 0;
71022
+ const match = /:([a-f0-9]{8,})$/.exec(imageUri);
71023
+ return match?.[1];
71024
+ }
71025
+
70633
71026
  // src/cli/commands/local-invoke.ts
70634
71027
  init_aws_clients();
70635
71028
  async function localInvokeCommand(target, options) {
@@ -70656,12 +71049,9 @@ async function localInvokeCommand(target, options) {
70656
71049
  };
70657
71050
  const { stacks } = await synthesizer.synthesize(synthOpts);
70658
71051
  const lambda = resolveLambdaTarget(target, stacks);
70659
- logger.info(`Target: ${lambda.stack.stackName}/${lambda.logicalId} (${lambda.runtime})`);
70660
- const codeDir = lambda.codePath ?? materializeInlineCode(
70661
- lambda.handler,
70662
- lambda.inlineCode ?? "",
70663
- resolveRuntimeFileExtension(lambda.runtime)
70664
- );
71052
+ const targetLabel = lambda.kind === "zip" ? lambda.runtime : "container image";
71053
+ logger.info(`Target: ${lambda.stack.stackName}/${lambda.logicalId} (${targetLabel})`);
71054
+ const imagePlan = await resolveImagePlan(lambda, options);
70665
71055
  let stateAudit;
70666
71056
  let templateEnv = getTemplateEnv(lambda.resource);
70667
71057
  let stateForRoleHint;
@@ -70701,7 +71091,6 @@ async function localInvokeCommand(target, options) {
70701
71091
  suggestAssumeRoleFromState(stateForRoleHint, lambda.logicalId);
70702
71092
  }
70703
71093
  const event = await readEvent(options);
70704
- const image = resolveRuntimeImage(lambda.runtime);
70705
71094
  const dockerEnv = {
70706
71095
  AWS_LAMBDA_FUNCTION_NAME: lambda.logicalId,
70707
71096
  AWS_LAMBDA_FUNCTION_MEMORY_SIZE: String(lambda.memoryMb),
@@ -70729,19 +71118,26 @@ async function localInvokeCommand(target, options) {
70729
71118
  throw new Error(`--debug-port must be an integer in 1..65535, got '${options.debugPort}'`);
70730
71119
  }
70731
71120
  dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
71121
+ if (lambda.kind === "image") {
71122
+ logger.warn(
71123
+ "--debug-port sets NODE_OPTIONS unconditionally on container Lambdas. If the image's runtime is not Node.js, this flag is a no-op."
71124
+ );
71125
+ }
70732
71126
  }
70733
- await pullImage(image, options.pull === false);
70734
71127
  const hostPort = await pickFreePort();
70735
- const containerHost = options.containerHost || "127.0.0.1";
70736
- logger.info(`Starting container (image=${image}, port=${hostPort})...`);
71128
+ const containerHost = options.containerHost;
71129
+ logger.info(`Starting container (image=${imagePlan.image}, port=${hostPort})...`);
70737
71130
  const containerId = await runDetached({
70738
- image,
70739
- mounts: [{ hostPath: codeDir, containerPath: "/var/task", readOnly: true }],
71131
+ image: imagePlan.image,
71132
+ mounts: imagePlan.mounts,
70740
71133
  env: dockerEnv,
70741
- cmd: [lambda.handler],
71134
+ cmd: imagePlan.cmd,
70742
71135
  hostPort,
70743
71136
  host: containerHost,
70744
- ...debugPort !== void 0 && { debugPort }
71137
+ ...debugPort !== void 0 && { debugPort },
71138
+ ...imagePlan.platform !== void 0 && { platform: imagePlan.platform },
71139
+ ...imagePlan.entryPoint !== void 0 && { entryPoint: imagePlan.entryPoint },
71140
+ ...imagePlan.workingDir !== void 0 && { workingDir: imagePlan.workingDir }
70745
71141
  });
70746
71142
  const stopLogs = streamLogs(containerId);
70747
71143
  const sigintHandler = () => {
@@ -70762,7 +71158,92 @@ async function localInvokeCommand(target, options) {
70762
71158
  process.off("SIGINT", sigintHandler);
70763
71159
  stopLogs();
70764
71160
  await removeContainer(containerId);
71161
+ if (imagePlan.inlineTmpDir) {
71162
+ try {
71163
+ rmSync2(imagePlan.inlineTmpDir, { recursive: true, force: true });
71164
+ } catch (err) {
71165
+ getLogger().debug(
71166
+ `Failed to remove inline-code tmpdir ${imagePlan.inlineTmpDir}: ${err instanceof Error ? err.message : String(err)}`
71167
+ );
71168
+ }
71169
+ }
71170
+ }
71171
+ }
71172
+ async function resolveImagePlan(lambda, options) {
71173
+ if (lambda.kind === "zip") {
71174
+ return resolveZipImagePlan(lambda, options);
71175
+ }
71176
+ return resolveContainerImagePlan(lambda, options);
71177
+ }
71178
+ async function resolveZipImagePlan(lambda, options) {
71179
+ let inlineTmpDir;
71180
+ let codeDir = lambda.codePath;
71181
+ if (codeDir === null) {
71182
+ inlineTmpDir = materializeInlineCode(
71183
+ lambda.handler,
71184
+ lambda.inlineCode ?? "",
71185
+ resolveRuntimeFileExtension(lambda.runtime)
71186
+ );
71187
+ codeDir = inlineTmpDir;
71188
+ }
71189
+ const image = resolveRuntimeImage(lambda.runtime);
71190
+ await pullImage(image, options.pull === false);
71191
+ return {
71192
+ image,
71193
+ mounts: [{ hostPath: codeDir, containerPath: "/var/task", readOnly: true }],
71194
+ cmd: [lambda.handler],
71195
+ ...inlineTmpDir !== void 0 && { inlineTmpDir }
71196
+ };
71197
+ }
71198
+ async function resolveContainerImagePlan(lambda, options) {
71199
+ const logger = getLogger();
71200
+ const platform = architectureToPlatform(lambda.architecture);
71201
+ const localBuild = await resolveLocalBuildPlan(lambda);
71202
+ let imageRef;
71203
+ if (localBuild) {
71204
+ imageRef = await buildContainerImage(localBuild.asset, localBuild.cdkOutDir, {
71205
+ architecture: lambda.architecture
71206
+ });
71207
+ } else {
71208
+ if (!parseEcrUri(lambda.imageUri)) {
71209
+ throw new Error(
71210
+ `Container Lambda '${lambda.logicalId}' has no matching asset in cdk.out, and Code.ImageUri '${lambda.imageUri}' is not an ECR URI cdkd can authenticate against. Re-synthesize the CDK app (so cdk.out includes the build context) or deploy the image to ECR first.`
71211
+ );
71212
+ }
71213
+ logger.info(
71214
+ `No matching cdk.out asset for ${lambda.imageUri}; falling back to ECR pull (same-acct/region only)...`
71215
+ );
71216
+ imageRef = await pullEcrImage(lambda.imageUri, {
71217
+ skipPull: options.pull === false,
71218
+ ...options.region !== void 0 && { region: options.region }
71219
+ });
70765
71220
  }
71221
+ return {
71222
+ image: imageRef,
71223
+ mounts: [],
71224
+ cmd: lambda.imageConfig.command ?? [],
71225
+ platform,
71226
+ ...lambda.imageConfig.entryPoint && lambda.imageConfig.entryPoint.length > 0 && {
71227
+ entryPoint: lambda.imageConfig.entryPoint
71228
+ },
71229
+ ...lambda.imageConfig.workingDirectory !== void 0 && {
71230
+ workingDir: lambda.imageConfig.workingDirectory
71231
+ }
71232
+ };
71233
+ }
71234
+ async function resolveLocalBuildPlan(lambda) {
71235
+ const manifestPath = lambda.stack.assetManifestPath;
71236
+ if (!manifestPath)
71237
+ return void 0;
71238
+ const cdkOutDir = dirname2(manifestPath);
71239
+ const loader = new AssetManifestLoader();
71240
+ const manifest = await loader.loadManifest(cdkOutDir, lambda.stack.stackName);
71241
+ if (!manifest)
71242
+ return void 0;
71243
+ const entry = getDockerImageBySourceHash(manifest, lambda.imageUri);
71244
+ if (!entry)
71245
+ return void 0;
71246
+ return { asset: entry.asset, cdkOutDir };
70766
71247
  }
70767
71248
  function getTemplateEnv(resource) {
70768
71249
  const props = resource.Properties ?? {};
@@ -70829,8 +71310,8 @@ async function readStdin() {
70829
71310
  return Buffer.concat(chunks).toString("utf-8");
70830
71311
  }
70831
71312
  async function assumeLambdaExecutionRole(roleArn, region) {
70832
- const { STSClient: STSClient10, AssumeRoleCommand: AssumeRoleCommand2 } = await import("@aws-sdk/client-sts");
70833
- const sts = new STSClient10({ ...region && { region } });
71313
+ const { STSClient: STSClient11, AssumeRoleCommand: AssumeRoleCommand2 } = await import("@aws-sdk/client-sts");
71314
+ const sts = new STSClient11({ ...region && { region } });
70834
71315
  try {
70835
71316
  const response = await sts.send(
70836
71317
  new AssumeRoleCommand2({
@@ -70992,7 +71473,12 @@ function createLocalCommand() {
70992
71473
  "--env-vars <file>",
70993
71474
  'JSON env-var overrides (SAM-compatible: {"LogicalId":{"KEY":"VALUE"}})'
70994
71475
  )
70995
- ).addOption(new Option7("--no-pull", "Skip docker pull (use cached image)")).addOption(new Option7("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(
71476
+ ).addOption(
71477
+ new Option7(
71478
+ "--no-pull",
71479
+ "Skip docker pull (use cached image) \u2014 no-op for IMAGE local-build path; `docker build` does not pull base layers by default"
71480
+ )
71481
+ ).addOption(new Option7("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(
70996
71482
  new Option7("--container-host <host>", "Host to bind the RIE port to").default("127.0.0.1")
70997
71483
  ).addOption(
70998
71484
  new Option7(
@@ -71047,7 +71533,7 @@ function reorderArgs(argv) {
71047
71533
  }
71048
71534
  async function main() {
71049
71535
  const program = new Command15();
71050
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.69.0");
71536
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.70.0");
71051
71537
  program.addCommand(createBootstrapCommand());
71052
71538
  program.addCommand(createSynthCommand());
71053
71539
  program.addCommand(createListCommand());