@go-to-k/cdkd 0.69.0 → 0.71.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 +49 -4
- package/dist/cli.js +2497 -317
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.71.0.tgz +0 -0
- package/dist/index.js +56 -34
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.69.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -708,10 +708,10 @@ var require_GraphQLError = __commonJS({
|
|
|
708
708
|
*/
|
|
709
709
|
constructor(message, ...rawArgs) {
|
|
710
710
|
var _this$nodes, _nodeLocations$, _ref;
|
|
711
|
-
const { nodes, source, positions, path:
|
|
711
|
+
const { nodes, source, positions, path: path3, originalError, extensions } = toNormalizedOptions(rawArgs);
|
|
712
712
|
super(message);
|
|
713
713
|
this.name = "GraphQLError";
|
|
714
|
-
this.path =
|
|
714
|
+
this.path = path3 !== null && path3 !== void 0 ? path3 : void 0;
|
|
715
715
|
this.originalError = originalError !== null && originalError !== void 0 ? originalError : void 0;
|
|
716
716
|
this.nodes = undefinedIfEmpty(
|
|
717
717
|
Array.isArray(nodes) ? nodes : nodes ? [nodes] : void 0
|
|
@@ -4173,14 +4173,14 @@ var require_visitor = __commonJS({
|
|
|
4173
4173
|
let node = root;
|
|
4174
4174
|
let key = void 0;
|
|
4175
4175
|
let parent = void 0;
|
|
4176
|
-
const
|
|
4176
|
+
const path3 = [];
|
|
4177
4177
|
const ancestors = [];
|
|
4178
4178
|
do {
|
|
4179
4179
|
index++;
|
|
4180
4180
|
const isLeaving = index === keys.length;
|
|
4181
4181
|
const isEdited = isLeaving && edits.length !== 0;
|
|
4182
4182
|
if (isLeaving) {
|
|
4183
|
-
key = ancestors.length === 0 ? void 0 :
|
|
4183
|
+
key = ancestors.length === 0 ? void 0 : path3[path3.length - 1];
|
|
4184
4184
|
node = parent;
|
|
4185
4185
|
parent = ancestors.pop();
|
|
4186
4186
|
if (isEdited) {
|
|
@@ -4214,7 +4214,7 @@ var require_visitor = __commonJS({
|
|
|
4214
4214
|
if (node === null || node === void 0) {
|
|
4215
4215
|
continue;
|
|
4216
4216
|
}
|
|
4217
|
-
|
|
4217
|
+
path3.push(key);
|
|
4218
4218
|
}
|
|
4219
4219
|
let result;
|
|
4220
4220
|
if (!Array.isArray(node)) {
|
|
@@ -4224,13 +4224,13 @@ var require_visitor = __commonJS({
|
|
|
4224
4224
|
`Invalid AST Node: ${(0, _inspect.inspect)(node)}.`
|
|
4225
4225
|
);
|
|
4226
4226
|
const visitFn = isLeaving ? (_enterLeaveMap$get = enterLeaveMap.get(node.kind)) === null || _enterLeaveMap$get === void 0 ? void 0 : _enterLeaveMap$get.leave : (_enterLeaveMap$get2 = enterLeaveMap.get(node.kind)) === null || _enterLeaveMap$get2 === void 0 ? void 0 : _enterLeaveMap$get2.enter;
|
|
4227
|
-
result = visitFn === null || visitFn === void 0 ? void 0 : visitFn.call(visitor, node, key, parent,
|
|
4227
|
+
result = visitFn === null || visitFn === void 0 ? void 0 : visitFn.call(visitor, node, key, parent, path3, ancestors);
|
|
4228
4228
|
if (result === BREAK) {
|
|
4229
4229
|
break;
|
|
4230
4230
|
}
|
|
4231
4231
|
if (result === false) {
|
|
4232
4232
|
if (!isLeaving) {
|
|
4233
|
-
|
|
4233
|
+
path3.pop();
|
|
4234
4234
|
continue;
|
|
4235
4235
|
}
|
|
4236
4236
|
} else if (result !== void 0) {
|
|
@@ -4239,7 +4239,7 @@ var require_visitor = __commonJS({
|
|
|
4239
4239
|
if ((0, _ast.isNode)(result)) {
|
|
4240
4240
|
node = result;
|
|
4241
4241
|
} else {
|
|
4242
|
-
|
|
4242
|
+
path3.pop();
|
|
4243
4243
|
continue;
|
|
4244
4244
|
}
|
|
4245
4245
|
}
|
|
@@ -4249,7 +4249,7 @@ var require_visitor = __commonJS({
|
|
|
4249
4249
|
edits.push([key, node]);
|
|
4250
4250
|
}
|
|
4251
4251
|
if (isLeaving) {
|
|
4252
|
-
|
|
4252
|
+
path3.pop();
|
|
4253
4253
|
} else {
|
|
4254
4254
|
var _node$kind;
|
|
4255
4255
|
stack = {
|
|
@@ -4374,16 +4374,16 @@ var require_printer = __commonJS({
|
|
|
4374
4374
|
},
|
|
4375
4375
|
// Document
|
|
4376
4376
|
Document: {
|
|
4377
|
-
leave: (node) =>
|
|
4377
|
+
leave: (node) => join9(node.definitions, "\n\n")
|
|
4378
4378
|
},
|
|
4379
4379
|
OperationDefinition: {
|
|
4380
4380
|
leave(node) {
|
|
4381
|
-
const varDefs = hasMultilineItems(node.variableDefinitions) ? wrap("(\n",
|
|
4382
|
-
const prefix = wrap("", node.description, "\n") +
|
|
4381
|
+
const varDefs = hasMultilineItems(node.variableDefinitions) ? wrap("(\n", join9(node.variableDefinitions, "\n"), "\n)") : wrap("(", join9(node.variableDefinitions, ", "), ")");
|
|
4382
|
+
const prefix = wrap("", node.description, "\n") + join9(
|
|
4383
4383
|
[
|
|
4384
4384
|
node.operation,
|
|
4385
|
-
|
|
4386
|
-
|
|
4385
|
+
join9([node.name, varDefs]),
|
|
4386
|
+
join9(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(" ",
|
|
4394
|
+
leave: ({ variable, type, defaultValue, directives, description }) => wrap("", description, "\n") + variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ", join9(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("(",
|
|
4402
|
+
let argsLine = prefix + wrap("(", join9(args, ", "), ")");
|
|
4403
4403
|
if (argsLine.length > MAX_LINE_LENGTH) {
|
|
4404
|
-
argsLine = prefix + wrap("(\n", indent(
|
|
4404
|
+
argsLine = prefix + wrap("(\n", indent(join9(args, "\n")), "\n)");
|
|
4405
4405
|
}
|
|
4406
|
-
return
|
|
4406
|
+
return join9([argsLine, join9(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(" ",
|
|
4414
|
+
leave: ({ name, directives }) => "..." + name + wrap(" ", join9(directives, " "))
|
|
4415
4415
|
},
|
|
4416
4416
|
InlineFragment: {
|
|
4417
|
-
leave: ({ typeCondition, directives, selectionSet }) =>
|
|
4417
|
+
leave: ({ typeCondition, directives, selectionSet }) => join9(
|
|
4418
4418
|
[
|
|
4419
4419
|
"...",
|
|
4420
4420
|
wrap("on ", typeCondition),
|
|
4421
|
-
|
|
4421
|
+
join9(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("(",
|
|
4437
|
+
`fragment ${name}${wrap("(", join9(variableDefinitions, ", "), ")")} on ${typeCondition} ${wrap("", join9(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 }) => "[" +
|
|
4459
|
+
leave: ({ values }) => "[" + join9(values, ", ") + "]"
|
|
4460
4460
|
},
|
|
4461
4461
|
ObjectValue: {
|
|
4462
|
-
leave: ({ fields }) => "{" +
|
|
4462
|
+
leave: ({ fields }) => "{" + join9(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("(",
|
|
4469
|
+
leave: ({ name, arguments: args }) => "@" + name + wrap("(", join9(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") +
|
|
4483
|
+
leave: ({ description, directives, operationTypes }) => wrap("", description, "\n") + join9(["schema", join9(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") +
|
|
4489
|
+
leave: ({ description, name, directives }) => wrap("", description, "\n") + join9(["scalar", name, join9(directives, " ")], " ")
|
|
4490
4490
|
},
|
|
4491
4491
|
ObjectTypeDefinition: {
|
|
4492
|
-
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") +
|
|
4492
|
+
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join9(
|
|
4493
4493
|
[
|
|
4494
4494
|
"type",
|
|
4495
4495
|
name,
|
|
4496
|
-
wrap("implements ",
|
|
4497
|
-
|
|
4496
|
+
wrap("implements ", join9(interfaces, " & ")),
|
|
4497
|
+
join9(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(
|
|
4504
|
+
leave: ({ description, name, arguments: args, type, directives }) => wrap("", description, "\n") + name + (hasMultilineItems(args) ? wrap("(\n", indent(join9(args, "\n")), "\n)") : wrap("(", join9(args, ", "), ")")) + ": " + type + wrap(" ", join9(directives, " "))
|
|
4505
4505
|
},
|
|
4506
4506
|
InputValueDefinition: {
|
|
4507
|
-
leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") +
|
|
4508
|
-
[name + ": " + type, wrap("= ", defaultValue),
|
|
4507
|
+
leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") + join9(
|
|
4508
|
+
[name + ": " + type, wrap("= ", defaultValue), join9(directives, " ")],
|
|
4509
4509
|
" "
|
|
4510
4510
|
)
|
|
4511
4511
|
},
|
|
4512
4512
|
InterfaceTypeDefinition: {
|
|
4513
|
-
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") +
|
|
4513
|
+
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join9(
|
|
4514
4514
|
[
|
|
4515
4515
|
"interface",
|
|
4516
4516
|
name,
|
|
4517
|
-
wrap("implements ",
|
|
4518
|
-
|
|
4517
|
+
wrap("implements ", join9(interfaces, " & ")),
|
|
4518
|
+
join9(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") +
|
|
4526
|
-
["union", name,
|
|
4525
|
+
leave: ({ description, name, directives, types }) => wrap("", description, "\n") + join9(
|
|
4526
|
+
["union", name, join9(directives, " "), wrap("= ", join9(types, " | "))],
|
|
4527
4527
|
" "
|
|
4528
4528
|
)
|
|
4529
4529
|
},
|
|
4530
4530
|
EnumTypeDefinition: {
|
|
4531
|
-
leave: ({ description, name, directives, values }) => wrap("", description, "\n") +
|
|
4531
|
+
leave: ({ description, name, directives, values }) => wrap("", description, "\n") + join9(["enum", name, join9(directives, " "), block(values)], " ")
|
|
4532
4532
|
},
|
|
4533
4533
|
EnumValueDefinition: {
|
|
4534
|
-
leave: ({ description, name, directives }) => wrap("", description, "\n") +
|
|
4534
|
+
leave: ({ description, name, directives }) => wrap("", description, "\n") + join9([name, join9(directives, " ")], " ")
|
|
4535
4535
|
},
|
|
4536
4536
|
InputObjectTypeDefinition: {
|
|
4537
|
-
leave: ({ description, name, directives, fields }) => wrap("", description, "\n") +
|
|
4537
|
+
leave: ({ description, name, directives, fields }) => wrap("", description, "\n") + join9(["input", name, join9(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(
|
|
4547
|
+
}) => wrap("", description, "\n") + "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(join9(args, "\n")), "\n)") : wrap("(", join9(args, ", "), ")")) + wrap(" ", join9(directives, " ")) + (repeatable ? " repeatable" : "") + " on " + join9(locations, " | ")
|
|
4548
4548
|
},
|
|
4549
4549
|
SchemaExtension: {
|
|
4550
|
-
leave: ({ directives, operationTypes }) =>
|
|
4551
|
-
["extend schema",
|
|
4550
|
+
leave: ({ directives, operationTypes }) => join9(
|
|
4551
|
+
["extend schema", join9(directives, " "), block(operationTypes)],
|
|
4552
4552
|
" "
|
|
4553
4553
|
)
|
|
4554
4554
|
},
|
|
4555
4555
|
ScalarTypeExtension: {
|
|
4556
|
-
leave: ({ name, directives }) =>
|
|
4556
|
+
leave: ({ name, directives }) => join9(["extend scalar", name, join9(directives, " ")], " ")
|
|
4557
4557
|
},
|
|
4558
4558
|
ObjectTypeExtension: {
|
|
4559
|
-
leave: ({ name, interfaces, directives, fields }) =>
|
|
4559
|
+
leave: ({ name, interfaces, directives, fields }) => join9(
|
|
4560
4560
|
[
|
|
4561
4561
|
"extend type",
|
|
4562
4562
|
name,
|
|
4563
|
-
wrap("implements ",
|
|
4564
|
-
|
|
4563
|
+
wrap("implements ", join9(interfaces, " & ")),
|
|
4564
|
+
join9(directives, " "),
|
|
4565
4565
|
block(fields)
|
|
4566
4566
|
],
|
|
4567
4567
|
" "
|
|
4568
4568
|
)
|
|
4569
4569
|
},
|
|
4570
4570
|
InterfaceTypeExtension: {
|
|
4571
|
-
leave: ({ name, interfaces, directives, fields }) =>
|
|
4571
|
+
leave: ({ name, interfaces, directives, fields }) => join9(
|
|
4572
4572
|
[
|
|
4573
4573
|
"extend interface",
|
|
4574
4574
|
name,
|
|
4575
|
-
wrap("implements ",
|
|
4576
|
-
|
|
4575
|
+
wrap("implements ", join9(interfaces, " & ")),
|
|
4576
|
+
join9(directives, " "),
|
|
4577
4577
|
block(fields)
|
|
4578
4578
|
],
|
|
4579
4579
|
" "
|
|
4580
4580
|
)
|
|
4581
4581
|
},
|
|
4582
4582
|
UnionTypeExtension: {
|
|
4583
|
-
leave: ({ name, directives, types }) =>
|
|
4583
|
+
leave: ({ name, directives, types }) => join9(
|
|
4584
4584
|
[
|
|
4585
4585
|
"extend union",
|
|
4586
4586
|
name,
|
|
4587
|
-
|
|
4588
|
-
wrap("= ",
|
|
4587
|
+
join9(directives, " "),
|
|
4588
|
+
wrap("= ", join9(types, " | "))
|
|
4589
4589
|
],
|
|
4590
4590
|
" "
|
|
4591
4591
|
)
|
|
4592
4592
|
},
|
|
4593
4593
|
EnumTypeExtension: {
|
|
4594
|
-
leave: ({ name, directives, values }) =>
|
|
4594
|
+
leave: ({ name, directives, values }) => join9(["extend enum", name, join9(directives, " "), block(values)], " ")
|
|
4595
4595
|
},
|
|
4596
4596
|
InputObjectTypeExtension: {
|
|
4597
|
-
leave: ({ name, directives, fields }) =>
|
|
4597
|
+
leave: ({ name, directives, fields }) => join9(["extend input", name, join9(directives, " "), block(fields)], " ")
|
|
4598
4598
|
},
|
|
4599
4599
|
DirectiveExtension: {
|
|
4600
|
-
leave: ({ name, directives }) =>
|
|
4600
|
+
leave: ({ name, directives }) => join9(["extend directive @" + name, join9(directives, " ")], " ")
|
|
4601
4601
|
},
|
|
4602
4602
|
// Schema Coordinates
|
|
4603
4603
|
TypeCoordinate: {
|
|
4604
4604
|
leave: ({ name }) => name
|
|
4605
4605
|
},
|
|
4606
4606
|
MemberCoordinate: {
|
|
4607
|
-
leave: ({ name, memberName }) =>
|
|
4607
|
+
leave: ({ name, memberName }) => join9([name, wrap(".", memberName)])
|
|
4608
4608
|
},
|
|
4609
4609
|
ArgumentCoordinate: {
|
|
4610
|
-
leave: ({ name, fieldName, argumentName }) =>
|
|
4610
|
+
leave: ({ name, fieldName, argumentName }) => join9([name, wrap(".", fieldName), wrap("(", argumentName, ":)")])
|
|
4611
4611
|
},
|
|
4612
4612
|
DirectiveCoordinate: {
|
|
4613
|
-
leave: ({ name }) =>
|
|
4613
|
+
leave: ({ name }) => join9(["@", name])
|
|
4614
4614
|
},
|
|
4615
4615
|
DirectiveArgumentCoordinate: {
|
|
4616
|
-
leave: ({ name, argumentName }) =>
|
|
4616
|
+
leave: ({ name, argumentName }) => join9(["@", name, wrap("(", argumentName, ":)")])
|
|
4617
4617
|
}
|
|
4618
4618
|
};
|
|
4619
|
-
function
|
|
4619
|
+
function join9(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(
|
|
4624
|
+
return wrap("{\n", indent(join9(array, "\n")), "\n}");
|
|
4625
4625
|
}
|
|
4626
4626
|
function wrap(start, maybeString, end = "") {
|
|
4627
4627
|
return maybeString != null && maybeString !== "" ? start + maybeString + end : "";
|
|
@@ -9578,8 +9578,8 @@ var require_printPathArray = __commonJS({
|
|
|
9578
9578
|
value: true
|
|
9579
9579
|
});
|
|
9580
9580
|
exports.printPathArray = printPathArray;
|
|
9581
|
-
function printPathArray(
|
|
9582
|
-
return
|
|
9581
|
+
function printPathArray(path3) {
|
|
9582
|
+
return path3.map(
|
|
9583
9583
|
(key) => typeof key === "number" ? "[" + key.toString() + "]" : "." + key
|
|
9584
9584
|
).join("");
|
|
9585
9585
|
}
|
|
@@ -9602,9 +9602,9 @@ var require_Path = __commonJS({
|
|
|
9602
9602
|
typename
|
|
9603
9603
|
};
|
|
9604
9604
|
}
|
|
9605
|
-
function pathToArray(
|
|
9605
|
+
function pathToArray(path3) {
|
|
9606
9606
|
const flattened = [];
|
|
9607
|
-
let curr =
|
|
9607
|
+
let curr = path3;
|
|
9608
9608
|
while (curr) {
|
|
9609
9609
|
flattened.push(curr.key);
|
|
9610
9610
|
curr = curr.prev;
|
|
@@ -9635,21 +9635,21 @@ var require_coerceInputValue = __commonJS({
|
|
|
9635
9635
|
function coerceInputValue(inputValue, type, onError = defaultOnError) {
|
|
9636
9636
|
return coerceInputValueImpl(inputValue, type, onError, void 0);
|
|
9637
9637
|
}
|
|
9638
|
-
function defaultOnError(
|
|
9638
|
+
function defaultOnError(path3, invalidValue, error) {
|
|
9639
9639
|
let errorPrefix = "Invalid value " + (0, _inspect.inspect)(invalidValue);
|
|
9640
|
-
if (
|
|
9641
|
-
errorPrefix += ` at "value${(0, _printPathArray.printPathArray)(
|
|
9640
|
+
if (path3.length > 0) {
|
|
9641
|
+
errorPrefix += ` at "value${(0, _printPathArray.printPathArray)(path3)}"`;
|
|
9642
9642
|
}
|
|
9643
9643
|
error.message = errorPrefix + ": " + error.message;
|
|
9644
9644
|
throw error;
|
|
9645
9645
|
}
|
|
9646
|
-
function coerceInputValueImpl(inputValue, type, onError,
|
|
9646
|
+
function coerceInputValueImpl(inputValue, type, onError, path3) {
|
|
9647
9647
|
if ((0, _definition.isNonNullType)(type)) {
|
|
9648
9648
|
if (inputValue != null) {
|
|
9649
|
-
return coerceInputValueImpl(inputValue, type.ofType, onError,
|
|
9649
|
+
return coerceInputValueImpl(inputValue, type.ofType, onError, path3);
|
|
9650
9650
|
}
|
|
9651
9651
|
onError(
|
|
9652
|
-
(0, _Path.pathToArray)(
|
|
9652
|
+
(0, _Path.pathToArray)(path3),
|
|
9653
9653
|
inputValue,
|
|
9654
9654
|
new _GraphQLError.GraphQLError(
|
|
9655
9655
|
`Expected non-nullable type "${(0, _inspect.inspect)(
|
|
@@ -9666,16 +9666,16 @@ var require_coerceInputValue = __commonJS({
|
|
|
9666
9666
|
const itemType = type.ofType;
|
|
9667
9667
|
if ((0, _isIterableObject.isIterableObject)(inputValue)) {
|
|
9668
9668
|
return Array.from(inputValue, (itemValue, index) => {
|
|
9669
|
-
const itemPath = (0, _Path.addPath)(
|
|
9669
|
+
const itemPath = (0, _Path.addPath)(path3, index, void 0);
|
|
9670
9670
|
return coerceInputValueImpl(itemValue, itemType, onError, itemPath);
|
|
9671
9671
|
});
|
|
9672
9672
|
}
|
|
9673
|
-
return [coerceInputValueImpl(inputValue, itemType, onError,
|
|
9673
|
+
return [coerceInputValueImpl(inputValue, itemType, onError, path3)];
|
|
9674
9674
|
}
|
|
9675
9675
|
if ((0, _definition.isInputObjectType)(type)) {
|
|
9676
9676
|
if (!(0, _isObjectLike.isObjectLike)(inputValue) || Array.isArray(inputValue)) {
|
|
9677
9677
|
onError(
|
|
9678
|
-
(0, _Path.pathToArray)(
|
|
9678
|
+
(0, _Path.pathToArray)(path3),
|
|
9679
9679
|
inputValue,
|
|
9680
9680
|
new _GraphQLError.GraphQLError(
|
|
9681
9681
|
`Expected type "${type.name}" to be an object.`
|
|
@@ -9693,7 +9693,7 @@ var require_coerceInputValue = __commonJS({
|
|
|
9693
9693
|
} else if ((0, _definition.isNonNullType)(field.type)) {
|
|
9694
9694
|
const typeStr = (0, _inspect.inspect)(field.type);
|
|
9695
9695
|
onError(
|
|
9696
|
-
(0, _Path.pathToArray)(
|
|
9696
|
+
(0, _Path.pathToArray)(path3),
|
|
9697
9697
|
inputValue,
|
|
9698
9698
|
new _GraphQLError.GraphQLError(
|
|
9699
9699
|
`Field "${field.name}" of required type "${typeStr}" was not provided.`
|
|
@@ -9706,7 +9706,7 @@ var require_coerceInputValue = __commonJS({
|
|
|
9706
9706
|
fieldValue,
|
|
9707
9707
|
field.type,
|
|
9708
9708
|
onError,
|
|
9709
|
-
(0, _Path.addPath)(
|
|
9709
|
+
(0, _Path.addPath)(path3, field.name, type.name)
|
|
9710
9710
|
);
|
|
9711
9711
|
}
|
|
9712
9712
|
for (const fieldName of Object.keys(inputValue)) {
|
|
@@ -9716,7 +9716,7 @@ var require_coerceInputValue = __commonJS({
|
|
|
9716
9716
|
Object.keys(type.getFields())
|
|
9717
9717
|
);
|
|
9718
9718
|
onError(
|
|
9719
|
-
(0, _Path.pathToArray)(
|
|
9719
|
+
(0, _Path.pathToArray)(path3),
|
|
9720
9720
|
inputValue,
|
|
9721
9721
|
new _GraphQLError.GraphQLError(
|
|
9722
9722
|
`Field "${fieldName}" is not defined by type "${type.name}".` + (0, _didYouMean.didYouMean)(suggestions)
|
|
@@ -9728,7 +9728,7 @@ var require_coerceInputValue = __commonJS({
|
|
|
9728
9728
|
const keys = Object.keys(coercedValue);
|
|
9729
9729
|
if (keys.length !== 1) {
|
|
9730
9730
|
onError(
|
|
9731
|
-
(0, _Path.pathToArray)(
|
|
9731
|
+
(0, _Path.pathToArray)(path3),
|
|
9732
9732
|
inputValue,
|
|
9733
9733
|
new _GraphQLError.GraphQLError(
|
|
9734
9734
|
`Exactly one key must be specified for OneOf type "${type.name}".`
|
|
@@ -9739,7 +9739,7 @@ var require_coerceInputValue = __commonJS({
|
|
|
9739
9739
|
const value = coercedValue[key];
|
|
9740
9740
|
if (value === null) {
|
|
9741
9741
|
onError(
|
|
9742
|
-
(0, _Path.pathToArray)(
|
|
9742
|
+
(0, _Path.pathToArray)(path3).concat(key),
|
|
9743
9743
|
value,
|
|
9744
9744
|
new _GraphQLError.GraphQLError(`Field "${key}" must be non-null.`)
|
|
9745
9745
|
);
|
|
@@ -9753,10 +9753,10 @@ var require_coerceInputValue = __commonJS({
|
|
|
9753
9753
|
parseResult = type.parseValue(inputValue);
|
|
9754
9754
|
} catch (error) {
|
|
9755
9755
|
if (error instanceof _GraphQLError.GraphQLError) {
|
|
9756
|
-
onError((0, _Path.pathToArray)(
|
|
9756
|
+
onError((0, _Path.pathToArray)(path3), inputValue, error);
|
|
9757
9757
|
} else {
|
|
9758
9758
|
onError(
|
|
9759
|
-
(0, _Path.pathToArray)(
|
|
9759
|
+
(0, _Path.pathToArray)(path3),
|
|
9760
9760
|
inputValue,
|
|
9761
9761
|
new _GraphQLError.GraphQLError(
|
|
9762
9762
|
`Expected type "${type.name}". ` + error.message,
|
|
@@ -9770,7 +9770,7 @@ var require_coerceInputValue = __commonJS({
|
|
|
9770
9770
|
}
|
|
9771
9771
|
if (parseResult === void 0) {
|
|
9772
9772
|
onError(
|
|
9773
|
-
(0, _Path.pathToArray)(
|
|
9773
|
+
(0, _Path.pathToArray)(path3),
|
|
9774
9774
|
inputValue,
|
|
9775
9775
|
new _GraphQLError.GraphQLError(`Expected type "${type.name}".`)
|
|
9776
9776
|
);
|
|
@@ -10011,11 +10011,11 @@ var require_values = __commonJS({
|
|
|
10011
10011
|
coercedValues[varName] = (0, _coerceInputValue.coerceInputValue)(
|
|
10012
10012
|
value,
|
|
10013
10013
|
varType,
|
|
10014
|
-
(
|
|
10014
|
+
(path3, invalidValue, error) => {
|
|
10015
10015
|
let prefix = `Variable "$${varName}" got invalid value ` + (0, _inspect.inspect)(invalidValue);
|
|
10016
|
-
if (
|
|
10016
|
+
if (path3.length > 0) {
|
|
10017
10017
|
prefix += ` at "${varName}${(0, _printPathArray.printPathArray)(
|
|
10018
|
-
|
|
10018
|
+
path3
|
|
10019
10019
|
)}"`;
|
|
10020
10020
|
}
|
|
10021
10021
|
onError(
|
|
@@ -11745,7 +11745,7 @@ var require_locatedError = __commonJS({
|
|
|
11745
11745
|
exports.locatedError = locatedError;
|
|
11746
11746
|
var _toError = require_toError();
|
|
11747
11747
|
var _GraphQLError = require_GraphQLError();
|
|
11748
|
-
function locatedError(rawOriginalError, nodes,
|
|
11748
|
+
function locatedError(rawOriginalError, nodes, path3) {
|
|
11749
11749
|
var _nodes;
|
|
11750
11750
|
const originalError = (0, _toError.toError)(rawOriginalError);
|
|
11751
11751
|
if (isLocatedGraphQLError(originalError)) {
|
|
@@ -11755,7 +11755,7 @@ var require_locatedError = __commonJS({
|
|
|
11755
11755
|
nodes: (_nodes = originalError.nodes) !== null && _nodes !== void 0 ? _nodes : nodes,
|
|
11756
11756
|
source: originalError.source,
|
|
11757
11757
|
positions: originalError.positions,
|
|
11758
|
-
path:
|
|
11758
|
+
path: path3,
|
|
11759
11759
|
originalError
|
|
11760
11760
|
});
|
|
11761
11761
|
}
|
|
@@ -11815,20 +11815,20 @@ var require_execute = __commonJS({
|
|
|
11815
11815
|
get errors() {
|
|
11816
11816
|
return this._errors;
|
|
11817
11817
|
}
|
|
11818
|
-
add(error,
|
|
11819
|
-
if (this._hasNulledPosition(
|
|
11818
|
+
add(error, path3) {
|
|
11819
|
+
if (this._hasNulledPosition(path3)) {
|
|
11820
11820
|
return;
|
|
11821
11821
|
}
|
|
11822
|
-
this._errorPositions.add(
|
|
11822
|
+
this._errorPositions.add(path3);
|
|
11823
11823
|
this._errors.push(error);
|
|
11824
11824
|
}
|
|
11825
11825
|
_hasNulledPosition(startPath) {
|
|
11826
|
-
let
|
|
11827
|
-
while (
|
|
11828
|
-
if (this._errorPositions.has(
|
|
11826
|
+
let path3 = startPath;
|
|
11827
|
+
while (path3 !== void 0) {
|
|
11828
|
+
if (this._errorPositions.has(path3)) {
|
|
11829
11829
|
return true;
|
|
11830
11830
|
}
|
|
11831
|
-
|
|
11831
|
+
path3 = path3.prev;
|
|
11832
11832
|
}
|
|
11833
11833
|
return this._errorPositions.has(void 0);
|
|
11834
11834
|
}
|
|
@@ -11977,27 +11977,27 @@ var require_execute = __commonJS({
|
|
|
11977
11977
|
rootType,
|
|
11978
11978
|
operation.selectionSet
|
|
11979
11979
|
);
|
|
11980
|
-
const
|
|
11980
|
+
const path3 = void 0;
|
|
11981
11981
|
switch (operation.operation) {
|
|
11982
11982
|
case _ast.OperationTypeNode.QUERY:
|
|
11983
|
-
return executeFields(exeContext, rootType, rootValue,
|
|
11983
|
+
return executeFields(exeContext, rootType, rootValue, path3, rootFields);
|
|
11984
11984
|
case _ast.OperationTypeNode.MUTATION:
|
|
11985
11985
|
return executeFieldsSerially(
|
|
11986
11986
|
exeContext,
|
|
11987
11987
|
rootType,
|
|
11988
11988
|
rootValue,
|
|
11989
|
-
|
|
11989
|
+
path3,
|
|
11990
11990
|
rootFields
|
|
11991
11991
|
);
|
|
11992
11992
|
case _ast.OperationTypeNode.SUBSCRIPTION:
|
|
11993
|
-
return executeFields(exeContext, rootType, rootValue,
|
|
11993
|
+
return executeFields(exeContext, rootType, rootValue, path3, rootFields);
|
|
11994
11994
|
}
|
|
11995
11995
|
}
|
|
11996
|
-
function executeFieldsSerially(exeContext, parentType, sourceValue,
|
|
11996
|
+
function executeFieldsSerially(exeContext, parentType, sourceValue, path3, fields) {
|
|
11997
11997
|
return (0, _promiseReduce.promiseReduce)(
|
|
11998
11998
|
fields.entries(),
|
|
11999
11999
|
(results, [responseName, fieldNodes]) => {
|
|
12000
|
-
const fieldPath = (0, _Path.addPath)(
|
|
12000
|
+
const fieldPath = (0, _Path.addPath)(path3, responseName, parentType.name);
|
|
12001
12001
|
const result = executeField(
|
|
12002
12002
|
exeContext,
|
|
12003
12003
|
parentType,
|
|
@@ -12020,12 +12020,12 @@ var require_execute = __commonJS({
|
|
|
12020
12020
|
/* @__PURE__ */ Object.create(null)
|
|
12021
12021
|
);
|
|
12022
12022
|
}
|
|
12023
|
-
function executeFields(exeContext, parentType, sourceValue,
|
|
12023
|
+
function executeFields(exeContext, parentType, sourceValue, path3, fields) {
|
|
12024
12024
|
const results = /* @__PURE__ */ Object.create(null);
|
|
12025
12025
|
let containsPromise = false;
|
|
12026
12026
|
try {
|
|
12027
12027
|
for (const [responseName, fieldNodes] of fields.entries()) {
|
|
12028
|
-
const fieldPath = (0, _Path.addPath)(
|
|
12028
|
+
const fieldPath = (0, _Path.addPath)(path3, responseName, parentType.name);
|
|
12029
12029
|
const result = executeField(
|
|
12030
12030
|
exeContext,
|
|
12031
12031
|
parentType,
|
|
@@ -12053,7 +12053,7 @@ var require_execute = __commonJS({
|
|
|
12053
12053
|
}
|
|
12054
12054
|
return (0, _promiseForObject.promiseForObject)(results);
|
|
12055
12055
|
}
|
|
12056
|
-
function executeField(exeContext, parentType, source, fieldNodes,
|
|
12056
|
+
function executeField(exeContext, parentType, source, fieldNodes, path3) {
|
|
12057
12057
|
var _fieldDef$resolve;
|
|
12058
12058
|
const fieldDef = getFieldDef(exeContext.schema, parentType, fieldNodes[0]);
|
|
12059
12059
|
if (!fieldDef) {
|
|
@@ -12066,7 +12066,7 @@ var require_execute = __commonJS({
|
|
|
12066
12066
|
fieldDef,
|
|
12067
12067
|
fieldNodes,
|
|
12068
12068
|
parentType,
|
|
12069
|
-
|
|
12069
|
+
path3
|
|
12070
12070
|
);
|
|
12071
12071
|
try {
|
|
12072
12072
|
const args = (0, _values.getArgumentValues)(
|
|
@@ -12079,7 +12079,7 @@ var require_execute = __commonJS({
|
|
|
12079
12079
|
let completed;
|
|
12080
12080
|
if ((0, _isPromise.isPromise)(result)) {
|
|
12081
12081
|
completed = result.then(
|
|
12082
|
-
(resolved) => completeValue(exeContext, returnType, fieldNodes, info,
|
|
12082
|
+
(resolved) => completeValue(exeContext, returnType, fieldNodes, info, path3, resolved)
|
|
12083
12083
|
);
|
|
12084
12084
|
} else {
|
|
12085
12085
|
completed = completeValue(
|
|
@@ -12087,7 +12087,7 @@ var require_execute = __commonJS({
|
|
|
12087
12087
|
returnType,
|
|
12088
12088
|
fieldNodes,
|
|
12089
12089
|
info,
|
|
12090
|
-
|
|
12090
|
+
path3,
|
|
12091
12091
|
result
|
|
12092
12092
|
);
|
|
12093
12093
|
}
|
|
@@ -12096,9 +12096,9 @@ var require_execute = __commonJS({
|
|
|
12096
12096
|
const error = (0, _locatedError.locatedError)(
|
|
12097
12097
|
rawError,
|
|
12098
12098
|
fieldNodes,
|
|
12099
|
-
(0, _Path.pathToArray)(
|
|
12099
|
+
(0, _Path.pathToArray)(path3)
|
|
12100
12100
|
);
|
|
12101
|
-
return handleFieldError(error, returnType,
|
|
12101
|
+
return handleFieldError(error, returnType, path3, exeContext);
|
|
12102
12102
|
});
|
|
12103
12103
|
}
|
|
12104
12104
|
return completed;
|
|
@@ -12106,18 +12106,18 @@ var require_execute = __commonJS({
|
|
|
12106
12106
|
const error = (0, _locatedError.locatedError)(
|
|
12107
12107
|
rawError,
|
|
12108
12108
|
fieldNodes,
|
|
12109
|
-
(0, _Path.pathToArray)(
|
|
12109
|
+
(0, _Path.pathToArray)(path3)
|
|
12110
12110
|
);
|
|
12111
|
-
return handleFieldError(error, returnType,
|
|
12111
|
+
return handleFieldError(error, returnType, path3, exeContext);
|
|
12112
12112
|
}
|
|
12113
12113
|
}
|
|
12114
|
-
function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType,
|
|
12114
|
+
function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path3) {
|
|
12115
12115
|
return {
|
|
12116
12116
|
fieldName: fieldDef.name,
|
|
12117
12117
|
fieldNodes,
|
|
12118
12118
|
returnType: fieldDef.type,
|
|
12119
12119
|
parentType,
|
|
12120
|
-
path:
|
|
12120
|
+
path: path3,
|
|
12121
12121
|
schema: exeContext.schema,
|
|
12122
12122
|
fragments: exeContext.fragments,
|
|
12123
12123
|
rootValue: exeContext.rootValue,
|
|
@@ -12125,14 +12125,14 @@ var require_execute = __commonJS({
|
|
|
12125
12125
|
variableValues: exeContext.variableValues
|
|
12126
12126
|
};
|
|
12127
12127
|
}
|
|
12128
|
-
function handleFieldError(error, returnType,
|
|
12128
|
+
function handleFieldError(error, returnType, path3, exeContext) {
|
|
12129
12129
|
if ((0, _definition.isNonNullType)(returnType)) {
|
|
12130
12130
|
throw error;
|
|
12131
12131
|
}
|
|
12132
|
-
exeContext.collectedErrors.add(error,
|
|
12132
|
+
exeContext.collectedErrors.add(error, path3);
|
|
12133
12133
|
return null;
|
|
12134
12134
|
}
|
|
12135
|
-
function completeValue(exeContext, returnType, fieldNodes, info,
|
|
12135
|
+
function completeValue(exeContext, returnType, fieldNodes, info, path3, result) {
|
|
12136
12136
|
if (result instanceof Error) {
|
|
12137
12137
|
throw result;
|
|
12138
12138
|
}
|
|
@@ -12142,7 +12142,7 @@ var require_execute = __commonJS({
|
|
|
12142
12142
|
returnType.ofType,
|
|
12143
12143
|
fieldNodes,
|
|
12144
12144
|
info,
|
|
12145
|
-
|
|
12145
|
+
path3,
|
|
12146
12146
|
result
|
|
12147
12147
|
);
|
|
12148
12148
|
if (completed === null) {
|
|
@@ -12161,7 +12161,7 @@ var require_execute = __commonJS({
|
|
|
12161
12161
|
returnType,
|
|
12162
12162
|
fieldNodes,
|
|
12163
12163
|
info,
|
|
12164
|
-
|
|
12164
|
+
path3,
|
|
12165
12165
|
result
|
|
12166
12166
|
);
|
|
12167
12167
|
}
|
|
@@ -12174,7 +12174,7 @@ var require_execute = __commonJS({
|
|
|
12174
12174
|
returnType,
|
|
12175
12175
|
fieldNodes,
|
|
12176
12176
|
info,
|
|
12177
|
-
|
|
12177
|
+
path3,
|
|
12178
12178
|
result
|
|
12179
12179
|
);
|
|
12180
12180
|
}
|
|
@@ -12184,7 +12184,7 @@ var require_execute = __commonJS({
|
|
|
12184
12184
|
returnType,
|
|
12185
12185
|
fieldNodes,
|
|
12186
12186
|
info,
|
|
12187
|
-
|
|
12187
|
+
path3,
|
|
12188
12188
|
result
|
|
12189
12189
|
);
|
|
12190
12190
|
}
|
|
@@ -12193,7 +12193,7 @@ var require_execute = __commonJS({
|
|
|
12193
12193
|
"Cannot complete value of unexpected output type: " + (0, _inspect.inspect)(returnType)
|
|
12194
12194
|
);
|
|
12195
12195
|
}
|
|
12196
|
-
function completeListValue(exeContext, returnType, fieldNodes, info,
|
|
12196
|
+
function completeListValue(exeContext, returnType, fieldNodes, info, path3, result) {
|
|
12197
12197
|
if (!(0, _isIterableObject.isIterableObject)(result)) {
|
|
12198
12198
|
throw new _GraphQLError.GraphQLError(
|
|
12199
12199
|
`Expected Iterable, but did not find one for field "${info.parentType.name}.${info.fieldName}".`
|
|
@@ -12202,7 +12202,7 @@ var require_execute = __commonJS({
|
|
|
12202
12202
|
const itemType = returnType.ofType;
|
|
12203
12203
|
let containsPromise = false;
|
|
12204
12204
|
const completedResults = Array.from(result, (item, index) => {
|
|
12205
|
-
const itemPath = (0, _Path.addPath)(
|
|
12205
|
+
const itemPath = (0, _Path.addPath)(path3, index, void 0);
|
|
12206
12206
|
try {
|
|
12207
12207
|
let completedItem;
|
|
12208
12208
|
if ((0, _isPromise.isPromise)(item)) {
|
|
@@ -12260,7 +12260,7 @@ var require_execute = __commonJS({
|
|
|
12260
12260
|
}
|
|
12261
12261
|
return serializedResult;
|
|
12262
12262
|
}
|
|
12263
|
-
function completeAbstractValue(exeContext, returnType, fieldNodes, info,
|
|
12263
|
+
function completeAbstractValue(exeContext, returnType, fieldNodes, info, path3, result) {
|
|
12264
12264
|
var _returnType$resolveTy;
|
|
12265
12265
|
const resolveTypeFn = (_returnType$resolveTy = returnType.resolveType) !== null && _returnType$resolveTy !== void 0 ? _returnType$resolveTy : exeContext.typeResolver;
|
|
12266
12266
|
const contextValue = exeContext.contextValue;
|
|
@@ -12279,7 +12279,7 @@ var require_execute = __commonJS({
|
|
|
12279
12279
|
),
|
|
12280
12280
|
fieldNodes,
|
|
12281
12281
|
info,
|
|
12282
|
-
|
|
12282
|
+
path3,
|
|
12283
12283
|
result
|
|
12284
12284
|
)
|
|
12285
12285
|
);
|
|
@@ -12296,7 +12296,7 @@ var require_execute = __commonJS({
|
|
|
12296
12296
|
),
|
|
12297
12297
|
fieldNodes,
|
|
12298
12298
|
info,
|
|
12299
|
-
|
|
12299
|
+
path3,
|
|
12300
12300
|
result
|
|
12301
12301
|
);
|
|
12302
12302
|
}
|
|
@@ -12344,7 +12344,7 @@ var require_execute = __commonJS({
|
|
|
12344
12344
|
}
|
|
12345
12345
|
return runtimeType;
|
|
12346
12346
|
}
|
|
12347
|
-
function completeObjectValue(exeContext, returnType, fieldNodes, info,
|
|
12347
|
+
function completeObjectValue(exeContext, returnType, fieldNodes, info, path3, result) {
|
|
12348
12348
|
const subFieldNodes = collectSubfields(exeContext, returnType, fieldNodes);
|
|
12349
12349
|
if (returnType.isTypeOf) {
|
|
12350
12350
|
const isTypeOf = returnType.isTypeOf(result, exeContext.contextValue, info);
|
|
@@ -12357,7 +12357,7 @@ var require_execute = __commonJS({
|
|
|
12357
12357
|
exeContext,
|
|
12358
12358
|
returnType,
|
|
12359
12359
|
result,
|
|
12360
|
-
|
|
12360
|
+
path3,
|
|
12361
12361
|
subFieldNodes
|
|
12362
12362
|
);
|
|
12363
12363
|
});
|
|
@@ -12366,7 +12366,7 @@ var require_execute = __commonJS({
|
|
|
12366
12366
|
throw invalidReturnTypeError(returnType, result, fieldNodes);
|
|
12367
12367
|
}
|
|
12368
12368
|
}
|
|
12369
|
-
return executeFields(exeContext, returnType, result,
|
|
12369
|
+
return executeFields(exeContext, returnType, result, path3, subFieldNodes);
|
|
12370
12370
|
}
|
|
12371
12371
|
function invalidReturnTypeError(returnType, result, fieldNodes) {
|
|
12372
12372
|
return new _GraphQLError.GraphQLError(
|
|
@@ -12448,7 +12448,7 @@ var require_graphql = __commonJS({
|
|
|
12448
12448
|
var _validate2 = require_validate2();
|
|
12449
12449
|
var _execute = require_execute();
|
|
12450
12450
|
function graphql(args) {
|
|
12451
|
-
return new Promise((
|
|
12451
|
+
return new Promise((resolve6) => resolve6(graphqlImpl(args)));
|
|
12452
12452
|
}
|
|
12453
12453
|
function graphqlSync(args) {
|
|
12454
12454
|
const result = graphqlImpl(args);
|
|
@@ -13450,13 +13450,13 @@ var require_subscribe = __commonJS({
|
|
|
13450
13450
|
}
|
|
13451
13451
|
);
|
|
13452
13452
|
}
|
|
13453
|
-
const
|
|
13453
|
+
const path3 = (0, _Path.addPath)(void 0, responseName, rootType.name);
|
|
13454
13454
|
const info = (0, _execute.buildResolveInfo)(
|
|
13455
13455
|
exeContext,
|
|
13456
13456
|
fieldDef,
|
|
13457
13457
|
fieldNodes,
|
|
13458
13458
|
rootType,
|
|
13459
|
-
|
|
13459
|
+
path3
|
|
13460
13460
|
);
|
|
13461
13461
|
try {
|
|
13462
13462
|
var _fieldDef$subscribe;
|
|
@@ -13476,7 +13476,7 @@ var require_subscribe = __commonJS({
|
|
|
13476
13476
|
throw (0, _locatedError.locatedError)(
|
|
13477
13477
|
error,
|
|
13478
13478
|
fieldNodes,
|
|
13479
|
-
(0, _Path.pathToArray)(
|
|
13479
|
+
(0, _Path.pathToArray)(path3)
|
|
13480
13480
|
);
|
|
13481
13481
|
}
|
|
13482
13482
|
}
|
|
@@ -17797,7 +17797,7 @@ var require_graphql2 = __commonJS({
|
|
|
17797
17797
|
});
|
|
17798
17798
|
|
|
17799
17799
|
// src/cli/index.ts
|
|
17800
|
-
import { Command as
|
|
17800
|
+
import { Command as Command16 } from "commander";
|
|
17801
17801
|
|
|
17802
17802
|
// src/cli/commands/bootstrap.ts
|
|
17803
17803
|
import { Command, Option as Option2 } from "commander";
|
|
@@ -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);
|
|
@@ -18405,6 +18412,13 @@ var StackTerminationProtectionError = class _StackTerminationProtectionError ext
|
|
|
18405
18412
|
Object.setPrototypeOf(this, _StackTerminationProtectionError.prototype);
|
|
18406
18413
|
}
|
|
18407
18414
|
};
|
|
18415
|
+
var RouteDiscoveryError = class _RouteDiscoveryError extends CdkdError {
|
|
18416
|
+
constructor(message, cause) {
|
|
18417
|
+
super(message, "ROUTE_DISCOVERY_ERROR", cause);
|
|
18418
|
+
this.name = "RouteDiscoveryError";
|
|
18419
|
+
Object.setPrototypeOf(this, _RouteDiscoveryError.prototype);
|
|
18420
|
+
}
|
|
18421
|
+
};
|
|
18408
18422
|
function isCdkdError(error) {
|
|
18409
18423
|
return error instanceof CdkdError;
|
|
18410
18424
|
}
|
|
@@ -18855,7 +18869,7 @@ var IntrinsicFunctionResolver = class {
|
|
|
18855
18869
|
this.logger.debug(
|
|
18856
18870
|
`VPC ${physicalId} IPv6 CIDR still associating (attempt ${attempt}/${maxAttempts}), waiting...`
|
|
18857
18871
|
);
|
|
18858
|
-
await new Promise((
|
|
18872
|
+
await new Promise((resolve6) => setTimeout(resolve6, 2e3));
|
|
18859
18873
|
}
|
|
18860
18874
|
this.logger.warn(
|
|
18861
18875
|
`VPC ${physicalId} IPv6 CIDR did not reach 'associated' state after ${maxAttempts} attempts`
|
|
@@ -19740,7 +19754,7 @@ var DagExecutor = class {
|
|
|
19740
19754
|
async execute(concurrency, fn, cancelled = () => false) {
|
|
19741
19755
|
let active = 0;
|
|
19742
19756
|
const errors = [];
|
|
19743
|
-
return new Promise((
|
|
19757
|
+
return new Promise((resolve6, reject) => {
|
|
19744
19758
|
const dispatch = () => {
|
|
19745
19759
|
let changed = true;
|
|
19746
19760
|
while (changed) {
|
|
@@ -19802,7 +19816,7 @@ var DagExecutor = class {
|
|
|
19802
19816
|
);
|
|
19803
19817
|
return;
|
|
19804
19818
|
}
|
|
19805
|
-
|
|
19819
|
+
resolve6();
|
|
19806
19820
|
}
|
|
19807
19821
|
};
|
|
19808
19822
|
dispatch();
|
|
@@ -20483,7 +20497,7 @@ Error: ${err.message || "Unknown error"}`,
|
|
|
20483
20497
|
* Sleep for specified milliseconds
|
|
20484
20498
|
*/
|
|
20485
20499
|
sleep(ms) {
|
|
20486
|
-
return new Promise((
|
|
20500
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
20487
20501
|
}
|
|
20488
20502
|
/**
|
|
20489
20503
|
* Check if a resource type is supported by Cloud Control API
|
|
@@ -21217,7 +21231,7 @@ var CustomResourceProvider = class _CustomResourceProvider {
|
|
|
21217
21231
|
return result;
|
|
21218
21232
|
}
|
|
21219
21233
|
sleep(ms) {
|
|
21220
|
-
return new Promise((
|
|
21234
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
21221
21235
|
}
|
|
21222
21236
|
/**
|
|
21223
21237
|
* Adopt an existing custom resource into cdkd state.
|
|
@@ -21647,7 +21661,7 @@ function isRetryableTransientError(error, message) {
|
|
|
21647
21661
|
}
|
|
21648
21662
|
|
|
21649
21663
|
// src/deployment/retry.ts
|
|
21650
|
-
var defaultSleep = (ms) => new Promise((
|
|
21664
|
+
var defaultSleep = (ms) => new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
21651
21665
|
async function withRetry(operation, logicalId, opts = {}) {
|
|
21652
21666
|
const maxRetries = opts.maxRetries ?? 8;
|
|
21653
21667
|
const initialDelayMs = opts.initialDelayMs ?? 1e3;
|
|
@@ -21702,7 +21716,7 @@ function validateOptions(opts) {
|
|
|
21702
21716
|
async function withResourceDeadline(operation, opts) {
|
|
21703
21717
|
validateOptions(opts);
|
|
21704
21718
|
const startedAt = Date.now();
|
|
21705
|
-
return new Promise((
|
|
21719
|
+
return new Promise((resolve6, reject) => {
|
|
21706
21720
|
let settled = false;
|
|
21707
21721
|
let warnTimer;
|
|
21708
21722
|
let timeoutTimer;
|
|
@@ -21742,7 +21756,7 @@ async function withResourceDeadline(operation, opts) {
|
|
|
21742
21756
|
return;
|
|
21743
21757
|
settled = true;
|
|
21744
21758
|
cleanup();
|
|
21745
|
-
|
|
21759
|
+
resolve6(value);
|
|
21746
21760
|
},
|
|
21747
21761
|
(err) => {
|
|
21748
21762
|
if (settled)
|
|
@@ -23313,6 +23327,41 @@ var contextOptions = [
|
|
|
23313
23327
|
"Set context values (can be specified multiple times)"
|
|
23314
23328
|
)
|
|
23315
23329
|
];
|
|
23330
|
+
var IAM_ROLE_ARN_REGEX = /^arn:[^:]+:iam::\d+:role\//;
|
|
23331
|
+
function parseAssumeRoleToken(raw, previous) {
|
|
23332
|
+
const acc = previous ?? { perLambda: {} };
|
|
23333
|
+
if (!acc.perLambda)
|
|
23334
|
+
acc.perLambda = {};
|
|
23335
|
+
const eqIndex = raw.indexOf("=");
|
|
23336
|
+
if (eqIndex === -1) {
|
|
23337
|
+
if (!IAM_ROLE_ARN_REGEX.test(raw)) {
|
|
23338
|
+
throw new Error(
|
|
23339
|
+
`Invalid --assume-role value "${raw}": expected an IAM role ARN like arn:aws:iam::123456789012:role/MyRole, or LogicalId=<arn>.`
|
|
23340
|
+
);
|
|
23341
|
+
}
|
|
23342
|
+
acc.globalArn = raw;
|
|
23343
|
+
return acc;
|
|
23344
|
+
}
|
|
23345
|
+
const logicalId = raw.substring(0, eqIndex).trim();
|
|
23346
|
+
const arn = raw.substring(eqIndex + 1).trim();
|
|
23347
|
+
if (!/^[A-Za-z][A-Za-z0-9]*$/.test(logicalId)) {
|
|
23348
|
+
throw new Error(
|
|
23349
|
+
`Invalid --assume-role value "${raw}": left-hand side "${logicalId}" must be a CloudFormation logical ID (alphanumeric, leading letter).`
|
|
23350
|
+
);
|
|
23351
|
+
}
|
|
23352
|
+
if (!IAM_ROLE_ARN_REGEX.test(arn)) {
|
|
23353
|
+
throw new Error(
|
|
23354
|
+
`Invalid --assume-role value "${raw}": right-hand side "${arn}" must be an IAM role ARN like arn:aws:iam::123456789012:role/MyRole.`
|
|
23355
|
+
);
|
|
23356
|
+
}
|
|
23357
|
+
acc.perLambda[logicalId] = arn;
|
|
23358
|
+
return acc;
|
|
23359
|
+
}
|
|
23360
|
+
function effectiveAssumeRoleArn(logicalId, opt) {
|
|
23361
|
+
if (!opt)
|
|
23362
|
+
return void 0;
|
|
23363
|
+
return opt.perLambda?.[logicalId] ?? opt.globalArn;
|
|
23364
|
+
}
|
|
23316
23365
|
var destroyOptions = [
|
|
23317
23366
|
new Option("-f, --force", "Do not ask for confirmation before destroying the stacks").default(
|
|
23318
23367
|
false
|
|
@@ -23436,11 +23485,11 @@ async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
|
|
|
23436
23485
|
return syncResult;
|
|
23437
23486
|
const logger = getLogger();
|
|
23438
23487
|
logger.debug("No state bucket specified, resolving default from account...");
|
|
23439
|
-
const { GetCallerIdentityCommand:
|
|
23488
|
+
const { GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
23440
23489
|
const { S3Client: S3Client12 } = await import("@aws-sdk/client-s3");
|
|
23441
23490
|
const { getAwsClients: getAwsClients2 } = await Promise.resolve().then(() => (init_aws_clients(), aws_clients_exports));
|
|
23442
23491
|
const awsClients = getAwsClients2();
|
|
23443
|
-
const identity = await awsClients.sts.send(new
|
|
23492
|
+
const identity = await awsClients.sts.send(new GetCallerIdentityCommand12({}));
|
|
23444
23493
|
const accountId = identity.Account;
|
|
23445
23494
|
const newName = getDefaultStateBucketName(accountId);
|
|
23446
23495
|
const legacyName = getLegacyStateBucketName(accountId, region);
|
|
@@ -23742,7 +23791,7 @@ var AppExecutor = class {
|
|
|
23742
23791
|
* Spawn subprocess and wait for completion
|
|
23743
23792
|
*/
|
|
23744
23793
|
spawn(commandLine, env) {
|
|
23745
|
-
return new Promise((
|
|
23794
|
+
return new Promise((resolve6, reject) => {
|
|
23746
23795
|
const proc = spawn(commandLine, {
|
|
23747
23796
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23748
23797
|
shell: true,
|
|
@@ -23768,7 +23817,7 @@ var AppExecutor = class {
|
|
|
23768
23817
|
});
|
|
23769
23818
|
proc.on("close", (code) => {
|
|
23770
23819
|
if (code === 0) {
|
|
23771
|
-
|
|
23820
|
+
resolve6();
|
|
23772
23821
|
} else {
|
|
23773
23822
|
const stderr = stderrChunks.join("\n");
|
|
23774
23823
|
reject(
|
|
@@ -24480,8 +24529,8 @@ var CcApiContextProvider = class {
|
|
|
24480
24529
|
/**
|
|
24481
24530
|
* Get nested property value using dot notation
|
|
24482
24531
|
*/
|
|
24483
|
-
getNestedProperty(obj,
|
|
24484
|
-
const parts =
|
|
24532
|
+
getNestedProperty(obj, path3) {
|
|
24533
|
+
const parts = path3.split(".");
|
|
24485
24534
|
let current = obj;
|
|
24486
24535
|
for (const part of parts) {
|
|
24487
24536
|
if (current === null || current === void 0 || typeof current !== "object") {
|
|
@@ -25290,11 +25339,11 @@ var FileAssetPublisher = class {
|
|
|
25290
25339
|
*/
|
|
25291
25340
|
async uploadZip(client, dirPath, bucket, key) {
|
|
25292
25341
|
const archiver = await import("archiver");
|
|
25293
|
-
const body = await new Promise((
|
|
25342
|
+
const body = await new Promise((resolve6, reject) => {
|
|
25294
25343
|
const chunks = [];
|
|
25295
25344
|
const archive = archiver.default("zip", { zlib: { level: 9 } });
|
|
25296
25345
|
archive.on("data", (chunk) => chunks.push(chunk));
|
|
25297
|
-
archive.on("end", () =>
|
|
25346
|
+
archive.on("end", () => resolve6(Buffer.concat(chunks)));
|
|
25298
25347
|
archive.on("error", reject);
|
|
25299
25348
|
const stat = statSync2(dirPath);
|
|
25300
25349
|
if (stat.isDirectory()) {
|
|
@@ -25322,14 +25371,57 @@ var FileAssetPublisher = class {
|
|
|
25322
25371
|
};
|
|
25323
25372
|
|
|
25324
25373
|
// src/assets/docker-asset-publisher.ts
|
|
25325
|
-
import { execFile, spawn as spawn2 } from "node:child_process";
|
|
25326
|
-
import { promisify } from "node:util";
|
|
25374
|
+
import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
|
|
25375
|
+
import { promisify as promisify2 } from "node:util";
|
|
25327
25376
|
import {
|
|
25328
25377
|
ECRClient,
|
|
25329
25378
|
GetAuthorizationTokenCommand,
|
|
25330
25379
|
DescribeImagesCommand as DescribeImagesCommand2
|
|
25331
25380
|
} from "@aws-sdk/client-ecr";
|
|
25381
|
+
|
|
25382
|
+
// src/assets/docker-build.ts
|
|
25383
|
+
import { execFile } from "node:child_process";
|
|
25384
|
+
import { promisify } from "node:util";
|
|
25332
25385
|
var execFileAsync = promisify(execFile);
|
|
25386
|
+
async function buildDockerImage(asset, cdkOutDir, tag, options) {
|
|
25387
|
+
const logger = getLogger().child("docker-build");
|
|
25388
|
+
const args = ["build", "-t", tag];
|
|
25389
|
+
if (options.platform) {
|
|
25390
|
+
args.push("--platform", options.platform);
|
|
25391
|
+
}
|
|
25392
|
+
if (asset.source.dockerFile) {
|
|
25393
|
+
args.push("-f", asset.source.dockerFile);
|
|
25394
|
+
}
|
|
25395
|
+
if (asset.source.dockerBuildArgs) {
|
|
25396
|
+
for (const [key, value] of Object.entries(asset.source.dockerBuildArgs)) {
|
|
25397
|
+
args.push("--build-arg", `${key}=${value}`);
|
|
25398
|
+
}
|
|
25399
|
+
}
|
|
25400
|
+
if (asset.source.dockerBuildTarget) {
|
|
25401
|
+
args.push("--target", asset.source.dockerBuildTarget);
|
|
25402
|
+
}
|
|
25403
|
+
if (asset.source.dockerOutputs) {
|
|
25404
|
+
for (const output of asset.source.dockerOutputs) {
|
|
25405
|
+
args.push("--output", output);
|
|
25406
|
+
}
|
|
25407
|
+
}
|
|
25408
|
+
const contextDir = `${cdkOutDir}/${asset.source.directory}`;
|
|
25409
|
+
args.push(contextDir);
|
|
25410
|
+
logger.debug(`docker ${args.join(" ")}`);
|
|
25411
|
+
try {
|
|
25412
|
+
await execFileAsync("docker", args, {
|
|
25413
|
+
maxBuffer: 50 * 1024 * 1024
|
|
25414
|
+
// 50MB for build output
|
|
25415
|
+
});
|
|
25416
|
+
} catch (error) {
|
|
25417
|
+
const err = error;
|
|
25418
|
+
const stderr = err.stderr || err.message || String(error);
|
|
25419
|
+
throw options.wrapError(stderr);
|
|
25420
|
+
}
|
|
25421
|
+
}
|
|
25422
|
+
|
|
25423
|
+
// src/assets/docker-asset-publisher.ts
|
|
25424
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
25333
25425
|
var DockerAssetPublisher = class {
|
|
25334
25426
|
logger = getLogger().child("DockerAssetPublisher");
|
|
25335
25427
|
/**
|
|
@@ -25412,38 +25504,17 @@ var DockerAssetPublisher = class {
|
|
|
25412
25504
|
}
|
|
25413
25505
|
}
|
|
25414
25506
|
/**
|
|
25415
|
-
* Build Docker image
|
|
25507
|
+
* Build Docker image — delegates to the shared `buildDockerImage`
|
|
25508
|
+
* helper so this code path stays in sync with `cdkd local invoke`'s
|
|
25509
|
+
* container-Lambda build path. `--platform` is currently not threaded
|
|
25510
|
+
* through here (publish-assets has no Architectures hint to consult);
|
|
25511
|
+
* a follow-up can lift this once the asset manifest carries a
|
|
25512
|
+
* platform field.
|
|
25416
25513
|
*/
|
|
25417
25514
|
async buildImage(asset, cdkOutputDir, tag) {
|
|
25418
|
-
|
|
25419
|
-
|
|
25420
|
-
|
|
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
|
-
}
|
|
25515
|
+
await buildDockerImage(asset, cdkOutputDir, tag, {
|
|
25516
|
+
wrapError: (stderr) => new AssetError(`Docker build failed: ${stderr}`)
|
|
25517
|
+
});
|
|
25447
25518
|
}
|
|
25448
25519
|
/**
|
|
25449
25520
|
* Authenticate with ECR
|
|
@@ -25457,7 +25528,7 @@ var DockerAssetPublisher = class {
|
|
|
25457
25528
|
const token = Buffer.from(authData.authorizationToken, "base64").toString();
|
|
25458
25529
|
const [username, password] = token.split(":");
|
|
25459
25530
|
const endpoint = authData.proxyEndpoint || `https://${accountId}.dkr.ecr.${region}.amazonaws.com`;
|
|
25460
|
-
await new Promise((
|
|
25531
|
+
await new Promise((resolve6, reject) => {
|
|
25461
25532
|
const proc = spawn2(
|
|
25462
25533
|
"docker",
|
|
25463
25534
|
["login", "--username", username, "--password-stdin", endpoint],
|
|
@@ -25471,7 +25542,7 @@ var DockerAssetPublisher = class {
|
|
|
25471
25542
|
});
|
|
25472
25543
|
proc.on("close", (code) => {
|
|
25473
25544
|
if (code === 0) {
|
|
25474
|
-
|
|
25545
|
+
resolve6();
|
|
25475
25546
|
} else {
|
|
25476
25547
|
reject(new AssetError(`ECR login failed: ${stderr.trim()}`));
|
|
25477
25548
|
}
|
|
@@ -25487,7 +25558,7 @@ var DockerAssetPublisher = class {
|
|
|
25487
25558
|
* Tag Docker image
|
|
25488
25559
|
*/
|
|
25489
25560
|
async tagImage(source, target) {
|
|
25490
|
-
await
|
|
25561
|
+
await execFileAsync2("docker", ["tag", source, target]);
|
|
25491
25562
|
}
|
|
25492
25563
|
/**
|
|
25493
25564
|
* Push Docker image
|
|
@@ -25495,7 +25566,7 @@ var DockerAssetPublisher = class {
|
|
|
25495
25566
|
async pushImage(uri) {
|
|
25496
25567
|
this.logger.debug(`Pushing: ${uri}`);
|
|
25497
25568
|
try {
|
|
25498
|
-
await
|
|
25569
|
+
await execFileAsync2("docker", ["push", uri], {
|
|
25499
25570
|
maxBuffer: 50 * 1024 * 1024
|
|
25500
25571
|
});
|
|
25501
25572
|
} catch (error) {
|
|
@@ -25524,7 +25595,7 @@ var WorkGraph = class {
|
|
|
25524
25595
|
async execute(concurrency, fn) {
|
|
25525
25596
|
const active = { "asset-build": 0, "asset-publish": 0, stack: 0 };
|
|
25526
25597
|
const errors = [];
|
|
25527
|
-
return new Promise((
|
|
25598
|
+
return new Promise((resolve6, reject) => {
|
|
25528
25599
|
const dispatch = () => {
|
|
25529
25600
|
const ready = [];
|
|
25530
25601
|
for (const node of this.nodes.values()) {
|
|
@@ -25596,7 +25667,7 @@ ${msg}`
|
|
|
25596
25667
|
);
|
|
25597
25668
|
return;
|
|
25598
25669
|
}
|
|
25599
|
-
|
|
25670
|
+
resolve6();
|
|
25600
25671
|
}
|
|
25601
25672
|
};
|
|
25602
25673
|
dispatch();
|
|
@@ -25718,9 +25789,9 @@ var AssetPublisher = class {
|
|
|
25718
25789
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
25719
25790
|
let accountId = options.accountId;
|
|
25720
25791
|
if (!accountId) {
|
|
25721
|
-
const { STSClient:
|
|
25722
|
-
const stsClient = new
|
|
25723
|
-
const identity = await stsClient.send(new
|
|
25792
|
+
const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
25793
|
+
const stsClient = new STSClient11({ region });
|
|
25794
|
+
const identity = await stsClient.send(new GetCallerIdentityCommand12({}));
|
|
25724
25795
|
accountId = identity.Account;
|
|
25725
25796
|
stsClient.destroy();
|
|
25726
25797
|
}
|
|
@@ -26587,7 +26658,7 @@ var LockManager = class {
|
|
|
26587
26658
|
this.logger.info(
|
|
26588
26659
|
`Stack '${stackName}' (${region}) is locked by ${lockInfo2.owner}${lockInfo2.operation ? ` (operation: ${lockInfo2.operation})` : ""}. Lock expires in ${this.formatDuration(remainingMs)}. Retrying in ${this.formatDuration(retryDelay)}... (attempt ${attempt + 1}/${maxRetries})`
|
|
26589
26660
|
);
|
|
26590
|
-
await new Promise((
|
|
26661
|
+
await new Promise((resolve6) => setTimeout(resolve6, retryDelay));
|
|
26591
26662
|
continue;
|
|
26592
26663
|
}
|
|
26593
26664
|
}
|
|
@@ -26835,11 +26906,11 @@ var DagBuilder = class {
|
|
|
26835
26906
|
const cycles = [];
|
|
26836
26907
|
const visited = /* @__PURE__ */ new Set();
|
|
26837
26908
|
const recursionStack = /* @__PURE__ */ new Set();
|
|
26838
|
-
const
|
|
26909
|
+
const path3 = [];
|
|
26839
26910
|
const dfs = (node) => {
|
|
26840
26911
|
visited.add(node);
|
|
26841
26912
|
recursionStack.add(node);
|
|
26842
|
-
|
|
26913
|
+
path3.push(node);
|
|
26843
26914
|
const successors = graph.successors(node) || [];
|
|
26844
26915
|
for (const successor of successors) {
|
|
26845
26916
|
if (!visited.has(successor)) {
|
|
@@ -26847,14 +26918,14 @@ var DagBuilder = class {
|
|
|
26847
26918
|
return true;
|
|
26848
26919
|
}
|
|
26849
26920
|
} else if (recursionStack.has(successor)) {
|
|
26850
|
-
const cycleStart =
|
|
26851
|
-
const cycle =
|
|
26921
|
+
const cycleStart = path3.indexOf(successor);
|
|
26922
|
+
const cycle = path3.slice(cycleStart);
|
|
26852
26923
|
cycle.push(successor);
|
|
26853
26924
|
cycles.push(cycle);
|
|
26854
26925
|
return true;
|
|
26855
26926
|
}
|
|
26856
26927
|
}
|
|
26857
|
-
|
|
26928
|
+
path3.pop();
|
|
26858
26929
|
recursionStack.delete(node);
|
|
26859
26930
|
return false;
|
|
26860
26931
|
};
|
|
@@ -28882,13 +28953,13 @@ var IAMInstanceProfileProvider = class {
|
|
|
28882
28953
|
properties["InstanceProfileName"] || logicalId,
|
|
28883
28954
|
{ maxLength: 128 }
|
|
28884
28955
|
);
|
|
28885
|
-
const
|
|
28956
|
+
const path3 = properties["Path"] || "/";
|
|
28886
28957
|
const roles = properties["Roles"];
|
|
28887
28958
|
try {
|
|
28888
28959
|
const response = await this.iamClient.send(
|
|
28889
28960
|
new CreateInstanceProfileCommand({
|
|
28890
28961
|
InstanceProfileName: instanceProfileName,
|
|
28891
|
-
Path:
|
|
28962
|
+
Path: path3
|
|
28892
28963
|
})
|
|
28893
28964
|
);
|
|
28894
28965
|
this.logger.debug(`Created IAM instance profile: ${instanceProfileName}`);
|
|
@@ -35081,7 +35152,7 @@ var LambdaFunctionProvider = class {
|
|
|
35081
35152
|
return enis;
|
|
35082
35153
|
}
|
|
35083
35154
|
sleep(ms) {
|
|
35084
|
-
return new Promise((
|
|
35155
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
35085
35156
|
}
|
|
35086
35157
|
/**
|
|
35087
35158
|
* Build Lambda Code parameter from CDK properties
|
|
@@ -36958,7 +37029,7 @@ var DynamoDBTableProvider = class {
|
|
|
36958
37029
|
if (status !== "CREATING") {
|
|
36959
37030
|
throw new Error(`Unexpected table status: ${status}`);
|
|
36960
37031
|
}
|
|
36961
|
-
await new Promise((
|
|
37032
|
+
await new Promise((resolve6) => setTimeout(resolve6, 1e3));
|
|
36962
37033
|
}
|
|
36963
37034
|
throw new Error(`Table ${tableName} did not reach ACTIVE status within ${maxAttempts} seconds`);
|
|
36964
37035
|
}
|
|
@@ -36978,7 +37049,7 @@ var DynamoDBTableProvider = class {
|
|
|
36978
37049
|
if (status === "ACTIVE") {
|
|
36979
37050
|
return;
|
|
36980
37051
|
}
|
|
36981
|
-
await new Promise((
|
|
37052
|
+
await new Promise((resolve6) => setTimeout(resolve6, 1e3));
|
|
36982
37053
|
}
|
|
36983
37054
|
throw new Error(
|
|
36984
37055
|
`Table ${tableName} did not reach ACTIVE status within ${maxAttempts} seconds after UpdateTable`
|
|
@@ -40158,7 +40229,7 @@ var EC2Provider = class {
|
|
|
40158
40229
|
this.logger.debug(
|
|
40159
40230
|
`VPC ${physicalId} has dependencies (attempt ${attempt}/${maxAttempts}), retrying in ${attempt * 5}s...`
|
|
40160
40231
|
);
|
|
40161
|
-
await new Promise((
|
|
40232
|
+
await new Promise((resolve6) => setTimeout(resolve6, attempt * 5e3));
|
|
40162
40233
|
continue;
|
|
40163
40234
|
}
|
|
40164
40235
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -40322,7 +40393,7 @@ var EC2Provider = class {
|
|
|
40322
40393
|
this.logger.debug(
|
|
40323
40394
|
`Subnet ${physicalId} has dependencies (attempt ${attempt}/${maxAttempts}), retrying in ${attempt * 5}s...`
|
|
40324
40395
|
);
|
|
40325
|
-
await new Promise((
|
|
40396
|
+
await new Promise((resolve6) => setTimeout(resolve6, attempt * 5e3));
|
|
40326
40397
|
continue;
|
|
40327
40398
|
}
|
|
40328
40399
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -41080,7 +41151,7 @@ var EC2Provider = class {
|
|
|
41080
41151
|
this.logger.debug(
|
|
41081
41152
|
`SecurityGroup ${physicalId} has dependent objects (attempt ${attempt}/${maxAttempts}), retrying in ${attempt * 5}s...`
|
|
41082
41153
|
);
|
|
41083
|
-
await new Promise((
|
|
41154
|
+
await new Promise((resolve6) => setTimeout(resolve6, attempt * 5e3));
|
|
41084
41155
|
continue;
|
|
41085
41156
|
}
|
|
41086
41157
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -42024,7 +42095,7 @@ var EC2Provider = class {
|
|
|
42024
42095
|
* `setTimeout` globally.
|
|
42025
42096
|
*/
|
|
42026
42097
|
sleep(ms) {
|
|
42027
|
-
return new Promise((
|
|
42098
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
42028
42099
|
}
|
|
42029
42100
|
/**
|
|
42030
42101
|
* Check if an error indicates the resource was not found
|
|
@@ -43305,13 +43376,13 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
43305
43376
|
{ key: "IdentityValidationExpression", path: "/identityValidationExpression" },
|
|
43306
43377
|
{ key: "AuthorizerResultTtlInSeconds", path: "/authorizerResultTtlInSeconds" }
|
|
43307
43378
|
];
|
|
43308
|
-
for (const { key, path:
|
|
43379
|
+
for (const { key, path: path3 } of primitiveFields) {
|
|
43309
43380
|
const newVal = properties[key];
|
|
43310
43381
|
const prevVal = previousProperties[key];
|
|
43311
43382
|
if (newVal !== prevVal) {
|
|
43312
43383
|
patchOperations.push({
|
|
43313
43384
|
op: "replace",
|
|
43314
|
-
path:
|
|
43385
|
+
path: path3,
|
|
43315
43386
|
value: newVal !== void 0 ? String(newVal) : ""
|
|
43316
43387
|
});
|
|
43317
43388
|
}
|
|
@@ -43947,13 +44018,13 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
43947
44018
|
{ key: "OperationName", path: "/operationName" },
|
|
43948
44019
|
{ key: "RequestValidatorId", path: "/requestValidatorId" }
|
|
43949
44020
|
];
|
|
43950
|
-
for (const { key, path:
|
|
44021
|
+
for (const { key, path: path3 } of primitiveFields) {
|
|
43951
44022
|
const newVal = properties[key];
|
|
43952
44023
|
const prevVal = previousProperties[key];
|
|
43953
44024
|
if (newVal !== prevVal) {
|
|
43954
44025
|
patchOperations.push({
|
|
43955
44026
|
op: "replace",
|
|
43956
|
-
path:
|
|
44027
|
+
path: path3,
|
|
43957
44028
|
value: newVal !== void 0 ? String(newVal) : ""
|
|
43958
44029
|
});
|
|
43959
44030
|
}
|
|
@@ -44124,7 +44195,7 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
44124
44195
|
* Sleep for specified milliseconds
|
|
44125
44196
|
*/
|
|
44126
44197
|
sleep(ms) {
|
|
44127
|
-
return new Promise((
|
|
44198
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
44128
44199
|
}
|
|
44129
44200
|
/**
|
|
44130
44201
|
* Convert CloudFormation Tags (Array<{Key, Value}>) to SDK tags (Record<string, string>).
|
|
@@ -44326,12 +44397,12 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
44326
44397
|
function appendMapPatchOps(ops, basePath, next, prev) {
|
|
44327
44398
|
const escape = (k) => k.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
44328
44399
|
for (const [key, val] of Object.entries(next)) {
|
|
44329
|
-
const
|
|
44400
|
+
const path3 = `${basePath}/${escape(key)}`;
|
|
44330
44401
|
const stringValue = String(val);
|
|
44331
44402
|
if (!(key in prev)) {
|
|
44332
|
-
ops.push({ op: "add", path:
|
|
44403
|
+
ops.push({ op: "add", path: path3, value: stringValue });
|
|
44333
44404
|
} else if (String(prev[key]) !== stringValue) {
|
|
44334
|
-
ops.push({ op: "replace", path:
|
|
44405
|
+
ops.push({ op: "replace", path: path3, value: stringValue });
|
|
44335
44406
|
}
|
|
44336
44407
|
}
|
|
44337
44408
|
for (const key of Object.keys(prev)) {
|
|
@@ -46016,7 +46087,7 @@ var CloudFrontDistributionProvider = class {
|
|
|
46016
46087
|
);
|
|
46017
46088
|
const sleepEnd = Date.now() + delay2;
|
|
46018
46089
|
while (Date.now() < sleepEnd && !interrupted) {
|
|
46019
|
-
await new Promise((
|
|
46090
|
+
await new Promise((resolve6) => setTimeout(resolve6, 1e3));
|
|
46020
46091
|
}
|
|
46021
46092
|
delay2 = Math.min(delay2 * 1.5, maxDelay);
|
|
46022
46093
|
}
|
|
@@ -46136,17 +46207,17 @@ var CloudFrontDistributionProvider = class {
|
|
|
46136
46207
|
/**
|
|
46137
46208
|
* Apply Quantity wrapping at a nested path (e.g., "ForwardedValues.Headers").
|
|
46138
46209
|
*/
|
|
46139
|
-
applyQuantityAtPath(obj,
|
|
46140
|
-
if (
|
|
46210
|
+
applyQuantityAtPath(obj, path3) {
|
|
46211
|
+
if (path3.length === 0)
|
|
46141
46212
|
return;
|
|
46142
|
-
if (
|
|
46143
|
-
const key =
|
|
46213
|
+
if (path3.length === 1) {
|
|
46214
|
+
const key = path3[0];
|
|
46144
46215
|
if (obj[key] !== void 0) {
|
|
46145
46216
|
obj[key] = this.wrapWithQuantity(obj[key]);
|
|
46146
46217
|
}
|
|
46147
46218
|
return;
|
|
46148
46219
|
}
|
|
46149
|
-
const [head, ...rest] =
|
|
46220
|
+
const [head, ...rest] = path3;
|
|
46150
46221
|
const headKey = head;
|
|
46151
46222
|
if (obj[headKey] && typeof obj[headKey] === "object") {
|
|
46152
46223
|
const nested = { ...obj[headKey] };
|
|
@@ -49828,7 +49899,7 @@ var RDSProvider = class {
|
|
|
49828
49899
|
throw new Error(`Timed out waiting for DBInstance ${dbInstanceIdentifier} to be deleted`);
|
|
49829
49900
|
}
|
|
49830
49901
|
sleep(ms) {
|
|
49831
|
-
return new Promise((
|
|
49902
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
49832
49903
|
}
|
|
49833
49904
|
/**
|
|
49834
49905
|
* Adopt an existing RDS resource into cdkd state.
|
|
@@ -50813,7 +50884,7 @@ var DocDBProvider = class {
|
|
|
50813
50884
|
throw new Error(`Timed out waiting for DocDB DBInstance ${dbInstanceIdentifier} to be deleted`);
|
|
50814
50885
|
}
|
|
50815
50886
|
sleep(ms) {
|
|
50816
|
-
return new Promise((
|
|
50887
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
50817
50888
|
}
|
|
50818
50889
|
/**
|
|
50819
50890
|
* Adopt an existing DocDB resource into cdkd state.
|
|
@@ -51803,7 +51874,7 @@ var NeptuneProvider = class {
|
|
|
51803
51874
|
);
|
|
51804
51875
|
}
|
|
51805
51876
|
sleep(ms) {
|
|
51806
|
-
return new Promise((
|
|
51877
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
51807
51878
|
}
|
|
51808
51879
|
/**
|
|
51809
51880
|
* Adopt an existing Neptune resource into cdkd state.
|
|
@@ -54343,7 +54414,7 @@ var ElastiCacheProvider = class {
|
|
|
54343
54414
|
throw new Error(`Timed out waiting for CacheCluster ${cacheClusterId} to be deleted`);
|
|
54344
54415
|
}
|
|
54345
54416
|
sleep(ms) {
|
|
54346
|
-
return new Promise((
|
|
54417
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
54347
54418
|
}
|
|
54348
54419
|
/**
|
|
54349
54420
|
* Read the AWS-current ElastiCache resource configuration in CFn-property shape.
|
|
@@ -55058,7 +55129,7 @@ var ServiceDiscoveryProvider = class {
|
|
|
55058
55129
|
logicalId
|
|
55059
55130
|
);
|
|
55060
55131
|
}
|
|
55061
|
-
await new Promise((
|
|
55132
|
+
await new Promise((resolve6) => setTimeout(resolve6, delay2));
|
|
55062
55133
|
delay2 = Math.min(delay2 * 2, 1e4);
|
|
55063
55134
|
}
|
|
55064
55135
|
throw new ProvisioningError(
|
|
@@ -59583,7 +59654,7 @@ var KinesisStreamProvider = class {
|
|
|
59583
59654
|
if (status !== "CREATING" && status !== "UPDATING") {
|
|
59584
59655
|
throw new Error(`Unexpected stream status: ${status}`);
|
|
59585
59656
|
}
|
|
59586
|
-
await new Promise((
|
|
59657
|
+
await new Promise((resolve6) => setTimeout(resolve6, 2e3));
|
|
59587
59658
|
}
|
|
59588
59659
|
throw new Error(
|
|
59589
59660
|
`Stream ${streamName} did not reach ACTIVE status within ${maxAttempts * 2} seconds`
|
|
@@ -59916,7 +59987,7 @@ var KinesisStreamConsumerProvider = class {
|
|
|
59916
59987
|
if (status !== "CREATING") {
|
|
59917
59988
|
throw new Error(`Unexpected consumer status: ${status}`);
|
|
59918
59989
|
}
|
|
59919
|
-
await new Promise((
|
|
59990
|
+
await new Promise((resolve6) => setTimeout(resolve6, 1e3));
|
|
59920
59991
|
}
|
|
59921
59992
|
throw new Error(
|
|
59922
59993
|
`Consumer ${consumerArn} did not reach ACTIVE status within ${maxAttempts} seconds`
|
|
@@ -60221,7 +60292,7 @@ var EFSProvider = class {
|
|
|
60221
60292
|
this.logger.debug(
|
|
60222
60293
|
`FileSystem ${fileSystemId} state: ${fs?.LifeCycleState ?? "unknown"}, waiting...`
|
|
60223
60294
|
);
|
|
60224
|
-
await new Promise((
|
|
60295
|
+
await new Promise((resolve6) => setTimeout(resolve6, pollIntervalMs));
|
|
60225
60296
|
}
|
|
60226
60297
|
throw new ProvisioningError(
|
|
60227
60298
|
`Timed out waiting for EFS FileSystem ${fileSystemId} to become available (60s)`,
|
|
@@ -60299,7 +60370,7 @@ var EFSProvider = class {
|
|
|
60299
60370
|
this.logger.debug(
|
|
60300
60371
|
`MountTarget ${mountTargetId} state: ${mountTarget?.LifeCycleState ?? "unknown"}, waiting...`
|
|
60301
60372
|
);
|
|
60302
|
-
await new Promise((
|
|
60373
|
+
await new Promise((resolve6) => setTimeout(resolve6, pollIntervalMs));
|
|
60303
60374
|
}
|
|
60304
60375
|
throw new ProvisioningError(
|
|
60305
60376
|
`Timed out waiting for EFS MountTarget ${mountTargetId} to become available (120s)`,
|
|
@@ -60365,7 +60436,7 @@ var EFSProvider = class {
|
|
|
60365
60436
|
}
|
|
60366
60437
|
throw error;
|
|
60367
60438
|
}
|
|
60368
|
-
await new Promise((
|
|
60439
|
+
await new Promise((resolve6) => setTimeout(resolve6, pollIntervalMs));
|
|
60369
60440
|
}
|
|
60370
60441
|
this.logger.warn(
|
|
60371
60442
|
`Timed out waiting for EFS MountTarget ${mountTargetId} deletion for ${logicalId} (120s)`
|
|
@@ -61323,7 +61394,7 @@ var FirehoseProvider = class {
|
|
|
61323
61394
|
this.logger.debug(
|
|
61324
61395
|
`Firehose ${logicalId} status: ${status} (attempt ${attempt}/${maxAttempts})`
|
|
61325
61396
|
);
|
|
61326
|
-
await new Promise((
|
|
61397
|
+
await new Promise((resolve6) => setTimeout(resolve6, 2e3));
|
|
61327
61398
|
}
|
|
61328
61399
|
this.logger.warn(`Firehose ${logicalId} did not reach ACTIVE after ${maxAttempts} attempts`);
|
|
61329
61400
|
}
|
|
@@ -64793,7 +64864,7 @@ var ASGProvider = class {
|
|
|
64793
64864
|
);
|
|
64794
64865
|
}
|
|
64795
64866
|
sleep(ms) {
|
|
64796
|
-
return new Promise((
|
|
64867
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
64797
64868
|
}
|
|
64798
64869
|
// ─── Sub-shape diff helpers ───────────────────────────────────────
|
|
64799
64870
|
// Each helper is a no-op when before/after JSON is identical (the cheap
|
|
@@ -65303,11 +65374,11 @@ async function deployCommand(stacks, options) {
|
|
|
65303
65374
|
addDependencies(stack.stackName);
|
|
65304
65375
|
}
|
|
65305
65376
|
}
|
|
65306
|
-
const { STSClient:
|
|
65307
|
-
const stsClient = new
|
|
65377
|
+
const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
65378
|
+
const stsClient = new STSClient11({
|
|
65308
65379
|
region: options.region || process.env["AWS_REGION"] || "us-east-1"
|
|
65309
65380
|
});
|
|
65310
|
-
const callerIdentity = await stsClient.send(new
|
|
65381
|
+
const callerIdentity = await stsClient.send(new GetCallerIdentityCommand12({}));
|
|
65311
65382
|
const accountId = callerIdentity.Account;
|
|
65312
65383
|
stsClient.destroy();
|
|
65313
65384
|
const assetPublisher = new AssetPublisher();
|
|
@@ -65714,29 +65785,29 @@ function calculateResourceDrift(stateProperties, awsProperties, options) {
|
|
|
65714
65785
|
}
|
|
65715
65786
|
return drifts;
|
|
65716
65787
|
}
|
|
65717
|
-
function isIgnoredPath(
|
|
65788
|
+
function isIgnoredPath(path3, ignorePaths) {
|
|
65718
65789
|
for (const entry of ignorePaths) {
|
|
65719
|
-
if (
|
|
65790
|
+
if (path3 === entry)
|
|
65720
65791
|
return true;
|
|
65721
|
-
if (
|
|
65792
|
+
if (path3.startsWith(`${entry}.`))
|
|
65722
65793
|
return true;
|
|
65723
65794
|
}
|
|
65724
65795
|
return false;
|
|
65725
65796
|
}
|
|
65726
|
-
function diffAt(
|
|
65797
|
+
function diffAt(path3, stateValue, awsValue, out, ignorePaths, unionWalkObjects) {
|
|
65727
65798
|
if (deepEqual(stateValue, awsValue))
|
|
65728
65799
|
return;
|
|
65729
65800
|
if (isPlainObject(stateValue) && isPlainObject(awsValue) && !Array.isArray(stateValue) && !Array.isArray(awsValue)) {
|
|
65730
65801
|
const keys = unionWalkObjects ? /* @__PURE__ */ new Set([...Object.keys(stateValue), ...Object.keys(awsValue)]) : Object.keys(stateValue);
|
|
65731
65802
|
for (const key of keys) {
|
|
65732
|
-
const childPath = `${
|
|
65803
|
+
const childPath = `${path3}.${key}`;
|
|
65733
65804
|
if (isIgnoredPath(childPath, ignorePaths))
|
|
65734
65805
|
continue;
|
|
65735
65806
|
diffAt(childPath, stateValue[key], awsValue[key], out, ignorePaths, unionWalkObjects);
|
|
65736
65807
|
}
|
|
65737
65808
|
return;
|
|
65738
65809
|
}
|
|
65739
|
-
out.push({ path:
|
|
65810
|
+
out.push({ path: path3, stateValue, awsValue });
|
|
65740
65811
|
}
|
|
65741
65812
|
function deepEqual(a, b) {
|
|
65742
65813
|
if (a === b)
|
|
@@ -66139,11 +66210,11 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
|
|
|
66139
66210
|
};
|
|
66140
66211
|
});
|
|
66141
66212
|
}
|
|
66142
|
-
function setAtPath(target,
|
|
66143
|
-
if (
|
|
66213
|
+
function setAtPath(target, path3, value) {
|
|
66214
|
+
if (path3.length === 0) {
|
|
66144
66215
|
return;
|
|
66145
66216
|
}
|
|
66146
|
-
const segments =
|
|
66217
|
+
const segments = path3.split(".");
|
|
66147
66218
|
let cursor = target;
|
|
66148
66219
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
66149
66220
|
const key = segments[i];
|
|
@@ -66733,7 +66804,7 @@ Acquiring lock for stack ${stackName}...`);
|
|
|
66733
66804
|
logger.debug(
|
|
66734
66805
|
` \u23F3 Retrying delete ${logicalId} in ${delay2 / 1e3}s (attempt ${attempt + 1}/${maxAttempts})`
|
|
66735
66806
|
);
|
|
66736
|
-
await new Promise((
|
|
66807
|
+
await new Promise((resolve6) => setTimeout(resolve6, delay2));
|
|
66737
66808
|
}
|
|
66738
66809
|
}
|
|
66739
66810
|
if (lastDeleteError)
|
|
@@ -67043,19 +67114,19 @@ function buildCdkPathIndex(template) {
|
|
|
67043
67114
|
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
67044
67115
|
if (resource.Type === "AWS::CDK::Metadata")
|
|
67045
67116
|
continue;
|
|
67046
|
-
const
|
|
67047
|
-
if (
|
|
67048
|
-
index.set(
|
|
67117
|
+
const path3 = readCdkPath(resource);
|
|
67118
|
+
if (path3)
|
|
67119
|
+
index.set(path3, logicalId);
|
|
67049
67120
|
}
|
|
67050
67121
|
return index;
|
|
67051
67122
|
}
|
|
67052
67123
|
function resolveCdkPathToLogicalIds(input, index) {
|
|
67053
67124
|
const seen = /* @__PURE__ */ new Map();
|
|
67054
67125
|
const prefix = `${input}/`;
|
|
67055
|
-
for (const [
|
|
67056
|
-
if (
|
|
67126
|
+
for (const [path3, logicalId] of index) {
|
|
67127
|
+
if (path3 === input || path3.startsWith(prefix)) {
|
|
67057
67128
|
if (!seen.has(logicalId))
|
|
67058
|
-
seen.set(logicalId,
|
|
67129
|
+
seen.set(logicalId, path3);
|
|
67059
67130
|
}
|
|
67060
67131
|
}
|
|
67061
67132
|
return [...seen.entries()].map(([logicalId, cdkPath]) => ({ logicalId, cdkPath }));
|
|
@@ -67780,9 +67851,9 @@ async function publishAssetsCommand(stacks, options) {
|
|
|
67780
67851
|
);
|
|
67781
67852
|
}
|
|
67782
67853
|
const baseRegion = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
67783
|
-
const { STSClient:
|
|
67784
|
-
const stsClient = new
|
|
67785
|
-
const callerIdentity = await stsClient.send(new
|
|
67854
|
+
const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
67855
|
+
const stsClient = new STSClient11({ region: baseRegion });
|
|
67856
|
+
const callerIdentity = await stsClient.send(new GetCallerIdentityCommand12({}));
|
|
67786
67857
|
const accountId = callerIdentity.Account;
|
|
67787
67858
|
stsClient.destroy();
|
|
67788
67859
|
const assetPublisher = new AssetPublisher();
|
|
@@ -69963,12 +70034,13 @@ async function captureObservedForImportedResources(stackState, providerRegistry,
|
|
|
69963
70034
|
}
|
|
69964
70035
|
|
|
69965
70036
|
// src/cli/commands/local-invoke.ts
|
|
69966
|
-
import { mkdtempSync as
|
|
69967
|
-
import { tmpdir as
|
|
69968
|
-
import
|
|
69969
|
-
import
|
|
70037
|
+
import { mkdtempSync as mkdtempSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
70038
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
70039
|
+
import { dirname as dirname3 } from "node:path";
|
|
70040
|
+
import * as path2 from "node:path";
|
|
70041
|
+
import { Command as Command15, Option as Option8 } from "commander";
|
|
69970
70042
|
|
|
69971
|
-
// src/local
|
|
70043
|
+
// src/local/lambda-resolver.ts
|
|
69972
70044
|
import { existsSync as existsSync4, statSync as statSync3 } from "node:fs";
|
|
69973
70045
|
import { dirname, isAbsolute, resolve as resolve4 } from "node:path";
|
|
69974
70046
|
var LocalInvokeResolutionError = class _LocalInvokeResolutionError extends Error {
|
|
@@ -70067,25 +70139,38 @@ function pickStack(parsed, stacks) {
|
|
|
70067
70139
|
}
|
|
70068
70140
|
function extractLambdaProperties(stack, logicalId, resource) {
|
|
70069
70141
|
const props = resource.Properties ?? {};
|
|
70070
|
-
const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
|
|
70071
|
-
const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
|
|
70072
70142
|
const memoryMb = typeof props["MemorySize"] === "number" ? props["MemorySize"] : 128;
|
|
70073
70143
|
const timeoutSec = typeof props["Timeout"] === "number" ? props["Timeout"] : 3;
|
|
70144
|
+
const code = props["Code"] ?? {};
|
|
70145
|
+
const imageUri = extractImageUri(code["ImageUri"]);
|
|
70146
|
+
if (imageUri !== void 0) {
|
|
70147
|
+
return extractImageLambdaProperties({
|
|
70148
|
+
stack,
|
|
70149
|
+
logicalId,
|
|
70150
|
+
resource,
|
|
70151
|
+
memoryMb,
|
|
70152
|
+
timeoutSec,
|
|
70153
|
+
props,
|
|
70154
|
+
imageUri
|
|
70155
|
+
});
|
|
70156
|
+
}
|
|
70157
|
+
const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
|
|
70158
|
+
const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
|
|
70074
70159
|
if (!runtime) {
|
|
70075
70160
|
throw new LocalInvokeResolutionError(
|
|
70076
|
-
`Lambda '${logicalId}' has no Runtime property
|
|
70161
|
+
`Lambda '${logicalId}' has no Runtime property and no Code.ImageUri. cdkd cannot tell if this is a ZIP or a container Lambda.`
|
|
70077
70162
|
);
|
|
70078
70163
|
}
|
|
70079
70164
|
if (!handler) {
|
|
70080
70165
|
throw new LocalInvokeResolutionError(`Lambda '${logicalId}' has no Handler property.`);
|
|
70081
70166
|
}
|
|
70082
|
-
const code = props["Code"] ?? {};
|
|
70083
70167
|
const inlineCode = typeof code["ZipFile"] === "string" ? code["ZipFile"] : void 0;
|
|
70084
70168
|
let codePath = null;
|
|
70085
70169
|
if (!inlineCode) {
|
|
70086
70170
|
codePath = resolveAssetCodePath(stack, logicalId, resource);
|
|
70087
70171
|
}
|
|
70088
70172
|
return {
|
|
70173
|
+
kind: "zip",
|
|
70089
70174
|
stack,
|
|
70090
70175
|
logicalId,
|
|
70091
70176
|
resource,
|
|
@@ -70097,6 +70182,62 @@ function extractLambdaProperties(stack, logicalId, resource) {
|
|
|
70097
70182
|
...inlineCode !== void 0 && { inlineCode }
|
|
70098
70183
|
};
|
|
70099
70184
|
}
|
|
70185
|
+
function extractImageUri(value) {
|
|
70186
|
+
if (typeof value === "string" && value.length > 0)
|
|
70187
|
+
return value;
|
|
70188
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
70189
|
+
const obj = value;
|
|
70190
|
+
const sub = obj["Fn::Sub"];
|
|
70191
|
+
if (typeof sub === "string" && sub.length > 0)
|
|
70192
|
+
return sub;
|
|
70193
|
+
if (Array.isArray(sub) && typeof sub[0] === "string")
|
|
70194
|
+
return sub[0];
|
|
70195
|
+
}
|
|
70196
|
+
return void 0;
|
|
70197
|
+
}
|
|
70198
|
+
function extractImageLambdaProperties(args) {
|
|
70199
|
+
const { stack, logicalId, resource, memoryMb, timeoutSec, props, imageUri } = args;
|
|
70200
|
+
const rawImageConfig = props["ImageConfig"] ?? {};
|
|
70201
|
+
const imageConfig = {};
|
|
70202
|
+
if (Array.isArray(rawImageConfig["Command"])) {
|
|
70203
|
+
imageConfig.command = rawImageConfig["Command"].filter(
|
|
70204
|
+
(s) => typeof s === "string"
|
|
70205
|
+
);
|
|
70206
|
+
}
|
|
70207
|
+
if (Array.isArray(rawImageConfig["EntryPoint"])) {
|
|
70208
|
+
imageConfig.entryPoint = rawImageConfig["EntryPoint"].filter(
|
|
70209
|
+
(s) => typeof s === "string"
|
|
70210
|
+
);
|
|
70211
|
+
}
|
|
70212
|
+
if (typeof rawImageConfig["WorkingDirectory"] === "string") {
|
|
70213
|
+
imageConfig.workingDirectory = rawImageConfig["WorkingDirectory"];
|
|
70214
|
+
}
|
|
70215
|
+
const arches = props["Architectures"];
|
|
70216
|
+
let architecture = "x86_64";
|
|
70217
|
+
if (Array.isArray(arches) && arches.length > 0) {
|
|
70218
|
+
const first = arches[0];
|
|
70219
|
+
if (first === "arm64")
|
|
70220
|
+
architecture = "arm64";
|
|
70221
|
+
else if (first === "x86_64")
|
|
70222
|
+
architecture = "x86_64";
|
|
70223
|
+
else {
|
|
70224
|
+
throw new LocalInvokeResolutionError(
|
|
70225
|
+
`Lambda '${logicalId}' has unsupported Architectures value '${String(first)}'. cdkd local invoke supports x86_64 and arm64.`
|
|
70226
|
+
);
|
|
70227
|
+
}
|
|
70228
|
+
}
|
|
70229
|
+
return {
|
|
70230
|
+
kind: "image",
|
|
70231
|
+
stack,
|
|
70232
|
+
logicalId,
|
|
70233
|
+
resource,
|
|
70234
|
+
memoryMb,
|
|
70235
|
+
timeoutSec,
|
|
70236
|
+
imageUri,
|
|
70237
|
+
imageConfig,
|
|
70238
|
+
architecture
|
|
70239
|
+
};
|
|
70240
|
+
}
|
|
70100
70241
|
function resolveAssetCodePath(stack, logicalId, resource) {
|
|
70101
70242
|
const meta = resource.Metadata;
|
|
70102
70243
|
const assetPath = meta?.["aws:asset:path"];
|
|
@@ -70140,7 +70281,7 @@ function notFoundError(target, stack, resources) {
|
|
|
70140
70281
|
return new LocalInvokeResolutionError(msg.trimEnd());
|
|
70141
70282
|
}
|
|
70142
70283
|
|
|
70143
|
-
// src/local
|
|
70284
|
+
// src/local/env-resolver.ts
|
|
70144
70285
|
function resolveEnvVars(logicalId, templateEnv, overrides) {
|
|
70145
70286
|
const resolved = {};
|
|
70146
70287
|
const unresolved = [];
|
|
@@ -70177,7 +70318,7 @@ function isLiteralEnvValue(value) {
|
|
|
70177
70318
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
70178
70319
|
}
|
|
70179
70320
|
|
|
70180
|
-
// src/local
|
|
70321
|
+
// src/local/state-resolver.ts
|
|
70181
70322
|
function substituteAgainstState(value, resources) {
|
|
70182
70323
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
70183
70324
|
return { kind: "literal", value };
|
|
@@ -70354,7 +70495,7 @@ function substituteEnvVarsFromState(templateEnv, resources) {
|
|
|
70354
70495
|
return { env, audit };
|
|
70355
70496
|
}
|
|
70356
70497
|
|
|
70357
|
-
// src/local
|
|
70498
|
+
// src/local/runtime-image.ts
|
|
70358
70499
|
var SUPPORTED_RUNTIMES = {
|
|
70359
70500
|
"nodejs18.x": { image: "public.ecr.aws/lambda/nodejs:18", fileExtension: ".js" },
|
|
70360
70501
|
"nodejs20.x": { image: "public.ecr.aws/lambda/nodejs:20", fileExtension: ".js" },
|
|
@@ -70381,7 +70522,7 @@ function resolveRuntimeSpec(runtime) {
|
|
|
70381
70522
|
if (typeof runtime !== "string" || runtime.length === 0) {
|
|
70382
70523
|
throw new UnsupportedRuntimeError(
|
|
70383
70524
|
String(runtime),
|
|
70384
|
-
"Lambda function has no Runtime property.
|
|
70525
|
+
"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
70526
|
);
|
|
70386
70527
|
}
|
|
70387
70528
|
const spec = SUPPORTED_RUNTIMES[runtime];
|
|
@@ -70399,11 +70540,11 @@ function resolveRuntimeSpec(runtime) {
|
|
|
70399
70540
|
);
|
|
70400
70541
|
}
|
|
70401
70542
|
|
|
70402
|
-
// src/local
|
|
70403
|
-
import { execFile as
|
|
70543
|
+
// src/local/docker-runner.ts
|
|
70544
|
+
import { execFile as execFile3, spawn as spawn3 } from "node:child_process";
|
|
70404
70545
|
import { createServer } from "node:net";
|
|
70405
|
-
import { promisify as
|
|
70406
|
-
var
|
|
70546
|
+
import { promisify as promisify3 } from "node:util";
|
|
70547
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
70407
70548
|
var DockerRunnerError = class _DockerRunnerError extends Error {
|
|
70408
70549
|
constructor(message) {
|
|
70409
70550
|
super(message);
|
|
@@ -70422,6 +70563,12 @@ async function pullImage(image, skipPull) {
|
|
|
70422
70563
|
}
|
|
70423
70564
|
async function runDetached(opts) {
|
|
70424
70565
|
const args = ["run", "-d", "--rm"];
|
|
70566
|
+
if (opts.name) {
|
|
70567
|
+
args.push("--name", opts.name);
|
|
70568
|
+
}
|
|
70569
|
+
if (opts.platform) {
|
|
70570
|
+
args.push("--platform", opts.platform);
|
|
70571
|
+
}
|
|
70425
70572
|
const host = opts.host ?? "127.0.0.1";
|
|
70426
70573
|
args.push("-p", `${host}:${opts.hostPort}:8080`);
|
|
70427
70574
|
if (opts.debugPort !== void 0) {
|
|
@@ -70434,11 +70581,19 @@ async function runDetached(opts) {
|
|
|
70434
70581
|
for (const [k, v] of Object.entries(opts.env)) {
|
|
70435
70582
|
args.push("-e", `${k}=${v}`);
|
|
70436
70583
|
}
|
|
70437
|
-
|
|
70584
|
+
if (opts.workingDir) {
|
|
70585
|
+
args.push("--workdir", opts.workingDir);
|
|
70586
|
+
}
|
|
70587
|
+
let entryPointTail = [];
|
|
70588
|
+
if (opts.entryPoint && opts.entryPoint.length > 0) {
|
|
70589
|
+
args.push("--entrypoint", opts.entryPoint[0]);
|
|
70590
|
+
entryPointTail = opts.entryPoint.slice(1);
|
|
70591
|
+
}
|
|
70592
|
+
args.push(opts.image, ...entryPointTail, ...opts.cmd);
|
|
70438
70593
|
const logger = getLogger().child("docker");
|
|
70439
|
-
logger.debug(`docker ${args.join(" ")}`);
|
|
70594
|
+
logger.debug(`docker ${redactAwsCredentialsInArgs(args).join(" ")}`);
|
|
70440
70595
|
try {
|
|
70441
|
-
const { stdout } = await
|
|
70596
|
+
const { stdout } = await execFileAsync3("docker", args, {
|
|
70442
70597
|
maxBuffer: 10 * 1024 * 1024
|
|
70443
70598
|
});
|
|
70444
70599
|
return stdout.trim();
|
|
@@ -70467,7 +70622,7 @@ async function removeContainer(containerId) {
|
|
|
70467
70622
|
return;
|
|
70468
70623
|
const logger = getLogger().child("docker");
|
|
70469
70624
|
try {
|
|
70470
|
-
await
|
|
70625
|
+
await execFileAsync3("docker", ["rm", "-f", containerId]);
|
|
70471
70626
|
logger.debug(`Removed container ${containerId}`);
|
|
70472
70627
|
} catch (error) {
|
|
70473
70628
|
const err = error;
|
|
@@ -70478,7 +70633,7 @@ async function removeContainer(containerId) {
|
|
|
70478
70633
|
}
|
|
70479
70634
|
async function ensureDockerAvailable() {
|
|
70480
70635
|
try {
|
|
70481
|
-
await
|
|
70636
|
+
await execFileAsync3("docker", ["version", "--format", "{{.Server.Version}}"]);
|
|
70482
70637
|
} catch (error) {
|
|
70483
70638
|
const err = error;
|
|
70484
70639
|
if (err.code === "ENOENT") {
|
|
@@ -70508,6 +70663,31 @@ function pickFreePort() {
|
|
|
70508
70663
|
});
|
|
70509
70664
|
});
|
|
70510
70665
|
}
|
|
70666
|
+
var REDACTED_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
70667
|
+
"AWS_ACCESS_KEY_ID",
|
|
70668
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
70669
|
+
"AWS_SESSION_TOKEN"
|
|
70670
|
+
]);
|
|
70671
|
+
function redactAwsCredentialsInArgs(args) {
|
|
70672
|
+
const out = [];
|
|
70673
|
+
for (let i = 0; i < args.length; i++) {
|
|
70674
|
+
const cur = args[i];
|
|
70675
|
+
const next = args[i + 1];
|
|
70676
|
+
if (cur === "-e" && typeof next === "string") {
|
|
70677
|
+
const eqIdx = next.indexOf("=");
|
|
70678
|
+
if (eqIdx > 0) {
|
|
70679
|
+
const key = next.substring(0, eqIdx);
|
|
70680
|
+
if (REDACTED_ENV_KEYS.has(key)) {
|
|
70681
|
+
out.push("-e", `${key}=***`);
|
|
70682
|
+
i++;
|
|
70683
|
+
continue;
|
|
70684
|
+
}
|
|
70685
|
+
}
|
|
70686
|
+
}
|
|
70687
|
+
out.push(cur);
|
|
70688
|
+
}
|
|
70689
|
+
return out;
|
|
70690
|
+
}
|
|
70511
70691
|
function runForeground(cmd, args) {
|
|
70512
70692
|
return new Promise((resolveProc, rejectProc) => {
|
|
70513
70693
|
const proc = spawn3(cmd, args, { stdio: "inherit" });
|
|
@@ -70521,7 +70701,164 @@ function runForeground(cmd, args) {
|
|
|
70521
70701
|
});
|
|
70522
70702
|
}
|
|
70523
70703
|
|
|
70524
|
-
// src/local
|
|
70704
|
+
// src/local/docker-image-builder.ts
|
|
70705
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
70706
|
+
async function buildContainerImage(asset, cdkOutDir, options) {
|
|
70707
|
+
const tag = computeLocalTag(asset.source);
|
|
70708
|
+
const platform = architectureToPlatform(options.architecture);
|
|
70709
|
+
const logger = getLogger().child("local-invoke-build");
|
|
70710
|
+
logger.info(`Building container image (platform=${platform})...`);
|
|
70711
|
+
logger.debug(`Local tag: ${tag}`);
|
|
70712
|
+
await buildDockerImage(asset, cdkOutDir, tag, {
|
|
70713
|
+
platform,
|
|
70714
|
+
wrapError: (stderr) => new LocalInvokeBuildError(
|
|
70715
|
+
`docker build failed for container Lambda asset (${asset.source.directory}): ${stderr}`
|
|
70716
|
+
)
|
|
70717
|
+
});
|
|
70718
|
+
return tag;
|
|
70719
|
+
}
|
|
70720
|
+
function architectureToPlatform(architecture) {
|
|
70721
|
+
return architecture === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
70722
|
+
}
|
|
70723
|
+
function computeLocalTag(source) {
|
|
70724
|
+
const hash = createHash2("sha256");
|
|
70725
|
+
hash.update(source.directory);
|
|
70726
|
+
hash.update("\0");
|
|
70727
|
+
hash.update(source.dockerFile ?? "");
|
|
70728
|
+
hash.update("\0");
|
|
70729
|
+
hash.update(source.dockerBuildTarget ?? "");
|
|
70730
|
+
hash.update("\0");
|
|
70731
|
+
if (source.dockerBuildArgs) {
|
|
70732
|
+
for (const [k, v] of Object.entries(source.dockerBuildArgs)) {
|
|
70733
|
+
hash.update(k);
|
|
70734
|
+
hash.update("=");
|
|
70735
|
+
hash.update(v);
|
|
70736
|
+
hash.update("\0");
|
|
70737
|
+
}
|
|
70738
|
+
}
|
|
70739
|
+
return `cdkd-local-invoke-${hash.digest("hex").slice(0, 16)}`;
|
|
70740
|
+
}
|
|
70741
|
+
|
|
70742
|
+
// src/local/ecr-puller.ts
|
|
70743
|
+
import { execFile as execFile4, spawn as spawn4 } from "node:child_process";
|
|
70744
|
+
import { promisify as promisify4 } from "node:util";
|
|
70745
|
+
import { ECRClient as ECRClient3, GetAuthorizationTokenCommand as GetAuthorizationTokenCommand2 } from "@aws-sdk/client-ecr";
|
|
70746
|
+
import { GetCallerIdentityCommand as GetCallerIdentityCommand11, STSClient as STSClient10 } from "@aws-sdk/client-sts";
|
|
70747
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
70748
|
+
var ECR_URI_REGEX = /^(\d{12})\.dkr\.ecr\.([^.]+)\.amazonaws\.com(?:\.cn)?\/([^:]+):(.+)$/;
|
|
70749
|
+
function parseEcrUri(imageUri) {
|
|
70750
|
+
const m = ECR_URI_REGEX.exec(imageUri);
|
|
70751
|
+
if (!m)
|
|
70752
|
+
return void 0;
|
|
70753
|
+
return {
|
|
70754
|
+
accountId: m[1],
|
|
70755
|
+
region: m[2],
|
|
70756
|
+
repository: m[3],
|
|
70757
|
+
tag: m[4]
|
|
70758
|
+
};
|
|
70759
|
+
}
|
|
70760
|
+
async function pullEcrImage(imageUri, options) {
|
|
70761
|
+
const logger = getLogger().child("ecr-puller");
|
|
70762
|
+
const parsed = parseEcrUri(imageUri);
|
|
70763
|
+
if (!parsed) {
|
|
70764
|
+
throw new LocalInvokeBuildError(
|
|
70765
|
+
`Image URI '${imageUri}' is not an ECR URI. cdkd local invoke v1 only authenticates against ECR for the deployed-image fallback path.`
|
|
70766
|
+
);
|
|
70767
|
+
}
|
|
70768
|
+
const sts = new STSClient10({ region: parsed.region });
|
|
70769
|
+
let callerAccount;
|
|
70770
|
+
try {
|
|
70771
|
+
const identity = await sts.send(new GetCallerIdentityCommand11({}));
|
|
70772
|
+
if (!identity.Account) {
|
|
70773
|
+
throw new LocalInvokeBuildError(
|
|
70774
|
+
"STS GetCallerIdentity returned no Account. Verify your AWS credentials."
|
|
70775
|
+
);
|
|
70776
|
+
}
|
|
70777
|
+
callerAccount = identity.Account;
|
|
70778
|
+
} finally {
|
|
70779
|
+
sts.destroy();
|
|
70780
|
+
}
|
|
70781
|
+
if (callerAccount !== parsed.accountId) {
|
|
70782
|
+
throw new LocalInvokeBuildError(
|
|
70783
|
+
`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).`
|
|
70784
|
+
);
|
|
70785
|
+
}
|
|
70786
|
+
const callerRegion = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"];
|
|
70787
|
+
if (callerRegion && callerRegion !== parsed.region) {
|
|
70788
|
+
throw new LocalInvokeBuildError(
|
|
70789
|
+
`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.`
|
|
70790
|
+
);
|
|
70791
|
+
}
|
|
70792
|
+
if (options.skipPull) {
|
|
70793
|
+
logger.info(`Skipping ECR pull (--no-pull). Verifying ${imageUri} is in local cache...`);
|
|
70794
|
+
await verifyImageInLocalCache(imageUri);
|
|
70795
|
+
return imageUri;
|
|
70796
|
+
}
|
|
70797
|
+
const ecr = new ECRClient3({ region: parsed.region });
|
|
70798
|
+
try {
|
|
70799
|
+
await ecrLogin(ecr, parsed.accountId, parsed.region);
|
|
70800
|
+
} finally {
|
|
70801
|
+
ecr.destroy();
|
|
70802
|
+
}
|
|
70803
|
+
logger.info(`Pulling ${imageUri}...`);
|
|
70804
|
+
await runForeground2("docker", ["pull", imageUri]);
|
|
70805
|
+
return imageUri;
|
|
70806
|
+
}
|
|
70807
|
+
async function ecrLogin(client, accountId, region) {
|
|
70808
|
+
const logger = getLogger().child("ecr-puller");
|
|
70809
|
+
logger.debug(`ECR login (account=${accountId}, region=${region})`);
|
|
70810
|
+
const response = await client.send(new GetAuthorizationTokenCommand2({}));
|
|
70811
|
+
const authData = response.authorizationData?.[0];
|
|
70812
|
+
if (!authData?.authorizationToken) {
|
|
70813
|
+
throw new LocalInvokeBuildError("Failed to get ECR authorization token");
|
|
70814
|
+
}
|
|
70815
|
+
const token = Buffer.from(authData.authorizationToken, "base64").toString();
|
|
70816
|
+
const [username, password] = token.split(":");
|
|
70817
|
+
const endpoint = authData.proxyEndpoint || `https://${accountId}.dkr.ecr.${region}.amazonaws.com`;
|
|
70818
|
+
await new Promise((resolve6, reject) => {
|
|
70819
|
+
const proc = spawn4("docker", ["login", "--username", username, "--password-stdin", endpoint], {
|
|
70820
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
70821
|
+
});
|
|
70822
|
+
let stderr = "";
|
|
70823
|
+
proc.stderr?.on("data", (data) => {
|
|
70824
|
+
stderr += data.toString();
|
|
70825
|
+
});
|
|
70826
|
+
proc.on("close", (code) => {
|
|
70827
|
+
if (code === 0)
|
|
70828
|
+
resolve6();
|
|
70829
|
+
else
|
|
70830
|
+
reject(new LocalInvokeBuildError(`ECR login failed: ${stderr.trim()}`));
|
|
70831
|
+
});
|
|
70832
|
+
proc.on("error", (err) => {
|
|
70833
|
+
reject(new LocalInvokeBuildError(`ECR login failed: ${err.message}`));
|
|
70834
|
+
});
|
|
70835
|
+
proc.stdin?.write(password);
|
|
70836
|
+
proc.stdin?.end();
|
|
70837
|
+
});
|
|
70838
|
+
}
|
|
70839
|
+
async function verifyImageInLocalCache(imageUri) {
|
|
70840
|
+
try {
|
|
70841
|
+
await execFileAsync4("docker", ["image", "inspect", imageUri]);
|
|
70842
|
+
} catch {
|
|
70843
|
+
throw new LocalInvokeBuildError(
|
|
70844
|
+
`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\`.`
|
|
70845
|
+
);
|
|
70846
|
+
}
|
|
70847
|
+
}
|
|
70848
|
+
function runForeground2(cmd, args) {
|
|
70849
|
+
return new Promise((resolve6, reject) => {
|
|
70850
|
+
const proc = spawn4(cmd, args, { stdio: "inherit" });
|
|
70851
|
+
proc.on("error", (err) => reject(new LocalInvokeBuildError(`${cmd} failed: ${err.message}`)));
|
|
70852
|
+
proc.on("close", (code) => {
|
|
70853
|
+
if (code === 0)
|
|
70854
|
+
resolve6();
|
|
70855
|
+
else
|
|
70856
|
+
reject(new LocalInvokeBuildError(`${cmd} exited with code ${code}`));
|
|
70857
|
+
});
|
|
70858
|
+
});
|
|
70859
|
+
}
|
|
70860
|
+
|
|
70861
|
+
// src/local/rie-client.ts
|
|
70525
70862
|
import { setTimeout as delay } from "node:timers/promises";
|
|
70526
70863
|
var INVOKE_PATH = "/2015-03-31/functions/function/invocations";
|
|
70527
70864
|
async function waitForRieReady(host, port, timeoutMs = 5e3) {
|
|
@@ -70630,9 +70967,1301 @@ async function fetchWithStartupRetry(url, body, signal) {
|
|
|
70630
70967
|
throw lastError;
|
|
70631
70968
|
}
|
|
70632
70969
|
|
|
70970
|
+
// src/assets/asset-manifest-loader.ts
|
|
70971
|
+
import { readFile } from "fs/promises";
|
|
70972
|
+
import { join as join6 } from "path";
|
|
70973
|
+
var AssetManifestLoader = class {
|
|
70974
|
+
logger = getLogger().child("AssetManifestLoader");
|
|
70975
|
+
/**
|
|
70976
|
+
* Load asset manifest from CDK output directory
|
|
70977
|
+
*
|
|
70978
|
+
* @param cdkOutputDir CDK output directory (e.g., "cdk.out")
|
|
70979
|
+
* @param stackName Stack name
|
|
70980
|
+
* @returns Asset manifest or null if not found
|
|
70981
|
+
*/
|
|
70982
|
+
async loadManifest(cdkOutputDir, stackName) {
|
|
70983
|
+
const manifestPath = join6(cdkOutputDir, `${stackName}.assets.json`);
|
|
70984
|
+
try {
|
|
70985
|
+
this.logger.debug(`Loading asset manifest from: ${manifestPath}`);
|
|
70986
|
+
const content = await readFile(manifestPath, "utf-8");
|
|
70987
|
+
const manifest = JSON.parse(content);
|
|
70988
|
+
this.logger.debug(
|
|
70989
|
+
`Loaded asset manifest: ${Object.keys(manifest.files).length} file assets, ${Object.keys(manifest.dockerImages).length} docker image assets`
|
|
70990
|
+
);
|
|
70991
|
+
return manifest;
|
|
70992
|
+
} catch (error) {
|
|
70993
|
+
if (error.code === "ENOENT") {
|
|
70994
|
+
this.logger.debug(`Asset manifest not found: ${manifestPath}`);
|
|
70995
|
+
return null;
|
|
70996
|
+
}
|
|
70997
|
+
throw new Error(
|
|
70998
|
+
`Failed to load asset manifest from ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
70999
|
+
);
|
|
71000
|
+
}
|
|
71001
|
+
}
|
|
71002
|
+
/**
|
|
71003
|
+
* Get file assets from manifest (excludes CloudFormation templates)
|
|
71004
|
+
*
|
|
71005
|
+
* @param manifest Asset manifest
|
|
71006
|
+
* @returns Map of asset hash to file asset
|
|
71007
|
+
*/
|
|
71008
|
+
getFileAssets(manifest) {
|
|
71009
|
+
const fileAssets = /* @__PURE__ */ new Map();
|
|
71010
|
+
for (const [assetHash, asset] of Object.entries(manifest.files)) {
|
|
71011
|
+
if (asset.source.path.endsWith(".json") || asset.source.path.endsWith(".template.json")) {
|
|
71012
|
+
this.logger.debug(`Skipping CloudFormation template asset: ${asset.displayName}`);
|
|
71013
|
+
continue;
|
|
71014
|
+
}
|
|
71015
|
+
fileAssets.set(assetHash, asset);
|
|
71016
|
+
}
|
|
71017
|
+
this.logger.debug(`Found ${fileAssets.size} file assets (excluding templates)`);
|
|
71018
|
+
return fileAssets;
|
|
71019
|
+
}
|
|
71020
|
+
/**
|
|
71021
|
+
* Get asset source path (absolute path)
|
|
71022
|
+
*
|
|
71023
|
+
* @param cdkOutputDir CDK output directory
|
|
71024
|
+
* @param asset File asset
|
|
71025
|
+
* @returns Absolute path to asset source
|
|
71026
|
+
*/
|
|
71027
|
+
getAssetSourcePath(cdkOutputDir, asset) {
|
|
71028
|
+
return join6(cdkOutputDir, asset.source.path);
|
|
71029
|
+
}
|
|
71030
|
+
/**
|
|
71031
|
+
* Resolve asset destination values (replace ${AWS::AccountId}, ${AWS::Region}, etc.)
|
|
71032
|
+
*
|
|
71033
|
+
* @param value Value with placeholders
|
|
71034
|
+
* @param accountId AWS account ID
|
|
71035
|
+
* @param region AWS region
|
|
71036
|
+
* @param partition AWS partition (default: "aws")
|
|
71037
|
+
* @returns Resolved value
|
|
71038
|
+
*/
|
|
71039
|
+
resolveAssetDestinationValue(value, accountId, region, partition = "aws") {
|
|
71040
|
+
return value.replace(/\$\{AWS::AccountId\}/g, accountId).replace(/\$\{AWS::Region\}/g, region).replace(/\$\{AWS::Partition\}/g, partition);
|
|
71041
|
+
}
|
|
71042
|
+
};
|
|
71043
|
+
function getDockerImageBySourceHash(manifest, imageUri) {
|
|
71044
|
+
const dockerImages = manifest.dockerImages ?? {};
|
|
71045
|
+
const entries = Object.entries(dockerImages);
|
|
71046
|
+
if (entries.length === 0)
|
|
71047
|
+
return void 0;
|
|
71048
|
+
const hash = extractHashFromImageUri(imageUri);
|
|
71049
|
+
if (hash !== void 0) {
|
|
71050
|
+
const asset = dockerImages[hash];
|
|
71051
|
+
if (asset) {
|
|
71052
|
+
return { hash, asset };
|
|
71053
|
+
}
|
|
71054
|
+
}
|
|
71055
|
+
if (entries.length === 1) {
|
|
71056
|
+
const [singleHash, singleAsset] = entries[0];
|
|
71057
|
+
return { hash: singleHash, asset: singleAsset };
|
|
71058
|
+
}
|
|
71059
|
+
return void 0;
|
|
71060
|
+
}
|
|
71061
|
+
function extractHashFromImageUri(imageUri) {
|
|
71062
|
+
if (imageUri.includes("@sha256:"))
|
|
71063
|
+
return void 0;
|
|
71064
|
+
const match = /:([a-f0-9]{8,})$/.exec(imageUri);
|
|
71065
|
+
return match?.[1];
|
|
71066
|
+
}
|
|
71067
|
+
|
|
70633
71068
|
// src/cli/commands/local-invoke.ts
|
|
70634
71069
|
init_aws_clients();
|
|
70635
|
-
|
|
71070
|
+
|
|
71071
|
+
// src/cli/commands/local-start-api.ts
|
|
71072
|
+
import { mkdirSync as mkdirSync2, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
71073
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
71074
|
+
import * as path from "node:path";
|
|
71075
|
+
import { Command as Command14, Option as Option7 } from "commander";
|
|
71076
|
+
|
|
71077
|
+
// src/local/route-discovery.ts
|
|
71078
|
+
function discoverRoutes(stacks) {
|
|
71079
|
+
const routes = [];
|
|
71080
|
+
const errors = [];
|
|
71081
|
+
for (const stack of stacks) {
|
|
71082
|
+
const template = stack.template;
|
|
71083
|
+
const resources = template.Resources ?? {};
|
|
71084
|
+
for (const [logicalId, resource] of Object.entries(resources)) {
|
|
71085
|
+
try {
|
|
71086
|
+
switch (resource.Type) {
|
|
71087
|
+
case "AWS::ApiGateway::Method":
|
|
71088
|
+
routes.push(...discoverRestV1Method(logicalId, resource, template, stack.stackName));
|
|
71089
|
+
break;
|
|
71090
|
+
case "AWS::ApiGatewayV2::Route":
|
|
71091
|
+
routes.push(...discoverHttpApiRoute(logicalId, resource, template, stack.stackName));
|
|
71092
|
+
break;
|
|
71093
|
+
case "AWS::Lambda::Url":
|
|
71094
|
+
routes.push(...discoverFunctionUrl(logicalId, resource, stack.stackName));
|
|
71095
|
+
break;
|
|
71096
|
+
default:
|
|
71097
|
+
break;
|
|
71098
|
+
}
|
|
71099
|
+
} catch (err) {
|
|
71100
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
71101
|
+
}
|
|
71102
|
+
}
|
|
71103
|
+
}
|
|
71104
|
+
if (errors.length > 0) {
|
|
71105
|
+
throw new RouteDiscoveryError(
|
|
71106
|
+
`cdkd local start-api: ${errors.length} unsupported route(s) in the synthesized template:
|
|
71107
|
+
` + errors.map((e) => ` - ${e}`).join("\n")
|
|
71108
|
+
);
|
|
71109
|
+
}
|
|
71110
|
+
return routes;
|
|
71111
|
+
}
|
|
71112
|
+
function discoverRestV1Method(logicalId, resource, template, stackName) {
|
|
71113
|
+
const props = resource.Properties ?? {};
|
|
71114
|
+
const integration = props["Integration"];
|
|
71115
|
+
if (!integration) {
|
|
71116
|
+
throw new Error(
|
|
71117
|
+
`${stackName}/${logicalId} (AWS::ApiGateway::Method): missing Integration property`
|
|
71118
|
+
);
|
|
71119
|
+
}
|
|
71120
|
+
const integrationType = integration["Type"];
|
|
71121
|
+
if (integrationType !== "AWS_PROXY") {
|
|
71122
|
+
throw new Error(
|
|
71123
|
+
`${stackName}/${logicalId} (AWS::ApiGateway::Method): integration type '${String(
|
|
71124
|
+
integrationType
|
|
71125
|
+
)}' is not supported (only AWS_PROXY). MOCK / AWS / HTTP / HTTP_PROXY require mapping templates that cdkd cannot emulate.`
|
|
71126
|
+
);
|
|
71127
|
+
}
|
|
71128
|
+
const integrationUri = integration["Uri"];
|
|
71129
|
+
const lambdaLogicalId = resolveLambdaArnIntrinsic(
|
|
71130
|
+
integrationUri,
|
|
71131
|
+
`${stackName}/${logicalId}.Integration.Uri`
|
|
71132
|
+
);
|
|
71133
|
+
const restApiId = props["RestApiId"];
|
|
71134
|
+
const restApiLogicalId = pickRefLogicalId(restApiId);
|
|
71135
|
+
if (!restApiLogicalId) {
|
|
71136
|
+
throw new Error(
|
|
71137
|
+
`${stackName}/${logicalId} (AWS::ApiGateway::Method): RestApiId must be a { Ref: '...' } reference (got ${shortJson(
|
|
71138
|
+
restApiId
|
|
71139
|
+
)}).`
|
|
71140
|
+
);
|
|
71141
|
+
}
|
|
71142
|
+
const resourceId = props["ResourceId"];
|
|
71143
|
+
const path3 = buildRestV1Path(resourceId, restApiLogicalId, template, stackName, logicalId);
|
|
71144
|
+
const httpMethod = String(props["HttpMethod"] ?? "ANY");
|
|
71145
|
+
const stage = pickRestV1Stage(restApiLogicalId, template);
|
|
71146
|
+
return [
|
|
71147
|
+
{
|
|
71148
|
+
method: httpMethod,
|
|
71149
|
+
pathPattern: path3,
|
|
71150
|
+
lambdaLogicalId,
|
|
71151
|
+
source: "rest-v1",
|
|
71152
|
+
apiVersion: "v1",
|
|
71153
|
+
stage,
|
|
71154
|
+
declaredAt: `${stackName}/${logicalId}`
|
|
71155
|
+
}
|
|
71156
|
+
];
|
|
71157
|
+
}
|
|
71158
|
+
function buildRestV1Path(resourceIdIntrinsic, restApiLogicalId, template, stackName, methodLogicalId) {
|
|
71159
|
+
if (resourceIdIntrinsic && typeof resourceIdIntrinsic === "object" && !Array.isArray(resourceIdIntrinsic)) {
|
|
71160
|
+
const obj = resourceIdIntrinsic;
|
|
71161
|
+
if ("Fn::GetAtt" in obj) {
|
|
71162
|
+
const arg = obj["Fn::GetAtt"];
|
|
71163
|
+
if (Array.isArray(arg) && arg.length === 2 && arg[1] === "RootResourceId") {
|
|
71164
|
+
return "/";
|
|
71165
|
+
}
|
|
71166
|
+
}
|
|
71167
|
+
}
|
|
71168
|
+
const resourceLogicalId = pickRefLogicalId(resourceIdIntrinsic);
|
|
71169
|
+
if (!resourceLogicalId) {
|
|
71170
|
+
throw new Error(
|
|
71171
|
+
`${stackName}/${methodLogicalId}: ResourceId must be { Ref: '...' } or { 'Fn::GetAtt': [..., 'RootResourceId'] } (got ${shortJson(
|
|
71172
|
+
resourceIdIntrinsic
|
|
71173
|
+
)}).`
|
|
71174
|
+
);
|
|
71175
|
+
}
|
|
71176
|
+
const segments = [];
|
|
71177
|
+
const visited = /* @__PURE__ */ new Set();
|
|
71178
|
+
let cursor = resourceLogicalId;
|
|
71179
|
+
while (cursor && cursor !== restApiLogicalId) {
|
|
71180
|
+
if (visited.has(cursor)) {
|
|
71181
|
+
throw new Error(
|
|
71182
|
+
`${stackName}/${methodLogicalId}: cycle detected in AWS::ApiGateway::Resource ParentId chain at ${cursor}`
|
|
71183
|
+
);
|
|
71184
|
+
}
|
|
71185
|
+
visited.add(cursor);
|
|
71186
|
+
const node = template.Resources?.[cursor];
|
|
71187
|
+
if (!node) {
|
|
71188
|
+
throw new Error(
|
|
71189
|
+
`${stackName}/${methodLogicalId}: ParentId chain references missing resource '${cursor}'`
|
|
71190
|
+
);
|
|
71191
|
+
}
|
|
71192
|
+
if (node.Type !== "AWS::ApiGateway::Resource") {
|
|
71193
|
+
throw new Error(
|
|
71194
|
+
`${stackName}/${methodLogicalId}: ParentId chain hit ${node.Type} (expected AWS::ApiGateway::Resource or RestApi root)`
|
|
71195
|
+
);
|
|
71196
|
+
}
|
|
71197
|
+
const nodeProps = node.Properties ?? {};
|
|
71198
|
+
const pathPart = nodeProps["PathPart"];
|
|
71199
|
+
if (typeof pathPart !== "string") {
|
|
71200
|
+
throw new Error(
|
|
71201
|
+
`${stackName}/${methodLogicalId}: AWS::ApiGateway::Resource '${cursor}' missing PathPart`
|
|
71202
|
+
);
|
|
71203
|
+
}
|
|
71204
|
+
segments.unshift(pathPart);
|
|
71205
|
+
const parentId = nodeProps["ParentId"];
|
|
71206
|
+
if (parentId && typeof parentId === "object" && !Array.isArray(parentId) && "Fn::GetAtt" in parentId) {
|
|
71207
|
+
const arg = parentId["Fn::GetAtt"];
|
|
71208
|
+
if (Array.isArray(arg) && arg[1] === "RootResourceId")
|
|
71209
|
+
break;
|
|
71210
|
+
}
|
|
71211
|
+
cursor = pickRefLogicalId(parentId) ?? void 0;
|
|
71212
|
+
}
|
|
71213
|
+
return "/" + segments.join("/");
|
|
71214
|
+
}
|
|
71215
|
+
function pickRestV1Stage(restApiLogicalId, template) {
|
|
71216
|
+
const resources = template.Resources ?? {};
|
|
71217
|
+
for (const [, resource] of Object.entries(resources)) {
|
|
71218
|
+
if (resource.Type !== "AWS::ApiGateway::Stage")
|
|
71219
|
+
continue;
|
|
71220
|
+
const props = resource.Properties ?? {};
|
|
71221
|
+
const ref = pickRefLogicalId(props["RestApiId"]);
|
|
71222
|
+
if (ref === restApiLogicalId) {
|
|
71223
|
+
const stageName = props["StageName"];
|
|
71224
|
+
if (typeof stageName === "string")
|
|
71225
|
+
return stageName;
|
|
71226
|
+
}
|
|
71227
|
+
}
|
|
71228
|
+
return "$default";
|
|
71229
|
+
}
|
|
71230
|
+
function discoverHttpApiRoute(logicalId, resource, template, stackName) {
|
|
71231
|
+
const props = resource.Properties ?? {};
|
|
71232
|
+
const apiId = props["ApiId"];
|
|
71233
|
+
const apiLogicalId = pickRefLogicalId(apiId);
|
|
71234
|
+
if (!apiLogicalId) {
|
|
71235
|
+
throw new Error(
|
|
71236
|
+
`${stackName}/${logicalId} (AWS::ApiGatewayV2::Route): ApiId must be { Ref: '...' } (got ${shortJson(
|
|
71237
|
+
apiId
|
|
71238
|
+
)}).`
|
|
71239
|
+
);
|
|
71240
|
+
}
|
|
71241
|
+
const apiResource = template.Resources?.[apiLogicalId];
|
|
71242
|
+
if (apiResource?.Type === "AWS::ApiGatewayV2::Api") {
|
|
71243
|
+
const protocolType = (apiResource.Properties ?? {})["ProtocolType"];
|
|
71244
|
+
if (protocolType === "WEBSOCKET") {
|
|
71245
|
+
throw new Error(
|
|
71246
|
+
`${stackName}/${logicalId} (AWS::ApiGatewayV2::Route): WebSocket APIs are not supported in cdkd local start-api (deferred follow-up PR).`
|
|
71247
|
+
);
|
|
71248
|
+
}
|
|
71249
|
+
}
|
|
71250
|
+
const routeKey = props["RouteKey"];
|
|
71251
|
+
if (typeof routeKey !== "string" || routeKey.length === 0) {
|
|
71252
|
+
throw new Error(
|
|
71253
|
+
`${stackName}/${logicalId} (AWS::ApiGatewayV2::Route): RouteKey must be a string`
|
|
71254
|
+
);
|
|
71255
|
+
}
|
|
71256
|
+
const target = props["Target"];
|
|
71257
|
+
const integrationLogicalId = parseHttpApiTargetIntegration(
|
|
71258
|
+
target,
|
|
71259
|
+
`${stackName}/${logicalId}.Target`
|
|
71260
|
+
);
|
|
71261
|
+
const integration = template.Resources?.[integrationLogicalId];
|
|
71262
|
+
if (!integration || integration.Type !== "AWS::ApiGatewayV2::Integration") {
|
|
71263
|
+
throw new Error(
|
|
71264
|
+
`${stackName}/${logicalId} (AWS::ApiGatewayV2::Route): Target points at '${integrationLogicalId}' which is not an AWS::ApiGatewayV2::Integration`
|
|
71265
|
+
);
|
|
71266
|
+
}
|
|
71267
|
+
const integrationProps = integration.Properties ?? {};
|
|
71268
|
+
const integrationType = integrationProps["IntegrationType"];
|
|
71269
|
+
if (integrationType !== "AWS_PROXY") {
|
|
71270
|
+
throw new Error(
|
|
71271
|
+
`${stackName}/${logicalId} (AWS::ApiGatewayV2::Route): integration type '${String(
|
|
71272
|
+
integrationType
|
|
71273
|
+
)}' is not supported (only AWS_PROXY).`
|
|
71274
|
+
);
|
|
71275
|
+
}
|
|
71276
|
+
if (integrationProps["IntegrationSubtype"] !== void 0) {
|
|
71277
|
+
throw new Error(
|
|
71278
|
+
`${stackName}/${logicalId} (AWS::ApiGatewayV2::Route): IntegrationSubtype '${String(
|
|
71279
|
+
integrationProps["IntegrationSubtype"]
|
|
71280
|
+
)}' is not supported (ApiGatewayV2 service integrations like SQS/EventBridge cannot run locally).`
|
|
71281
|
+
);
|
|
71282
|
+
}
|
|
71283
|
+
const lambdaLogicalId = resolveLambdaArnIntrinsic(
|
|
71284
|
+
integrationProps["IntegrationUri"],
|
|
71285
|
+
`${stackName}/${integrationLogicalId}.IntegrationUri`
|
|
71286
|
+
);
|
|
71287
|
+
const { method, pathPattern } = parseRouteKey(routeKey);
|
|
71288
|
+
return [
|
|
71289
|
+
{
|
|
71290
|
+
method,
|
|
71291
|
+
pathPattern,
|
|
71292
|
+
lambdaLogicalId,
|
|
71293
|
+
source: "http-api",
|
|
71294
|
+
apiVersion: "v2",
|
|
71295
|
+
stage: "$default",
|
|
71296
|
+
declaredAt: `${stackName}/${logicalId}`
|
|
71297
|
+
}
|
|
71298
|
+
];
|
|
71299
|
+
}
|
|
71300
|
+
function discoverFunctionUrl(logicalId, resource, stackName) {
|
|
71301
|
+
const props = resource.Properties ?? {};
|
|
71302
|
+
const authType = props["AuthType"];
|
|
71303
|
+
if (authType !== "NONE") {
|
|
71304
|
+
throw new Error(
|
|
71305
|
+
`${stackName}/${logicalId} (AWS::Lambda::Url): AuthType '${String(
|
|
71306
|
+
authType
|
|
71307
|
+
)}' is not supported (only NONE \u2014 IAM auth requires SigV4 verification cdkd cannot emulate locally; deferred follow-up PR).`
|
|
71308
|
+
);
|
|
71309
|
+
}
|
|
71310
|
+
const invokeMode = props["InvokeMode"];
|
|
71311
|
+
if (invokeMode === "RESPONSE_STREAM") {
|
|
71312
|
+
throw new Error(
|
|
71313
|
+
`${stackName}/${logicalId} (AWS::Lambda::Url): InvokeMode RESPONSE_STREAM is not supported (deferred follow-up PR).`
|
|
71314
|
+
);
|
|
71315
|
+
}
|
|
71316
|
+
const targetArn = props["TargetFunctionArn"];
|
|
71317
|
+
const lambdaLogicalId = resolveLambdaArnIntrinsic(
|
|
71318
|
+
targetArn,
|
|
71319
|
+
`${stackName}/${logicalId}.TargetFunctionArn`
|
|
71320
|
+
);
|
|
71321
|
+
return [
|
|
71322
|
+
{
|
|
71323
|
+
method: "ANY",
|
|
71324
|
+
pathPattern: "/{proxy+}",
|
|
71325
|
+
lambdaLogicalId,
|
|
71326
|
+
source: "function-url",
|
|
71327
|
+
apiVersion: "v2",
|
|
71328
|
+
stage: "$default",
|
|
71329
|
+
declaredAt: `${stackName}/${logicalId}`
|
|
71330
|
+
}
|
|
71331
|
+
];
|
|
71332
|
+
}
|
|
71333
|
+
function resolveLambdaArnIntrinsic(value, location) {
|
|
71334
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
71335
|
+
const obj = value;
|
|
71336
|
+
if ("Ref" in obj && typeof obj["Ref"] === "string") {
|
|
71337
|
+
return obj["Ref"];
|
|
71338
|
+
}
|
|
71339
|
+
if ("Fn::GetAtt" in obj) {
|
|
71340
|
+
const arg = obj["Fn::GetAtt"];
|
|
71341
|
+
if (Array.isArray(arg) && arg.length === 2 && typeof arg[0] === "string" && arg[1] === "Arn") {
|
|
71342
|
+
return arg[0];
|
|
71343
|
+
}
|
|
71344
|
+
}
|
|
71345
|
+
if ("Fn::Join" in obj) {
|
|
71346
|
+
const join9 = obj["Fn::Join"];
|
|
71347
|
+
if (Array.isArray(join9) && join9.length === 2 && Array.isArray(join9[1])) {
|
|
71348
|
+
const parts = join9[1];
|
|
71349
|
+
const literalParts = parts.filter((p) => typeof p === "string").join("");
|
|
71350
|
+
if (literalParts.includes(":lambda:path/2015-03-31/functions/")) {
|
|
71351
|
+
for (const p of parts) {
|
|
71352
|
+
if (p && typeof p === "object" && !Array.isArray(p)) {
|
|
71353
|
+
const inner = p;
|
|
71354
|
+
const arg = inner["Fn::GetAtt"];
|
|
71355
|
+
if (Array.isArray(arg) && arg.length === 2 && typeof arg[0] === "string" && arg[1] === "Arn") {
|
|
71356
|
+
return arg[0];
|
|
71357
|
+
}
|
|
71358
|
+
}
|
|
71359
|
+
}
|
|
71360
|
+
}
|
|
71361
|
+
}
|
|
71362
|
+
}
|
|
71363
|
+
}
|
|
71364
|
+
throw new Error(
|
|
71365
|
+
`${location}: only { Ref: <LambdaLogicalId> }, { 'Fn::GetAtt': [<LambdaLogicalId>, 'Arn'] }, or the REST v1 invoke-ARN Fn::Join wrapper are supported (got ${shortJson(
|
|
71366
|
+
value
|
|
71367
|
+
)}). Other intrinsics (Fn::Sub against arbitrary templates, etc.) require deploy-state and are not supported in cdkd local start-api.`
|
|
71368
|
+
);
|
|
71369
|
+
}
|
|
71370
|
+
function parseHttpApiTargetIntegration(target, location) {
|
|
71371
|
+
if (typeof target === "string") {
|
|
71372
|
+
const m = /^integrations\/(.+)$/.exec(target);
|
|
71373
|
+
if (m)
|
|
71374
|
+
return m[1];
|
|
71375
|
+
throw new Error(`${location}: literal Target '${target}' must start with 'integrations/'`);
|
|
71376
|
+
}
|
|
71377
|
+
if (target && typeof target === "object" && !Array.isArray(target)) {
|
|
71378
|
+
const obj = target;
|
|
71379
|
+
const join9 = obj["Fn::Join"];
|
|
71380
|
+
if (Array.isArray(join9) && join9.length === 2 && Array.isArray(join9[1])) {
|
|
71381
|
+
const sep = join9[0];
|
|
71382
|
+
const parts = join9[1];
|
|
71383
|
+
if (sep === "/" && parts.length === 2 && parts[0] === "integrations") {
|
|
71384
|
+
const ref = pickRefLogicalId(parts[1]);
|
|
71385
|
+
if (ref)
|
|
71386
|
+
return ref;
|
|
71387
|
+
}
|
|
71388
|
+
if (sep === "" && parts.length === 2 && parts[0] === "integrations/") {
|
|
71389
|
+
const ref = pickRefLogicalId(parts[1]);
|
|
71390
|
+
if (ref)
|
|
71391
|
+
return ref;
|
|
71392
|
+
}
|
|
71393
|
+
}
|
|
71394
|
+
}
|
|
71395
|
+
throw new Error(
|
|
71396
|
+
`${location}: Target must be 'integrations/<id>' or Fn::Join with one of the documented shapes (got ${shortJson(
|
|
71397
|
+
target
|
|
71398
|
+
)}).`
|
|
71399
|
+
);
|
|
71400
|
+
}
|
|
71401
|
+
function parseRouteKey(routeKey) {
|
|
71402
|
+
if (routeKey === "$default") {
|
|
71403
|
+
return { method: "ANY", pathPattern: "$default" };
|
|
71404
|
+
}
|
|
71405
|
+
const m = /^([A-Za-z]+)\s+(\S+)$/.exec(routeKey);
|
|
71406
|
+
if (!m) {
|
|
71407
|
+
throw new Error(
|
|
71408
|
+
`RouteKey '${routeKey}' is malformed: expected '<METHOD> <path>' (e.g. 'GET /items/{id}') or '$default'.`
|
|
71409
|
+
);
|
|
71410
|
+
}
|
|
71411
|
+
return { method: m[1].toUpperCase(), pathPattern: m[2] };
|
|
71412
|
+
}
|
|
71413
|
+
function pickRefLogicalId(value) {
|
|
71414
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
71415
|
+
const ref = value["Ref"];
|
|
71416
|
+
if (typeof ref === "string")
|
|
71417
|
+
return ref;
|
|
71418
|
+
}
|
|
71419
|
+
return null;
|
|
71420
|
+
}
|
|
71421
|
+
function shortJson(value) {
|
|
71422
|
+
try {
|
|
71423
|
+
const s = JSON.stringify(value);
|
|
71424
|
+
return s.length > 200 ? `${s.slice(0, 200)}\u2026` : s;
|
|
71425
|
+
} catch {
|
|
71426
|
+
return String(value);
|
|
71427
|
+
}
|
|
71428
|
+
}
|
|
71429
|
+
|
|
71430
|
+
// src/local/container-pool.ts
|
|
71431
|
+
var DEFAULT_IDLE_MS = 6e4;
|
|
71432
|
+
var MAX_PER_LAMBDA_CONCURRENCY = 4;
|
|
71433
|
+
var MIN_PER_LAMBDA_CONCURRENCY = 1;
|
|
71434
|
+
function createContainerPool(specs, options) {
|
|
71435
|
+
const logger = getLogger().child("container-pool");
|
|
71436
|
+
const concurrencyCap = clampConcurrency(options.perLambdaConcurrency);
|
|
71437
|
+
const idleMs = options.idleMs ?? DEFAULT_IDLE_MS;
|
|
71438
|
+
const streamingEnabled = options.streamLogs !== false;
|
|
71439
|
+
const entries = /* @__PURE__ */ new Map();
|
|
71440
|
+
const inFlightStarts = /* @__PURE__ */ new Set();
|
|
71441
|
+
for (const logicalId of specs.keys()) {
|
|
71442
|
+
entries.set(logicalId, emptyEntry(logicalId));
|
|
71443
|
+
}
|
|
71444
|
+
function emptyEntry(logicalId) {
|
|
71445
|
+
return {
|
|
71446
|
+
logicalId,
|
|
71447
|
+
warm: [],
|
|
71448
|
+
inUse: /* @__PURE__ */ new Set(),
|
|
71449
|
+
waitQueue: [],
|
|
71450
|
+
idleTimer: null,
|
|
71451
|
+
growthMutex: Promise.resolve()
|
|
71452
|
+
};
|
|
71453
|
+
}
|
|
71454
|
+
async function startOne(spec) {
|
|
71455
|
+
const image = resolveRuntimeImage(spec.lambda.runtime);
|
|
71456
|
+
const hostPort = await pickFreePort();
|
|
71457
|
+
const name = `cdkd-local-${spec.lambda.logicalId}-${process.pid}-${Math.floor(
|
|
71458
|
+
Math.random() * 1e6
|
|
71459
|
+
)}`;
|
|
71460
|
+
logger.debug(
|
|
71461
|
+
`Starting container ${name} for ${spec.lambda.logicalId} on ${spec.containerHost}:${hostPort}`
|
|
71462
|
+
);
|
|
71463
|
+
const containerId = await runDetached({
|
|
71464
|
+
image,
|
|
71465
|
+
mounts: [{ hostPath: spec.codeDir, containerPath: "/var/task", readOnly: true }],
|
|
71466
|
+
env: spec.env,
|
|
71467
|
+
cmd: [spec.lambda.handler],
|
|
71468
|
+
hostPort,
|
|
71469
|
+
host: spec.containerHost,
|
|
71470
|
+
name,
|
|
71471
|
+
...spec.debugPort !== void 0 && { debugPort: spec.debugPort }
|
|
71472
|
+
});
|
|
71473
|
+
const stopLogStream = streamingEnabled ? streamLogs(containerId) : () => void 0;
|
|
71474
|
+
try {
|
|
71475
|
+
await waitForRieReady(spec.containerHost, hostPort, 3e4);
|
|
71476
|
+
} catch (err) {
|
|
71477
|
+
stopLogStream();
|
|
71478
|
+
await removeContainer(containerId).catch(() => void 0);
|
|
71479
|
+
throw err;
|
|
71480
|
+
}
|
|
71481
|
+
return {
|
|
71482
|
+
logicalId: spec.lambda.logicalId,
|
|
71483
|
+
containerId,
|
|
71484
|
+
containerName: name,
|
|
71485
|
+
hostPort,
|
|
71486
|
+
containerHost: spec.containerHost,
|
|
71487
|
+
stopLogStream
|
|
71488
|
+
};
|
|
71489
|
+
}
|
|
71490
|
+
async function withMutex(entry, body) {
|
|
71491
|
+
const previous = entry.growthMutex;
|
|
71492
|
+
let release;
|
|
71493
|
+
entry.growthMutex = new Promise((r) => release = r);
|
|
71494
|
+
try {
|
|
71495
|
+
await previous;
|
|
71496
|
+
return await body();
|
|
71497
|
+
} finally {
|
|
71498
|
+
release();
|
|
71499
|
+
}
|
|
71500
|
+
}
|
|
71501
|
+
async function tearDown(handle) {
|
|
71502
|
+
try {
|
|
71503
|
+
handle.stopLogStream();
|
|
71504
|
+
} catch (err) {
|
|
71505
|
+
logger.debug(
|
|
71506
|
+
`stopLogStream(${handle.containerName}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
71507
|
+
);
|
|
71508
|
+
}
|
|
71509
|
+
try {
|
|
71510
|
+
await removeContainer(handle.containerId);
|
|
71511
|
+
} catch (err) {
|
|
71512
|
+
logger.warn(
|
|
71513
|
+
`Failed to remove container ${handle.containerName}: ${err instanceof Error ? err.message : String(err)}. Continuing cleanup.`
|
|
71514
|
+
);
|
|
71515
|
+
}
|
|
71516
|
+
}
|
|
71517
|
+
function poolSize(entry) {
|
|
71518
|
+
return entry.warm.length + entry.inUse.size;
|
|
71519
|
+
}
|
|
71520
|
+
function resetIdleTimer(entry) {
|
|
71521
|
+
if (entry.idleTimer) {
|
|
71522
|
+
clearTimeout(entry.idleTimer);
|
|
71523
|
+
entry.idleTimer = null;
|
|
71524
|
+
}
|
|
71525
|
+
if (entry.warm.length === 0)
|
|
71526
|
+
return;
|
|
71527
|
+
entry.idleTimer = setTimeout(() => {
|
|
71528
|
+
void gcIdle(entry);
|
|
71529
|
+
}, idleMs);
|
|
71530
|
+
entry.idleTimer.unref?.();
|
|
71531
|
+
}
|
|
71532
|
+
async function gcIdle(entry) {
|
|
71533
|
+
const handles = entry.warm.splice(0, entry.warm.length);
|
|
71534
|
+
entry.idleTimer = null;
|
|
71535
|
+
if (handles.length === 0)
|
|
71536
|
+
return;
|
|
71537
|
+
logger.debug(`Idle GC: tearing down ${handles.length} container(s) for ${entry.logicalId}`);
|
|
71538
|
+
await Promise.allSettled(handles.map((h) => tearDown(h)));
|
|
71539
|
+
}
|
|
71540
|
+
return {
|
|
71541
|
+
async acquire(logicalId) {
|
|
71542
|
+
const entry = entries.get(logicalId);
|
|
71543
|
+
if (!entry) {
|
|
71544
|
+
throw new Error(
|
|
71545
|
+
`containerPool.acquire: no spec registered for Lambda '${logicalId}'. This is a bug \u2014 every reachable route's Lambda should be registered at server boot.`
|
|
71546
|
+
);
|
|
71547
|
+
}
|
|
71548
|
+
if (entry.warm.length > 0) {
|
|
71549
|
+
const handle = entry.warm.shift();
|
|
71550
|
+
entry.inUse.add(handle);
|
|
71551
|
+
if (entry.idleTimer) {
|
|
71552
|
+
clearTimeout(entry.idleTimer);
|
|
71553
|
+
entry.idleTimer = null;
|
|
71554
|
+
}
|
|
71555
|
+
return handle;
|
|
71556
|
+
}
|
|
71557
|
+
return await withMutex(entry, async () => {
|
|
71558
|
+
if (entry.warm.length > 0) {
|
|
71559
|
+
const handle = entry.warm.shift();
|
|
71560
|
+
entry.inUse.add(handle);
|
|
71561
|
+
return handle;
|
|
71562
|
+
}
|
|
71563
|
+
if (poolSize(entry) < concurrencyCap) {
|
|
71564
|
+
const spec = specs.get(logicalId);
|
|
71565
|
+
const startPromise = startOne(spec);
|
|
71566
|
+
inFlightStarts.add(startPromise);
|
|
71567
|
+
let handle;
|
|
71568
|
+
try {
|
|
71569
|
+
handle = await startPromise;
|
|
71570
|
+
} finally {
|
|
71571
|
+
inFlightStarts.delete(startPromise);
|
|
71572
|
+
}
|
|
71573
|
+
entry.inUse.add(handle);
|
|
71574
|
+
return handle;
|
|
71575
|
+
}
|
|
71576
|
+
return await new Promise((resolveAcquire, rejectAcquire) => {
|
|
71577
|
+
entry.waitQueue.push({ resolve: resolveAcquire, reject: rejectAcquire });
|
|
71578
|
+
});
|
|
71579
|
+
});
|
|
71580
|
+
},
|
|
71581
|
+
release(handle) {
|
|
71582
|
+
const entry = entries.get(handle.logicalId);
|
|
71583
|
+
if (!entry)
|
|
71584
|
+
return;
|
|
71585
|
+
entry.inUse.delete(handle);
|
|
71586
|
+
const waiter = entry.waitQueue.shift();
|
|
71587
|
+
if (waiter) {
|
|
71588
|
+
entry.inUse.add(handle);
|
|
71589
|
+
waiter.resolve(handle);
|
|
71590
|
+
return;
|
|
71591
|
+
}
|
|
71592
|
+
entry.warm.push(handle);
|
|
71593
|
+
resetIdleTimer(entry);
|
|
71594
|
+
},
|
|
71595
|
+
async dispose() {
|
|
71596
|
+
logger.debug("Disposing container pool");
|
|
71597
|
+
const allHandles = [];
|
|
71598
|
+
for (const entry of entries.values()) {
|
|
71599
|
+
if (entry.idleTimer) {
|
|
71600
|
+
clearTimeout(entry.idleTimer);
|
|
71601
|
+
entry.idleTimer = null;
|
|
71602
|
+
}
|
|
71603
|
+
for (const waiter of entry.waitQueue.splice(0, entry.waitQueue.length)) {
|
|
71604
|
+
try {
|
|
71605
|
+
waiter.reject(
|
|
71606
|
+
new Error(`Container pool disposed while ${entry.logicalId} was waiting`)
|
|
71607
|
+
);
|
|
71608
|
+
} catch {
|
|
71609
|
+
}
|
|
71610
|
+
}
|
|
71611
|
+
allHandles.push(...entry.warm.splice(0, entry.warm.length));
|
|
71612
|
+
for (const h of entry.inUse)
|
|
71613
|
+
allHandles.push(h);
|
|
71614
|
+
entry.inUse.clear();
|
|
71615
|
+
}
|
|
71616
|
+
const startPromises = [...inFlightStarts];
|
|
71617
|
+
if (startPromises.length > 0) {
|
|
71618
|
+
logger.debug(
|
|
71619
|
+
`Waiting for ${startPromises.length} in-flight container start(s) to settle before teardown`
|
|
71620
|
+
);
|
|
71621
|
+
const drainTimeoutMs = 5e3;
|
|
71622
|
+
const wrapped = startPromises.map(
|
|
71623
|
+
(p) => Promise.race([
|
|
71624
|
+
p.then((h) => ({ kind: "ok", handle: h })),
|
|
71625
|
+
new Promise((r) => {
|
|
71626
|
+
const t = setTimeout(() => r({ kind: "timeout" }), drainTimeoutMs);
|
|
71627
|
+
t.unref?.();
|
|
71628
|
+
})
|
|
71629
|
+
]).catch((err) => {
|
|
71630
|
+
logger.debug(
|
|
71631
|
+
`In-flight startOne rejected during dispose: ${err instanceof Error ? err.message : String(err)}`
|
|
71632
|
+
);
|
|
71633
|
+
return { kind: "rejected" };
|
|
71634
|
+
})
|
|
71635
|
+
);
|
|
71636
|
+
const results = await Promise.all(wrapped);
|
|
71637
|
+
let timedOut = 0;
|
|
71638
|
+
for (const r of results) {
|
|
71639
|
+
if (r.kind === "ok") {
|
|
71640
|
+
allHandles.push(r.handle);
|
|
71641
|
+
} else if (r.kind === "timeout") {
|
|
71642
|
+
timedOut++;
|
|
71643
|
+
}
|
|
71644
|
+
}
|
|
71645
|
+
if (timedOut > 0) {
|
|
71646
|
+
logger.warn(
|
|
71647
|
+
`Container pool disposed with ${timedOut} in-flight start(s) still pending after ${drainTimeoutMs}ms; relying on docker --rm + the verify.sh sweep to clean up.`
|
|
71648
|
+
);
|
|
71649
|
+
}
|
|
71650
|
+
inFlightStarts.clear();
|
|
71651
|
+
}
|
|
71652
|
+
await Promise.allSettled(allHandles.map((h) => tearDown(h)));
|
|
71653
|
+
entries.clear();
|
|
71654
|
+
}
|
|
71655
|
+
};
|
|
71656
|
+
}
|
|
71657
|
+
function clampConcurrency(input) {
|
|
71658
|
+
if (!Number.isFinite(input))
|
|
71659
|
+
return 2;
|
|
71660
|
+
return Math.min(
|
|
71661
|
+
MAX_PER_LAMBDA_CONCURRENCY,
|
|
71662
|
+
Math.max(MIN_PER_LAMBDA_CONCURRENCY, Math.trunc(input))
|
|
71663
|
+
);
|
|
71664
|
+
}
|
|
71665
|
+
|
|
71666
|
+
// src/local/http-server.ts
|
|
71667
|
+
import { createServer as createServer2 } from "node:http";
|
|
71668
|
+
|
|
71669
|
+
// src/local/api-gateway-event.ts
|
|
71670
|
+
import { randomUUID } from "node:crypto";
|
|
71671
|
+
var MOCK_ACCOUNT_ID = "123456789012";
|
|
71672
|
+
var MOCK_DOMAIN_PREFIX = "local";
|
|
71673
|
+
var MOCK_DOMAIN_NAME = "localhost";
|
|
71674
|
+
var MOCK_API_ID = "local";
|
|
71675
|
+
function buildHttpApiV2Event(req, ctx, opts = {}) {
|
|
71676
|
+
const { rawPath, rawQueryString } = splitRawUrl(req.rawUrl);
|
|
71677
|
+
const { headers, cookies } = normalizeHeadersV2(req.headers);
|
|
71678
|
+
const queryStringParameters = parseQueryStringV2(rawQueryString);
|
|
71679
|
+
const userAgent = headers["user-agent"] ?? "";
|
|
71680
|
+
const contentType = headers["content-type"] ?? "";
|
|
71681
|
+
const { body, isBase64Encoded } = encodeBody(req.body, contentType);
|
|
71682
|
+
const now = opts.now ? opts.now() : /* @__PURE__ */ new Date();
|
|
71683
|
+
const routeKey = ctx.route.pathPattern === "$default" ? "$default" : `${ctx.route.method} ${ctx.route.pathPattern}`;
|
|
71684
|
+
const event = {
|
|
71685
|
+
version: "2.0",
|
|
71686
|
+
routeKey,
|
|
71687
|
+
rawPath,
|
|
71688
|
+
rawQueryString,
|
|
71689
|
+
cookies,
|
|
71690
|
+
headers,
|
|
71691
|
+
queryStringParameters,
|
|
71692
|
+
pathParameters: decodePathParameters(ctx.pathParameters),
|
|
71693
|
+
stageVariables: null,
|
|
71694
|
+
requestContext: {
|
|
71695
|
+
accountId: MOCK_ACCOUNT_ID,
|
|
71696
|
+
apiId: MOCK_API_ID,
|
|
71697
|
+
domainName: MOCK_DOMAIN_NAME,
|
|
71698
|
+
domainPrefix: MOCK_DOMAIN_PREFIX,
|
|
71699
|
+
http: {
|
|
71700
|
+
method: req.method.toUpperCase(),
|
|
71701
|
+
path: ctx.matchedPath,
|
|
71702
|
+
protocol: "HTTP/1.1",
|
|
71703
|
+
sourceIp: req.sourceIp ?? "127.0.0.1",
|
|
71704
|
+
userAgent
|
|
71705
|
+
},
|
|
71706
|
+
requestId: randomUUID(),
|
|
71707
|
+
routeKey,
|
|
71708
|
+
stage: ctx.route.stage,
|
|
71709
|
+
time: formatRequestTime(now),
|
|
71710
|
+
timeEpoch: now.getTime(),
|
|
71711
|
+
authentication: null,
|
|
71712
|
+
authorizer: null
|
|
71713
|
+
},
|
|
71714
|
+
body,
|
|
71715
|
+
isBase64Encoded
|
|
71716
|
+
};
|
|
71717
|
+
return event;
|
|
71718
|
+
}
|
|
71719
|
+
function buildRestV1Event(req, ctx, opts = {}) {
|
|
71720
|
+
const { rawPath, rawQueryString } = splitRawUrl(req.rawUrl);
|
|
71721
|
+
const { singular: headers, multi: multiValueHeaders } = normalizeHeadersV1(req.headers);
|
|
71722
|
+
const { singular: queryStringParameters, multi: multiValueQueryStringParameters } = parseQueryStringV1(rawQueryString);
|
|
71723
|
+
const contentType = headers["content-type"] ?? "";
|
|
71724
|
+
const { body, isBase64Encoded } = encodeBody(req.body, contentType);
|
|
71725
|
+
const now = opts.now ? opts.now() : /* @__PURE__ */ new Date();
|
|
71726
|
+
const pathParams = decodePathParameters(ctx.pathParameters);
|
|
71727
|
+
const event = {
|
|
71728
|
+
resource: ctx.route.pathPattern,
|
|
71729
|
+
path: ctx.matchedPath,
|
|
71730
|
+
httpMethod: req.method.toUpperCase(),
|
|
71731
|
+
headers,
|
|
71732
|
+
multiValueHeaders,
|
|
71733
|
+
queryStringParameters: Object.keys(queryStringParameters).length > 0 ? queryStringParameters : null,
|
|
71734
|
+
multiValueQueryStringParameters: Object.keys(multiValueQueryStringParameters).length > 0 ? multiValueQueryStringParameters : null,
|
|
71735
|
+
pathParameters: Object.keys(pathParams).length > 0 ? pathParams : null,
|
|
71736
|
+
stageVariables: null,
|
|
71737
|
+
requestContext: {
|
|
71738
|
+
accountId: MOCK_ACCOUNT_ID,
|
|
71739
|
+
apiId: MOCK_API_ID,
|
|
71740
|
+
domainName: MOCK_DOMAIN_NAME,
|
|
71741
|
+
domainPrefix: MOCK_DOMAIN_PREFIX,
|
|
71742
|
+
httpMethod: req.method.toUpperCase(),
|
|
71743
|
+
identity: {
|
|
71744
|
+
sourceIp: req.sourceIp ?? "127.0.0.1",
|
|
71745
|
+
userAgent: headers["user-agent"] ?? ""
|
|
71746
|
+
},
|
|
71747
|
+
path: `/${ctx.route.stage}${ctx.matchedPath}`,
|
|
71748
|
+
protocol: "HTTP/1.1",
|
|
71749
|
+
requestId: randomUUID(),
|
|
71750
|
+
requestTime: formatRequestTime(now),
|
|
71751
|
+
requestTimeEpoch: now.getTime(),
|
|
71752
|
+
resourcePath: ctx.route.pathPattern,
|
|
71753
|
+
stage: ctx.route.stage,
|
|
71754
|
+
authorizer: null
|
|
71755
|
+
},
|
|
71756
|
+
body: req.body.length === 0 ? null : body,
|
|
71757
|
+
isBase64Encoded
|
|
71758
|
+
};
|
|
71759
|
+
return event;
|
|
71760
|
+
}
|
|
71761
|
+
function splitRawUrl(rawUrl) {
|
|
71762
|
+
const q = rawUrl.indexOf("?");
|
|
71763
|
+
if (q === -1)
|
|
71764
|
+
return { rawPath: rawUrl, rawQueryString: "" };
|
|
71765
|
+
return { rawPath: rawUrl.slice(0, q), rawQueryString: rawUrl.slice(q + 1) };
|
|
71766
|
+
}
|
|
71767
|
+
function normalizeHeadersV2(rawHeaders) {
|
|
71768
|
+
const headers = {};
|
|
71769
|
+
let cookies = [];
|
|
71770
|
+
for (const [name, values] of Object.entries(rawHeaders)) {
|
|
71771
|
+
const lower = name.toLowerCase();
|
|
71772
|
+
if (lower === "cookie") {
|
|
71773
|
+
cookies = values.flatMap((v) => v.split(";")).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
71774
|
+
continue;
|
|
71775
|
+
}
|
|
71776
|
+
headers[lower] = values.join(",");
|
|
71777
|
+
}
|
|
71778
|
+
return { headers, cookies };
|
|
71779
|
+
}
|
|
71780
|
+
function normalizeHeadersV1(rawHeaders) {
|
|
71781
|
+
const singular = {};
|
|
71782
|
+
const multi = {};
|
|
71783
|
+
for (const [name, values] of Object.entries(rawHeaders)) {
|
|
71784
|
+
const lower = name.toLowerCase();
|
|
71785
|
+
if (values.length === 0)
|
|
71786
|
+
continue;
|
|
71787
|
+
multi[lower] = [...values];
|
|
71788
|
+
singular[lower] = values[values.length - 1];
|
|
71789
|
+
}
|
|
71790
|
+
return { singular, multi };
|
|
71791
|
+
}
|
|
71792
|
+
function parseQueryStringV2(rawQueryString) {
|
|
71793
|
+
if (rawQueryString.length === 0)
|
|
71794
|
+
return {};
|
|
71795
|
+
const out = {};
|
|
71796
|
+
for (const pair of rawQueryString.split("&")) {
|
|
71797
|
+
if (pair.length === 0)
|
|
71798
|
+
continue;
|
|
71799
|
+
const eq = pair.indexOf("=");
|
|
71800
|
+
const rawKey = eq === -1 ? pair : pair.slice(0, eq);
|
|
71801
|
+
const rawValue = eq === -1 ? "" : pair.slice(eq + 1);
|
|
71802
|
+
const key = safeDecode(rawKey);
|
|
71803
|
+
const value = safeDecode(rawValue);
|
|
71804
|
+
if (!out[key])
|
|
71805
|
+
out[key] = [];
|
|
71806
|
+
out[key].push(value);
|
|
71807
|
+
}
|
|
71808
|
+
const result = {};
|
|
71809
|
+
for (const [k, vs] of Object.entries(out))
|
|
71810
|
+
result[k] = vs.join(",");
|
|
71811
|
+
return result;
|
|
71812
|
+
}
|
|
71813
|
+
function parseQueryStringV1(rawQueryString) {
|
|
71814
|
+
const multi = {};
|
|
71815
|
+
if (rawQueryString.length > 0) {
|
|
71816
|
+
for (const pair of rawQueryString.split("&")) {
|
|
71817
|
+
if (pair.length === 0)
|
|
71818
|
+
continue;
|
|
71819
|
+
const eq = pair.indexOf("=");
|
|
71820
|
+
const rawKey = eq === -1 ? pair : pair.slice(0, eq);
|
|
71821
|
+
const rawValue = eq === -1 ? "" : pair.slice(eq + 1);
|
|
71822
|
+
const key = safeDecode(rawKey);
|
|
71823
|
+
const value = safeDecode(rawValue);
|
|
71824
|
+
if (!multi[key])
|
|
71825
|
+
multi[key] = [];
|
|
71826
|
+
multi[key].push(value);
|
|
71827
|
+
}
|
|
71828
|
+
}
|
|
71829
|
+
const singular = {};
|
|
71830
|
+
for (const [k, vs] of Object.entries(multi)) {
|
|
71831
|
+
if (vs.length > 0)
|
|
71832
|
+
singular[k] = vs[vs.length - 1];
|
|
71833
|
+
}
|
|
71834
|
+
return { singular, multi };
|
|
71835
|
+
}
|
|
71836
|
+
function decodePathParameters(pathParameters) {
|
|
71837
|
+
const out = {};
|
|
71838
|
+
for (const [k, v] of Object.entries(pathParameters)) {
|
|
71839
|
+
out[k] = safeDecode(v);
|
|
71840
|
+
}
|
|
71841
|
+
return out;
|
|
71842
|
+
}
|
|
71843
|
+
function safeDecode(s) {
|
|
71844
|
+
try {
|
|
71845
|
+
return decodeURIComponent(s);
|
|
71846
|
+
} catch {
|
|
71847
|
+
return s;
|
|
71848
|
+
}
|
|
71849
|
+
}
|
|
71850
|
+
function encodeBody(body, contentType) {
|
|
71851
|
+
if (body.length === 0) {
|
|
71852
|
+
return { body: "", isBase64Encoded: false };
|
|
71853
|
+
}
|
|
71854
|
+
if (isTextualContentType(contentType)) {
|
|
71855
|
+
return { body: body.toString("utf-8"), isBase64Encoded: false };
|
|
71856
|
+
}
|
|
71857
|
+
return { body: body.toString("base64"), isBase64Encoded: true };
|
|
71858
|
+
}
|
|
71859
|
+
var TEXT_PREFIXES = [
|
|
71860
|
+
"text/",
|
|
71861
|
+
"application/json",
|
|
71862
|
+
"application/xml",
|
|
71863
|
+
"application/javascript",
|
|
71864
|
+
"application/x-www-form-urlencoded",
|
|
71865
|
+
"application/graphql"
|
|
71866
|
+
];
|
|
71867
|
+
function isTextualContentType(contentType) {
|
|
71868
|
+
if (!contentType)
|
|
71869
|
+
return false;
|
|
71870
|
+
const lower = contentType.toLowerCase();
|
|
71871
|
+
return TEXT_PREFIXES.some((p) => lower.startsWith(p));
|
|
71872
|
+
}
|
|
71873
|
+
function formatRequestTime(d) {
|
|
71874
|
+
const months = [
|
|
71875
|
+
"Jan",
|
|
71876
|
+
"Feb",
|
|
71877
|
+
"Mar",
|
|
71878
|
+
"Apr",
|
|
71879
|
+
"May",
|
|
71880
|
+
"Jun",
|
|
71881
|
+
"Jul",
|
|
71882
|
+
"Aug",
|
|
71883
|
+
"Sep",
|
|
71884
|
+
"Oct",
|
|
71885
|
+
"Nov",
|
|
71886
|
+
"Dec"
|
|
71887
|
+
];
|
|
71888
|
+
const dd = String(d.getUTCDate()).padStart(2, "0");
|
|
71889
|
+
const mmm = months[d.getUTCMonth()];
|
|
71890
|
+
const yyyy = d.getUTCFullYear();
|
|
71891
|
+
const HH = String(d.getUTCHours()).padStart(2, "0");
|
|
71892
|
+
const MM = String(d.getUTCMinutes()).padStart(2, "0");
|
|
71893
|
+
const SS = String(d.getUTCSeconds()).padStart(2, "0");
|
|
71894
|
+
return `${dd}/${mmm}/${yyyy}:${HH}:${MM}:${SS} +0000`;
|
|
71895
|
+
}
|
|
71896
|
+
|
|
71897
|
+
// src/local/api-gateway-response.ts
|
|
71898
|
+
function translateLambdaResponse(payload, version) {
|
|
71899
|
+
if (isErrorEnvelope(payload)) {
|
|
71900
|
+
return errorEnvelopeResponse();
|
|
71901
|
+
}
|
|
71902
|
+
if (isShapedResponse(payload)) {
|
|
71903
|
+
return translateShapedResponse(payload, version);
|
|
71904
|
+
}
|
|
71905
|
+
return autoFormatResponse(payload);
|
|
71906
|
+
}
|
|
71907
|
+
function isErrorEnvelope(payload) {
|
|
71908
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
71909
|
+
return false;
|
|
71910
|
+
const obj = payload;
|
|
71911
|
+
if ("statusCode" in obj)
|
|
71912
|
+
return false;
|
|
71913
|
+
return typeof obj["errorMessage"] === "string";
|
|
71914
|
+
}
|
|
71915
|
+
function isShapedResponse(payload) {
|
|
71916
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
71917
|
+
return false;
|
|
71918
|
+
const status = payload["statusCode"];
|
|
71919
|
+
return typeof status === "number";
|
|
71920
|
+
}
|
|
71921
|
+
function errorEnvelopeResponse() {
|
|
71922
|
+
const body = Buffer.from('{"message":"Internal server error"}', "utf-8");
|
|
71923
|
+
return {
|
|
71924
|
+
statusCode: 502,
|
|
71925
|
+
headers: {
|
|
71926
|
+
"content-type": "application/json",
|
|
71927
|
+
"content-length": String(body.length)
|
|
71928
|
+
},
|
|
71929
|
+
cookies: [],
|
|
71930
|
+
body
|
|
71931
|
+
};
|
|
71932
|
+
}
|
|
71933
|
+
function translateShapedResponse(payload, version) {
|
|
71934
|
+
const statusCode = Number(payload["statusCode"]);
|
|
71935
|
+
const isBase64 = payload["isBase64Encoded"] === true;
|
|
71936
|
+
const rawBody = payload["body"];
|
|
71937
|
+
let body;
|
|
71938
|
+
if (rawBody === void 0 || rawBody === null) {
|
|
71939
|
+
body = Buffer.alloc(0);
|
|
71940
|
+
} else if (typeof rawBody === "string") {
|
|
71941
|
+
body = isBase64 ? Buffer.from(rawBody, "base64") : Buffer.from(rawBody, "utf-8");
|
|
71942
|
+
} else {
|
|
71943
|
+
body = Buffer.from(JSON.stringify(rawBody), "utf-8");
|
|
71944
|
+
}
|
|
71945
|
+
const headers = {};
|
|
71946
|
+
const cookies = [];
|
|
71947
|
+
const headersIn = payload["headers"];
|
|
71948
|
+
if (headersIn && typeof headersIn === "object" && !Array.isArray(headersIn)) {
|
|
71949
|
+
for (const [name, value] of Object.entries(headersIn)) {
|
|
71950
|
+
const lower = name.toLowerCase();
|
|
71951
|
+
const stringValue = stringifyHeaderValue(value);
|
|
71952
|
+
if (lower === "set-cookie") {
|
|
71953
|
+
cookies.push(stringValue);
|
|
71954
|
+
continue;
|
|
71955
|
+
}
|
|
71956
|
+
headers[lower] = stringValue;
|
|
71957
|
+
}
|
|
71958
|
+
}
|
|
71959
|
+
if (version === "v1") {
|
|
71960
|
+
const mvh = payload["multiValueHeaders"];
|
|
71961
|
+
if (mvh && typeof mvh === "object" && !Array.isArray(mvh)) {
|
|
71962
|
+
for (const [name, values] of Object.entries(mvh)) {
|
|
71963
|
+
if (!Array.isArray(values))
|
|
71964
|
+
continue;
|
|
71965
|
+
const lower = name.toLowerCase();
|
|
71966
|
+
const stringified = values.map((v) => stringifyHeaderValue(v));
|
|
71967
|
+
if (lower === "set-cookie") {
|
|
71968
|
+
for (const c of stringified)
|
|
71969
|
+
cookies.push(c);
|
|
71970
|
+
continue;
|
|
71971
|
+
}
|
|
71972
|
+
headers[lower] = stringified.join(",");
|
|
71973
|
+
}
|
|
71974
|
+
}
|
|
71975
|
+
}
|
|
71976
|
+
if (version === "v2") {
|
|
71977
|
+
const cookieList = payload["cookies"];
|
|
71978
|
+
if (Array.isArray(cookieList)) {
|
|
71979
|
+
for (const c of cookieList) {
|
|
71980
|
+
if (typeof c === "string")
|
|
71981
|
+
cookies.push(c);
|
|
71982
|
+
}
|
|
71983
|
+
}
|
|
71984
|
+
}
|
|
71985
|
+
if (!("content-length" in headers)) {
|
|
71986
|
+
headers["content-length"] = String(body.length);
|
|
71987
|
+
}
|
|
71988
|
+
return { statusCode, headers, cookies, body };
|
|
71989
|
+
}
|
|
71990
|
+
function autoFormatResponse(payload) {
|
|
71991
|
+
const body = payload === void 0 ? Buffer.alloc(0) : Buffer.from(JSON.stringify(payload), "utf-8");
|
|
71992
|
+
return {
|
|
71993
|
+
statusCode: 200,
|
|
71994
|
+
headers: {
|
|
71995
|
+
"content-type": "application/json",
|
|
71996
|
+
"content-length": String(body.length)
|
|
71997
|
+
},
|
|
71998
|
+
cookies: [],
|
|
71999
|
+
body
|
|
72000
|
+
};
|
|
72001
|
+
}
|
|
72002
|
+
function stringifyHeaderValue(value) {
|
|
72003
|
+
if (value === null || value === void 0)
|
|
72004
|
+
return "";
|
|
72005
|
+
if (Array.isArray(value))
|
|
72006
|
+
return value.map((v) => String(v)).join(",");
|
|
72007
|
+
return String(value);
|
|
72008
|
+
}
|
|
72009
|
+
|
|
72010
|
+
// src/local/route-matcher.ts
|
|
72011
|
+
function matchRoute(method, requestPath, routes) {
|
|
72012
|
+
const methodUpper = method.toUpperCase();
|
|
72013
|
+
const normalizedPath = requestPath.length > 1 ? requestPath.replace(/\/+$/, "") : requestPath;
|
|
72014
|
+
const requestSegments = splitPath(normalizedPath);
|
|
72015
|
+
let bestFull = null;
|
|
72016
|
+
for (const route of routes) {
|
|
72017
|
+
if (!methodMatches(route.method, methodUpper))
|
|
72018
|
+
continue;
|
|
72019
|
+
if (route.pathPattern === "$default")
|
|
72020
|
+
continue;
|
|
72021
|
+
if (isProxyRoute(route.pathPattern))
|
|
72022
|
+
continue;
|
|
72023
|
+
const result = matchFullPattern(requestSegments, route.pathPattern);
|
|
72024
|
+
if (!result)
|
|
72025
|
+
continue;
|
|
72026
|
+
if (!bestFull || result.literalCount > bestFull.literalCount) {
|
|
72027
|
+
bestFull = {
|
|
72028
|
+
route,
|
|
72029
|
+
pathParameters: result.pathParameters,
|
|
72030
|
+
literalCount: result.literalCount
|
|
72031
|
+
};
|
|
72032
|
+
}
|
|
72033
|
+
}
|
|
72034
|
+
if (bestFull)
|
|
72035
|
+
return { route: bestFull.route, pathParameters: bestFull.pathParameters };
|
|
72036
|
+
let bestProxy = null;
|
|
72037
|
+
for (const route of routes) {
|
|
72038
|
+
if (!methodMatches(route.method, methodUpper))
|
|
72039
|
+
continue;
|
|
72040
|
+
if (route.pathPattern === "$default")
|
|
72041
|
+
continue;
|
|
72042
|
+
if (!isProxyRoute(route.pathPattern))
|
|
72043
|
+
continue;
|
|
72044
|
+
const result = matchProxyPattern(requestSegments, route.pathPattern);
|
|
72045
|
+
if (!result)
|
|
72046
|
+
continue;
|
|
72047
|
+
if (!bestProxy || result.literalCount > bestProxy.literalCount) {
|
|
72048
|
+
bestProxy = {
|
|
72049
|
+
route,
|
|
72050
|
+
pathParameters: result.pathParameters,
|
|
72051
|
+
literalCount: result.literalCount
|
|
72052
|
+
};
|
|
72053
|
+
}
|
|
72054
|
+
}
|
|
72055
|
+
if (bestProxy)
|
|
72056
|
+
return { route: bestProxy.route, pathParameters: bestProxy.pathParameters };
|
|
72057
|
+
for (const route of routes) {
|
|
72058
|
+
if (!methodMatches(route.method, methodUpper))
|
|
72059
|
+
continue;
|
|
72060
|
+
if (route.pathPattern === "$default")
|
|
72061
|
+
return { route, pathParameters: {} };
|
|
72062
|
+
}
|
|
72063
|
+
return null;
|
|
72064
|
+
}
|
|
72065
|
+
function splitPath(path3) {
|
|
72066
|
+
return path3.split("/").filter((s) => s.length > 0);
|
|
72067
|
+
}
|
|
72068
|
+
function methodMatches(routeMethod, requestMethodUpper) {
|
|
72069
|
+
if (routeMethod === "ANY")
|
|
72070
|
+
return true;
|
|
72071
|
+
return routeMethod.toUpperCase() === requestMethodUpper;
|
|
72072
|
+
}
|
|
72073
|
+
function isProxyRoute(pattern) {
|
|
72074
|
+
return /\/\{[^/{}]+\+\}$/.test(pattern) || pattern === "/{proxy+}";
|
|
72075
|
+
}
|
|
72076
|
+
function matchFullPattern(requestSegments, pattern) {
|
|
72077
|
+
const patternSegments = splitPath(pattern);
|
|
72078
|
+
if (patternSegments.length !== requestSegments.length)
|
|
72079
|
+
return null;
|
|
72080
|
+
const pathParameters = {};
|
|
72081
|
+
let literalCount = 0;
|
|
72082
|
+
for (let i = 0; i < patternSegments.length; i++) {
|
|
72083
|
+
const ps = patternSegments[i];
|
|
72084
|
+
const rs = requestSegments[i];
|
|
72085
|
+
if (isPlaceholder(ps)) {
|
|
72086
|
+
const name = ps.slice(1, -1);
|
|
72087
|
+
pathParameters[name] = rs;
|
|
72088
|
+
} else if (ps === rs) {
|
|
72089
|
+
literalCount++;
|
|
72090
|
+
} else {
|
|
72091
|
+
return null;
|
|
72092
|
+
}
|
|
72093
|
+
}
|
|
72094
|
+
return { pathParameters, literalCount };
|
|
72095
|
+
}
|
|
72096
|
+
function matchProxyPattern(requestSegments, pattern) {
|
|
72097
|
+
const patternSegments = splitPath(pattern);
|
|
72098
|
+
if (patternSegments.length === 0)
|
|
72099
|
+
return null;
|
|
72100
|
+
const tail = patternSegments[patternSegments.length - 1];
|
|
72101
|
+
if (!/^\{[^/{}]+\+\}$/.test(tail))
|
|
72102
|
+
return null;
|
|
72103
|
+
const proxyName = tail.slice(1, -2);
|
|
72104
|
+
const fixedPrefixLen = patternSegments.length - 1;
|
|
72105
|
+
if (requestSegments.length < fixedPrefixLen)
|
|
72106
|
+
return null;
|
|
72107
|
+
const pathParameters = {};
|
|
72108
|
+
let literalCount = 0;
|
|
72109
|
+
for (let i = 0; i < fixedPrefixLen; i++) {
|
|
72110
|
+
const ps = patternSegments[i];
|
|
72111
|
+
const rs = requestSegments[i];
|
|
72112
|
+
if (isPlaceholder(ps)) {
|
|
72113
|
+
pathParameters[ps.slice(1, -1)] = rs;
|
|
72114
|
+
} else if (ps === rs) {
|
|
72115
|
+
literalCount++;
|
|
72116
|
+
} else {
|
|
72117
|
+
return null;
|
|
72118
|
+
}
|
|
72119
|
+
}
|
|
72120
|
+
pathParameters[proxyName] = requestSegments.slice(fixedPrefixLen).join("/");
|
|
72121
|
+
return { pathParameters, literalCount };
|
|
72122
|
+
}
|
|
72123
|
+
function isPlaceholder(segment) {
|
|
72124
|
+
return /^\{[^/{}+]+\}$/.test(segment);
|
|
72125
|
+
}
|
|
72126
|
+
|
|
72127
|
+
// src/local/http-server.ts
|
|
72128
|
+
async function startApiServer(opts) {
|
|
72129
|
+
const logger = getLogger().child("start-api");
|
|
72130
|
+
const server = createServer2((req, res) => {
|
|
72131
|
+
handleRequest(req, res, opts).catch((err) => {
|
|
72132
|
+
logger.error(
|
|
72133
|
+
`Unhandled request error: ${err instanceof Error ? err.stack ?? err.message : String(err)}`
|
|
72134
|
+
);
|
|
72135
|
+
if (!res.headersSent) {
|
|
72136
|
+
writeError(res, 502);
|
|
72137
|
+
}
|
|
72138
|
+
});
|
|
72139
|
+
});
|
|
72140
|
+
server.on("connection", (socket) => {
|
|
72141
|
+
socket.setNoDelay(true);
|
|
72142
|
+
});
|
|
72143
|
+
const { actualPort, actualHost } = await new Promise(
|
|
72144
|
+
(resolveListen, rejectListen) => {
|
|
72145
|
+
server.once("error", rejectListen);
|
|
72146
|
+
server.listen(opts.port, opts.host, () => {
|
|
72147
|
+
const addr = server.address();
|
|
72148
|
+
if (addr === null || typeof addr === "string") {
|
|
72149
|
+
rejectListen(new Error("Could not determine listening address"));
|
|
72150
|
+
return;
|
|
72151
|
+
}
|
|
72152
|
+
resolveListen({ actualPort: addr.port, actualHost: opts.host });
|
|
72153
|
+
});
|
|
72154
|
+
}
|
|
72155
|
+
);
|
|
72156
|
+
let closed = false;
|
|
72157
|
+
return {
|
|
72158
|
+
port: actualPort,
|
|
72159
|
+
host: actualHost,
|
|
72160
|
+
server,
|
|
72161
|
+
close: async () => {
|
|
72162
|
+
if (closed)
|
|
72163
|
+
return;
|
|
72164
|
+
closed = true;
|
|
72165
|
+
await new Promise((resolveClose) => {
|
|
72166
|
+
server.close(() => resolveClose());
|
|
72167
|
+
server.closeAllConnections?.();
|
|
72168
|
+
});
|
|
72169
|
+
}
|
|
72170
|
+
};
|
|
72171
|
+
}
|
|
72172
|
+
async function handleRequest(req, res, opts) {
|
|
72173
|
+
const logger = getLogger().child("start-api");
|
|
72174
|
+
const bodyBuf = await readBody(req);
|
|
72175
|
+
const rawUrl = req.url ?? "/";
|
|
72176
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
72177
|
+
const requestPath = rawUrl.split("?")[0] ?? "/";
|
|
72178
|
+
const match = matchRoute(method, requestPath, opts.routes);
|
|
72179
|
+
if (!match) {
|
|
72180
|
+
writeError(res, 404, '{"message":"Not Found"}');
|
|
72181
|
+
return;
|
|
72182
|
+
}
|
|
72183
|
+
const snapshot = {
|
|
72184
|
+
method,
|
|
72185
|
+
rawUrl,
|
|
72186
|
+
headers: collectHeaders(req),
|
|
72187
|
+
body: bodyBuf,
|
|
72188
|
+
...req.socket.remoteAddress !== void 0 && { sourceIp: req.socket.remoteAddress }
|
|
72189
|
+
};
|
|
72190
|
+
const matchCtx = {
|
|
72191
|
+
route: match.route,
|
|
72192
|
+
pathParameters: match.pathParameters,
|
|
72193
|
+
matchedPath: requestPath
|
|
72194
|
+
};
|
|
72195
|
+
const event = match.route.apiVersion === "v1" ? buildRestV1Event(snapshot, matchCtx) : buildHttpApiV2Event(snapshot, matchCtx);
|
|
72196
|
+
let handle;
|
|
72197
|
+
try {
|
|
72198
|
+
handle = await opts.pool.acquire(match.route.lambdaLogicalId);
|
|
72199
|
+
} catch (err) {
|
|
72200
|
+
logger.error(
|
|
72201
|
+
`Failed to acquire container for ${match.route.lambdaLogicalId}: ${err instanceof Error ? err.message : String(err)}`
|
|
72202
|
+
);
|
|
72203
|
+
writeError(res, 502);
|
|
72204
|
+
return;
|
|
72205
|
+
}
|
|
72206
|
+
try {
|
|
72207
|
+
const invokeResult = await invokeRie(
|
|
72208
|
+
handle.containerHost,
|
|
72209
|
+
handle.hostPort,
|
|
72210
|
+
event,
|
|
72211
|
+
opts.rieTimeoutMs
|
|
72212
|
+
);
|
|
72213
|
+
const translated = translateLambdaResponse(invokeResult.payload, match.route.apiVersion);
|
|
72214
|
+
res.statusCode = translated.statusCode;
|
|
72215
|
+
for (const [name, value] of Object.entries(translated.headers)) {
|
|
72216
|
+
res.setHeader(name, value);
|
|
72217
|
+
}
|
|
72218
|
+
if (translated.cookies.length > 0) {
|
|
72219
|
+
res.setHeader("set-cookie", translated.cookies);
|
|
72220
|
+
}
|
|
72221
|
+
res.end(translated.body);
|
|
72222
|
+
} catch (err) {
|
|
72223
|
+
logger.error(
|
|
72224
|
+
`RIE invoke failed for ${match.route.lambdaLogicalId}: ${err instanceof Error ? err.message : String(err)}`
|
|
72225
|
+
);
|
|
72226
|
+
if (!res.headersSent) {
|
|
72227
|
+
writeError(res, 502);
|
|
72228
|
+
} else {
|
|
72229
|
+
res.end();
|
|
72230
|
+
}
|
|
72231
|
+
} finally {
|
|
72232
|
+
opts.pool.release(handle);
|
|
72233
|
+
}
|
|
72234
|
+
}
|
|
72235
|
+
function readBody(req) {
|
|
72236
|
+
return new Promise((resolveBody, rejectBody) => {
|
|
72237
|
+
const chunks = [];
|
|
72238
|
+
req.on("data", (chunk) => {
|
|
72239
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
72240
|
+
});
|
|
72241
|
+
req.on("end", () => resolveBody(Buffer.concat(chunks)));
|
|
72242
|
+
req.on("error", rejectBody);
|
|
72243
|
+
});
|
|
72244
|
+
}
|
|
72245
|
+
function collectHeaders(req) {
|
|
72246
|
+
const out = {};
|
|
72247
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
72248
|
+
if (Array.isArray(value)) {
|
|
72249
|
+
out[name] = value;
|
|
72250
|
+
} else if (typeof value === "string") {
|
|
72251
|
+
out[name] = [value];
|
|
72252
|
+
}
|
|
72253
|
+
}
|
|
72254
|
+
return out;
|
|
72255
|
+
}
|
|
72256
|
+
function writeError(res, statusCode, body = '{"message":"Internal server error"}') {
|
|
72257
|
+
res.statusCode = statusCode;
|
|
72258
|
+
res.setHeader("content-type", "application/json");
|
|
72259
|
+
res.setHeader("content-length", String(Buffer.byteLength(body, "utf-8")));
|
|
72260
|
+
res.end(body);
|
|
72261
|
+
}
|
|
72262
|
+
|
|
72263
|
+
// src/cli/commands/local-start-api.ts
|
|
72264
|
+
async function localStartApiCommand(options) {
|
|
70636
72265
|
const logger = getLogger();
|
|
70637
72266
|
if (options.verbose) {
|
|
70638
72267
|
logger.setLevel("debug");
|
|
@@ -70655,15 +72284,469 @@ async function localInvokeCommand(target, options) {
|
|
|
70655
72284
|
...Object.keys(context).length > 0 && { context }
|
|
70656
72285
|
};
|
|
70657
72286
|
const { stacks } = await synthesizer.synthesize(synthOpts);
|
|
70658
|
-
const
|
|
70659
|
-
|
|
72287
|
+
const targetStacks = pickTargetStacks(stacks, options.stack);
|
|
72288
|
+
if (targetStacks.length === 0) {
|
|
72289
|
+
throw new Error("No stacks matched. Pass --stack <name> or run from a single-stack app.");
|
|
72290
|
+
}
|
|
72291
|
+
const routes = discoverRoutes(targetStacks);
|
|
72292
|
+
if (routes.length === 0) {
|
|
72293
|
+
throw new Error(
|
|
72294
|
+
"No supported API routes were discovered. cdkd local start-api supports AWS::ApiGateway::* (REST v1), AWS::ApiGatewayV2::* (HTTP), and AWS::Lambda::Url (Function URL) with AWS_PROXY integrations only."
|
|
72295
|
+
);
|
|
72296
|
+
}
|
|
72297
|
+
const lambdaIds = uniqueLambdaIds(routes);
|
|
72298
|
+
const overrides = readEnvOverridesFile(options.envVars);
|
|
72299
|
+
const debugPortBase = options.debugPortBase ? parseDebugPort(options.debugPortBase) : void 0;
|
|
72300
|
+
const specs = /* @__PURE__ */ new Map();
|
|
72301
|
+
const inlineTmpDirs = /* @__PURE__ */ new Set();
|
|
72302
|
+
for (let i = 0; i < lambdaIds.length; i++) {
|
|
72303
|
+
const logicalId = lambdaIds[i];
|
|
72304
|
+
const spec = await buildContainerSpec({
|
|
72305
|
+
logicalId,
|
|
72306
|
+
stacks: targetStacks,
|
|
72307
|
+
overrides,
|
|
72308
|
+
assumeRole: options.assumeRole,
|
|
72309
|
+
containerHost: options.containerHost,
|
|
72310
|
+
...debugPortBase !== void 0 && { debugPort: debugPortBase + i },
|
|
72311
|
+
stsRegion: options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"],
|
|
72312
|
+
inlineTmpDirs
|
|
72313
|
+
});
|
|
72314
|
+
specs.set(logicalId, spec);
|
|
72315
|
+
}
|
|
72316
|
+
const distinctImages = /* @__PURE__ */ new Set();
|
|
72317
|
+
for (const spec of specs.values()) {
|
|
72318
|
+
distinctImages.add(resolveRuntimeImage(spec.lambda.runtime));
|
|
72319
|
+
}
|
|
72320
|
+
for (const image of distinctImages) {
|
|
72321
|
+
await pullImage(image, options.pull === false);
|
|
72322
|
+
}
|
|
72323
|
+
const perLambdaConcurrency = parsePerLambdaConcurrency(options.perLambdaConcurrency);
|
|
72324
|
+
const pool = createContainerPool(specs, {
|
|
72325
|
+
perLambdaConcurrency,
|
|
72326
|
+
skipPull: options.pull === false
|
|
72327
|
+
});
|
|
72328
|
+
if (options.warm) {
|
|
72329
|
+
logger.info(`Pre-warming ${specs.size} container(s)...`);
|
|
72330
|
+
const handles = await Promise.allSettled([...specs.keys()].map((id) => pool.acquire(id)));
|
|
72331
|
+
for (const result of handles) {
|
|
72332
|
+
if (result.status === "fulfilled") {
|
|
72333
|
+
pool.release(result.value);
|
|
72334
|
+
} else {
|
|
72335
|
+
logger.warn(
|
|
72336
|
+
`Pre-warm failed for one Lambda (cold start cost will apply on first request): ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`
|
|
72337
|
+
);
|
|
72338
|
+
}
|
|
72339
|
+
}
|
|
72340
|
+
}
|
|
72341
|
+
let maxTimeoutSec = 0;
|
|
72342
|
+
for (const spec of specs.values()) {
|
|
72343
|
+
if (spec.lambda.timeoutSec > maxTimeoutSec)
|
|
72344
|
+
maxTimeoutSec = spec.lambda.timeoutSec;
|
|
72345
|
+
}
|
|
72346
|
+
const rieTimeoutMs = Math.max(3e4, maxTimeoutSec * 2 * 1e3);
|
|
72347
|
+
const port = parseInt(options.port, 10);
|
|
72348
|
+
if (!Number.isFinite(port) || port < 0 || port > 65535) {
|
|
72349
|
+
throw new Error(`--port must be 0..65535 (got ${options.port}).`);
|
|
72350
|
+
}
|
|
72351
|
+
const server = await startApiServer({
|
|
72352
|
+
routes,
|
|
72353
|
+
pool,
|
|
72354
|
+
rieTimeoutMs,
|
|
72355
|
+
host: options.host,
|
|
72356
|
+
port
|
|
72357
|
+
});
|
|
72358
|
+
printRouteTable(routes);
|
|
72359
|
+
logger.info(
|
|
72360
|
+
`Per-Lambda concurrency: ${perLambdaConcurrency} (override with --per-lambda-concurrency)`
|
|
72361
|
+
);
|
|
72362
|
+
process.stdout.write(`Server listening on http://${server.host}:${server.port}
|
|
72363
|
+
`);
|
|
72364
|
+
process.stdout.write("^C to stop and clean up containers.\n");
|
|
72365
|
+
let shuttingDown = false;
|
|
72366
|
+
let forceExitArmed = false;
|
|
72367
|
+
const shutdown = async (signal, exitCode) => {
|
|
72368
|
+
if (shuttingDown) {
|
|
72369
|
+
if (!forceExitArmed) {
|
|
72370
|
+
forceExitArmed = true;
|
|
72371
|
+
logger.warn(
|
|
72372
|
+
`Received second ${signal}; force-exiting. Orphan containers may remain \u2014 run 'docker ps --filter name=cdkd-local-' and 'docker rm -f' to clean up.`
|
|
72373
|
+
);
|
|
72374
|
+
process.exit(130);
|
|
72375
|
+
}
|
|
72376
|
+
return;
|
|
72377
|
+
}
|
|
72378
|
+
shuttingDown = true;
|
|
72379
|
+
logger.info(`Received ${signal}, shutting down...`);
|
|
72380
|
+
try {
|
|
72381
|
+
await server.close();
|
|
72382
|
+
} catch (err) {
|
|
72383
|
+
logger.warn(`server.close() failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
72384
|
+
}
|
|
72385
|
+
try {
|
|
72386
|
+
await pool.dispose();
|
|
72387
|
+
} catch (err) {
|
|
72388
|
+
logger.warn(`pool.dispose() failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
72389
|
+
}
|
|
72390
|
+
for (const dir of inlineTmpDirs) {
|
|
72391
|
+
try {
|
|
72392
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
72393
|
+
} catch (err) {
|
|
72394
|
+
logger.warn(
|
|
72395
|
+
`Failed to remove inline-code tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`
|
|
72396
|
+
);
|
|
72397
|
+
}
|
|
72398
|
+
}
|
|
72399
|
+
process.exit(exitCode);
|
|
72400
|
+
};
|
|
72401
|
+
process.on("SIGINT", () => {
|
|
72402
|
+
void shutdown("SIGINT", 130);
|
|
72403
|
+
});
|
|
72404
|
+
process.on("SIGTERM", () => {
|
|
72405
|
+
void shutdown("SIGTERM", 0);
|
|
72406
|
+
});
|
|
72407
|
+
process.on("uncaughtException", (err) => {
|
|
72408
|
+
logger.error(
|
|
72409
|
+
`Uncaught exception: ${err instanceof Error ? err.stack ?? err.message : String(err)}`
|
|
72410
|
+
);
|
|
72411
|
+
void shutdown("uncaughtException", 1);
|
|
72412
|
+
});
|
|
72413
|
+
process.on("unhandledRejection", (reason) => {
|
|
72414
|
+
logger.error(
|
|
72415
|
+
`Unhandled rejection: ${reason instanceof Error ? reason.stack ?? reason.message : String(reason)}`
|
|
72416
|
+
);
|
|
72417
|
+
void shutdown("unhandledRejection", 1);
|
|
72418
|
+
});
|
|
72419
|
+
await new Promise(() => void 0);
|
|
72420
|
+
}
|
|
72421
|
+
function pickTargetStacks(stacks, pattern) {
|
|
72422
|
+
if (pattern) {
|
|
72423
|
+
return matchStacks(stacks, [pattern]);
|
|
72424
|
+
}
|
|
72425
|
+
if (stacks.length === 1)
|
|
72426
|
+
return stacks;
|
|
72427
|
+
if (stacks.length === 0)
|
|
72428
|
+
return [];
|
|
72429
|
+
throw new Error(
|
|
72430
|
+
`Multi-stack app: pass --stack <name> to pick a target. Available stacks: ${stacks.map((s) => s.stackName).join(", ")}.`
|
|
72431
|
+
);
|
|
72432
|
+
}
|
|
72433
|
+
function uniqueLambdaIds(routes) {
|
|
72434
|
+
const seen = /* @__PURE__ */ new Set();
|
|
72435
|
+
const out = [];
|
|
72436
|
+
for (const r of routes) {
|
|
72437
|
+
if (!seen.has(r.lambdaLogicalId)) {
|
|
72438
|
+
seen.add(r.lambdaLogicalId);
|
|
72439
|
+
out.push(r.lambdaLogicalId);
|
|
72440
|
+
}
|
|
72441
|
+
}
|
|
72442
|
+
return out;
|
|
72443
|
+
}
|
|
72444
|
+
async function buildContainerSpec(args) {
|
|
72445
|
+
const {
|
|
72446
|
+
logicalId,
|
|
72447
|
+
stacks,
|
|
72448
|
+
overrides,
|
|
72449
|
+
assumeRole,
|
|
72450
|
+
containerHost,
|
|
72451
|
+
debugPort,
|
|
72452
|
+
stsRegion,
|
|
72453
|
+
inlineTmpDirs
|
|
72454
|
+
} = args;
|
|
72455
|
+
const lambda = resolveLambdaByLogicalId(logicalId, stacks);
|
|
70660
72456
|
const codeDir = lambda.codePath ?? materializeInlineCode(
|
|
70661
72457
|
lambda.handler,
|
|
70662
72458
|
lambda.inlineCode ?? "",
|
|
70663
|
-
resolveRuntimeFileExtension(lambda.runtime)
|
|
72459
|
+
resolveRuntimeFileExtension(lambda.runtime),
|
|
72460
|
+
inlineTmpDirs
|
|
70664
72461
|
);
|
|
72462
|
+
const templateEnv = getTemplateEnv(lambda.resource);
|
|
72463
|
+
const envResult = resolveEnvVars(logicalId, templateEnv, overrides);
|
|
72464
|
+
for (const key of envResult.unresolved) {
|
|
72465
|
+
getLogger().warn(
|
|
72466
|
+
`Lambda ${logicalId}: env var ${key} contains a CloudFormation intrinsic and was dropped. Override it with --env-vars (e.g. {"${logicalId}":{"${key}":"<literal>"}}) to surface a literal value.`
|
|
72467
|
+
);
|
|
72468
|
+
}
|
|
72469
|
+
const dockerEnv = {
|
|
72470
|
+
AWS_LAMBDA_FUNCTION_NAME: logicalId,
|
|
72471
|
+
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: String(lambda.memoryMb),
|
|
72472
|
+
AWS_LAMBDA_FUNCTION_TIMEOUT: String(lambda.timeoutSec),
|
|
72473
|
+
AWS_LAMBDA_FUNCTION_VERSION: "$LATEST",
|
|
72474
|
+
AWS_LAMBDA_LOG_GROUP_NAME: `/aws/lambda/${logicalId}`,
|
|
72475
|
+
AWS_LAMBDA_LOG_STREAM_NAME: "local",
|
|
72476
|
+
...envResult.resolved
|
|
72477
|
+
};
|
|
72478
|
+
const roleArn = effectiveAssumeRoleArn(logicalId, assumeRole);
|
|
72479
|
+
if (roleArn) {
|
|
72480
|
+
const creds = await assumeLambdaExecutionRole(roleArn, stsRegion);
|
|
72481
|
+
dockerEnv["AWS_ACCESS_KEY_ID"] = creds.accessKeyId;
|
|
72482
|
+
dockerEnv["AWS_SECRET_ACCESS_KEY"] = creds.secretAccessKey;
|
|
72483
|
+
dockerEnv["AWS_SESSION_TOKEN"] = creds.sessionToken;
|
|
72484
|
+
if (stsRegion)
|
|
72485
|
+
dockerEnv["AWS_REGION"] = stsRegion;
|
|
72486
|
+
} else {
|
|
72487
|
+
forwardAwsEnv(dockerEnv);
|
|
72488
|
+
}
|
|
72489
|
+
if (debugPort !== void 0) {
|
|
72490
|
+
dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
|
|
72491
|
+
}
|
|
72492
|
+
const spec = {
|
|
72493
|
+
lambda,
|
|
72494
|
+
codeDir,
|
|
72495
|
+
env: dockerEnv,
|
|
72496
|
+
containerHost,
|
|
72497
|
+
...debugPort !== void 0 && { debugPort }
|
|
72498
|
+
};
|
|
72499
|
+
return spec;
|
|
72500
|
+
}
|
|
72501
|
+
function resolveLambdaByLogicalId(logicalId, stacks) {
|
|
72502
|
+
for (const stack of stacks) {
|
|
72503
|
+
const resource = stack.template.Resources?.[logicalId];
|
|
72504
|
+
if (!resource || resource.Type !== "AWS::Lambda::Function")
|
|
72505
|
+
continue;
|
|
72506
|
+
const props = resource.Properties ?? {};
|
|
72507
|
+
const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
|
|
72508
|
+
const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
|
|
72509
|
+
const memoryMb = typeof props["MemorySize"] === "number" ? props["MemorySize"] : 128;
|
|
72510
|
+
const timeoutSec = typeof props["Timeout"] === "number" ? props["Timeout"] : 3;
|
|
72511
|
+
if (!runtime) {
|
|
72512
|
+
throw new Error(
|
|
72513
|
+
`Lambda '${logicalId}' has no Runtime property. Container-image Lambdas (Code.ImageUri) are not supported in cdkd local start-api v1.`
|
|
72514
|
+
);
|
|
72515
|
+
}
|
|
72516
|
+
if (!handler) {
|
|
72517
|
+
throw new Error(`Lambda '${logicalId}' has no Handler property.`);
|
|
72518
|
+
}
|
|
72519
|
+
const code = props["Code"] ?? {};
|
|
72520
|
+
const imageUri = code["ImageUri"];
|
|
72521
|
+
if (typeof imageUri === "string" || typeof imageUri === "object" && imageUri !== null && "Fn::Sub" in imageUri) {
|
|
72522
|
+
throw new Error(
|
|
72523
|
+
`Lambda '${logicalId}' uses Code.ImageUri (container-image Lambda). 'cdkd local start-api' v1 supports ZIP Lambdas only \u2014 container-image support is deferred to a follow-up PR. Use 'cdkd local invoke' to exercise this function locally.`
|
|
72524
|
+
);
|
|
72525
|
+
}
|
|
72526
|
+
const inlineCode = typeof code["ZipFile"] === "string" ? code["ZipFile"] : void 0;
|
|
72527
|
+
let codePath = null;
|
|
72528
|
+
if (!inlineCode) {
|
|
72529
|
+
codePath = resolveAssetCodePath2(stack, logicalId, resource);
|
|
72530
|
+
}
|
|
72531
|
+
return {
|
|
72532
|
+
kind: "zip",
|
|
72533
|
+
stack,
|
|
72534
|
+
logicalId,
|
|
72535
|
+
resource,
|
|
72536
|
+
runtime,
|
|
72537
|
+
handler,
|
|
72538
|
+
memoryMb,
|
|
72539
|
+
timeoutSec,
|
|
72540
|
+
codePath,
|
|
72541
|
+
...inlineCode !== void 0 && { inlineCode }
|
|
72542
|
+
};
|
|
72543
|
+
}
|
|
72544
|
+
throw new Error(
|
|
72545
|
+
`No AWS::Lambda::Function resource named '${logicalId}' found in target stacks. This is likely a synthesis bug \u2014 the route-discovery phase resolved a route to this logical ID.`
|
|
72546
|
+
);
|
|
72547
|
+
}
|
|
72548
|
+
function resolveAssetCodePath2(stack, logicalId, resource) {
|
|
72549
|
+
const meta = resource.Metadata;
|
|
72550
|
+
const assetPath = meta?.["aws:asset:path"];
|
|
72551
|
+
if (typeof assetPath !== "string" || assetPath.length === 0) {
|
|
72552
|
+
throw new Error(
|
|
72553
|
+
`Lambda '${logicalId}' has no Metadata['aws:asset:path']. cdkd local start-api needs this hint to find the local asset directory. Re-synthesize the app and retry.`
|
|
72554
|
+
);
|
|
72555
|
+
}
|
|
72556
|
+
const cdkOutDir = stack.assetManifestPath ? path.dirname(stack.assetManifestPath) : process.cwd();
|
|
72557
|
+
return path.isAbsolute(assetPath) ? assetPath : path.resolve(cdkOutDir, assetPath);
|
|
72558
|
+
}
|
|
72559
|
+
function printRouteTable(routes) {
|
|
72560
|
+
const sorted = [...routes].sort((a, b) => {
|
|
72561
|
+
if (a.pathPattern !== b.pathPattern)
|
|
72562
|
+
return a.pathPattern.localeCompare(b.pathPattern);
|
|
72563
|
+
return a.method.localeCompare(b.method);
|
|
72564
|
+
});
|
|
72565
|
+
const methodWidth = Math.max(...sorted.map((r) => r.method.length), 6);
|
|
72566
|
+
const pathWidth = Math.max(...sorted.map((r) => r.pathPattern.length), 8);
|
|
72567
|
+
process.stdout.write("Discovered routes:\n");
|
|
72568
|
+
for (const r of sorted) {
|
|
72569
|
+
const sourceLabel = r.source === "http-api" ? "HTTP API" : r.source === "rest-v1" ? `REST v1, stage '${r.stage}'` : "Function URL";
|
|
72570
|
+
process.stdout.write(
|
|
72571
|
+
` ${r.method.padEnd(methodWidth)} ${r.pathPattern.padEnd(pathWidth)} -> ${r.lambdaLogicalId} (${sourceLabel})
|
|
72572
|
+
`
|
|
72573
|
+
);
|
|
72574
|
+
}
|
|
72575
|
+
process.stdout.write("\n");
|
|
72576
|
+
}
|
|
72577
|
+
function materializeInlineCode(handler, source, fileExtension, tmpDirsOut) {
|
|
72578
|
+
const lastDot = handler.lastIndexOf(".");
|
|
72579
|
+
if (lastDot <= 0) {
|
|
72580
|
+
throw new Error(`Handler '${handler}' is malformed: expected '<modulePath>.<exportName>'.`);
|
|
72581
|
+
}
|
|
72582
|
+
const modulePath = handler.substring(0, lastDot);
|
|
72583
|
+
const dir = mkdtempSync2(path.join(tmpdir2(), "cdkd-local-start-api-"));
|
|
72584
|
+
tmpDirsOut.add(dir);
|
|
72585
|
+
const filePath = path.join(dir, `${modulePath}${fileExtension}`);
|
|
72586
|
+
mkdirSync2(path.dirname(filePath), { recursive: true });
|
|
72587
|
+
writeFileSync5(filePath, source, "utf-8");
|
|
72588
|
+
return dir;
|
|
72589
|
+
}
|
|
72590
|
+
function getTemplateEnv(resource) {
|
|
72591
|
+
const props = resource.Properties ?? {};
|
|
72592
|
+
const env = props["Environment"];
|
|
72593
|
+
if (!env || typeof env !== "object")
|
|
72594
|
+
return void 0;
|
|
72595
|
+
const vars = env["Variables"];
|
|
72596
|
+
if (!vars || typeof vars !== "object")
|
|
72597
|
+
return void 0;
|
|
72598
|
+
return vars;
|
|
72599
|
+
}
|
|
72600
|
+
function readEnvOverridesFile(filePath) {
|
|
72601
|
+
if (!filePath)
|
|
72602
|
+
return void 0;
|
|
72603
|
+
let raw;
|
|
72604
|
+
try {
|
|
72605
|
+
raw = readFileSync6(filePath, "utf-8");
|
|
72606
|
+
} catch (err) {
|
|
72607
|
+
throw new Error(
|
|
72608
|
+
`Failed to read --env-vars file '${filePath}': ${err instanceof Error ? err.message : String(err)}`
|
|
72609
|
+
);
|
|
72610
|
+
}
|
|
72611
|
+
let parsed;
|
|
72612
|
+
try {
|
|
72613
|
+
parsed = JSON.parse(raw);
|
|
72614
|
+
} catch (err) {
|
|
72615
|
+
throw new Error(
|
|
72616
|
+
`Failed to parse --env-vars file '${filePath}' as JSON: ${err instanceof Error ? err.message : String(err)}`
|
|
72617
|
+
);
|
|
72618
|
+
}
|
|
72619
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
72620
|
+
throw new Error(`--env-vars file '${filePath}' must contain a JSON object at the top level.`);
|
|
72621
|
+
}
|
|
72622
|
+
return parsed;
|
|
72623
|
+
}
|
|
72624
|
+
function forwardAwsEnv(env) {
|
|
72625
|
+
const passThrough = [
|
|
72626
|
+
"AWS_ACCESS_KEY_ID",
|
|
72627
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
72628
|
+
"AWS_SESSION_TOKEN",
|
|
72629
|
+
"AWS_REGION",
|
|
72630
|
+
"AWS_DEFAULT_REGION"
|
|
72631
|
+
];
|
|
72632
|
+
for (const key of passThrough) {
|
|
72633
|
+
const value = process.env[key];
|
|
72634
|
+
if (value !== void 0)
|
|
72635
|
+
env[key] = value;
|
|
72636
|
+
}
|
|
72637
|
+
}
|
|
72638
|
+
async function assumeLambdaExecutionRole(roleArn, region) {
|
|
72639
|
+
const { STSClient: STSClient11, AssumeRoleCommand: AssumeRoleCommand2 } = await import("@aws-sdk/client-sts");
|
|
72640
|
+
const sts = new STSClient11({ ...region && { region } });
|
|
72641
|
+
try {
|
|
72642
|
+
const response = await sts.send(
|
|
72643
|
+
new AssumeRoleCommand2({
|
|
72644
|
+
RoleArn: roleArn,
|
|
72645
|
+
RoleSessionName: `cdkd-local-start-api-${Date.now()}`,
|
|
72646
|
+
DurationSeconds: 3600
|
|
72647
|
+
})
|
|
72648
|
+
);
|
|
72649
|
+
const creds = response.Credentials;
|
|
72650
|
+
if (!creds?.AccessKeyId || !creds.SecretAccessKey || !creds.SessionToken) {
|
|
72651
|
+
throw new Error(`AssumeRole(${roleArn}) returned no usable credentials.`);
|
|
72652
|
+
}
|
|
72653
|
+
return {
|
|
72654
|
+
accessKeyId: creds.AccessKeyId,
|
|
72655
|
+
secretAccessKey: creds.SecretAccessKey,
|
|
72656
|
+
sessionToken: creds.SessionToken
|
|
72657
|
+
};
|
|
72658
|
+
} finally {
|
|
72659
|
+
sts.destroy();
|
|
72660
|
+
}
|
|
72661
|
+
}
|
|
72662
|
+
function parsePerLambdaConcurrency(raw) {
|
|
72663
|
+
const parsed = parseInt(raw, 10);
|
|
72664
|
+
if (!Number.isFinite(parsed) || parsed < 1) {
|
|
72665
|
+
throw new Error(`--per-lambda-concurrency must be a positive integer (got '${raw}')`);
|
|
72666
|
+
}
|
|
72667
|
+
if (parsed > 4) {
|
|
72668
|
+
getLogger().warn(
|
|
72669
|
+
`--per-lambda-concurrency ${parsed} exceeds the v1 cap of 4; clamping to 4. (Raise this in a follow-up PR if your workload needs more.)`
|
|
72670
|
+
);
|
|
72671
|
+
return 4;
|
|
72672
|
+
}
|
|
72673
|
+
return parsed;
|
|
72674
|
+
}
|
|
72675
|
+
function parseDebugPort(raw) {
|
|
72676
|
+
const parsed = parseInt(raw, 10);
|
|
72677
|
+
if (!Number.isFinite(parsed) || parsed < 1 || parsed > 65535) {
|
|
72678
|
+
throw new Error(`--debug-port-base must be 1..65535 (got '${raw}')`);
|
|
72679
|
+
}
|
|
72680
|
+
return parsed;
|
|
72681
|
+
}
|
|
72682
|
+
function createLocalStartApiCommand() {
|
|
72683
|
+
const startApi = new Command14("start-api").description(
|
|
72684
|
+
"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)."
|
|
72685
|
+
).addOption(
|
|
72686
|
+
new Option7("--port <port>", "HTTP server port (default: auto-allocate)").default("0")
|
|
72687
|
+
).addOption(new Option7("--host <host>", "Bind address").default("127.0.0.1")).addOption(new Option7("--stack <name>", "Stack to start (single-stack apps auto-detect)")).addOption(
|
|
72688
|
+
new Option7("--warm", "Pre-start one container per Lambda at server boot").default(false)
|
|
72689
|
+
).addOption(
|
|
72690
|
+
new Option7(
|
|
72691
|
+
"--per-lambda-concurrency <n>",
|
|
72692
|
+
"Pool size cap per Lambda (default 2, max 4)"
|
|
72693
|
+
).default("2")
|
|
72694
|
+
).addOption(new Option7("--no-pull", "Skip docker pull (cached image)")).addOption(
|
|
72695
|
+
new Option7(
|
|
72696
|
+
"--container-host <host>",
|
|
72697
|
+
"Hostname/IP the container reaches the host on"
|
|
72698
|
+
).default("host.docker.internal")
|
|
72699
|
+
).addOption(
|
|
72700
|
+
new Option7(
|
|
72701
|
+
"--debug-port-base <port>",
|
|
72702
|
+
"Reserve a contiguous --debug-port range (one per Lambda)"
|
|
72703
|
+
)
|
|
72704
|
+
).addOption(
|
|
72705
|
+
new Option7(
|
|
72706
|
+
"--env-vars <file>",
|
|
72707
|
+
'JSON env-var overrides (SAM-compatible: {"LogicalId":{"KEY":"VALUE"}, "Parameters": {...}})'
|
|
72708
|
+
)
|
|
72709
|
+
).addOption(
|
|
72710
|
+
new Option7(
|
|
72711
|
+
"--assume-role <arn-or-pair>",
|
|
72712
|
+
"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)."
|
|
72713
|
+
).argParser((raw, prev) => parseAssumeRoleToken(raw, prev))
|
|
72714
|
+
).action(withErrorHandling(localStartApiCommand));
|
|
72715
|
+
[...commonOptions, ...appOptions, ...contextOptions].forEach((opt) => startApi.addOption(opt));
|
|
72716
|
+
startApi.addOption(deprecatedRegionOption);
|
|
72717
|
+
return startApi;
|
|
72718
|
+
}
|
|
72719
|
+
|
|
72720
|
+
// src/cli/commands/local-invoke.ts
|
|
72721
|
+
async function localInvokeCommand(target, options) {
|
|
72722
|
+
const logger = getLogger();
|
|
72723
|
+
if (options.verbose) {
|
|
72724
|
+
logger.setLevel("debug");
|
|
72725
|
+
}
|
|
72726
|
+
warnIfDeprecatedRegion(options);
|
|
72727
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
72728
|
+
await ensureDockerAvailable();
|
|
72729
|
+
const appCmd = resolveApp(options.app);
|
|
72730
|
+
if (!appCmd) {
|
|
72731
|
+
throw new Error('No CDK app specified. Pass --app, set CDKD_APP, or add "app" to cdk.json.');
|
|
72732
|
+
}
|
|
72733
|
+
logger.info("Synthesizing CDK app...");
|
|
72734
|
+
const synthesizer = new Synthesizer();
|
|
72735
|
+
const context = parseContextOptions(options.context);
|
|
72736
|
+
const synthOpts = {
|
|
72737
|
+
app: appCmd,
|
|
72738
|
+
output: options.output,
|
|
72739
|
+
...options.region && { region: options.region },
|
|
72740
|
+
...options.profile && { profile: options.profile },
|
|
72741
|
+
...Object.keys(context).length > 0 && { context }
|
|
72742
|
+
};
|
|
72743
|
+
const { stacks } = await synthesizer.synthesize(synthOpts);
|
|
72744
|
+
const lambda = resolveLambdaTarget(target, stacks);
|
|
72745
|
+
const targetLabel = lambda.kind === "zip" ? lambda.runtime : "container image";
|
|
72746
|
+
logger.info(`Target: ${lambda.stack.stackName}/${lambda.logicalId} (${targetLabel})`);
|
|
72747
|
+
const imagePlan = await resolveImagePlan(lambda, options);
|
|
70665
72748
|
let stateAudit;
|
|
70666
|
-
let templateEnv =
|
|
72749
|
+
let templateEnv = getTemplateEnv2(lambda.resource);
|
|
70667
72750
|
let stateForRoleHint;
|
|
70668
72751
|
if (options.fromState) {
|
|
70669
72752
|
const loaded = await loadStateForStack(lambda.stack.stackName, lambda.stack.region, {
|
|
@@ -70688,7 +72771,7 @@ async function localInvokeCommand(target, options) {
|
|
|
70688
72771
|
}
|
|
70689
72772
|
}
|
|
70690
72773
|
}
|
|
70691
|
-
const overrides =
|
|
72774
|
+
const overrides = readEnvOverridesFile2(options.envVars);
|
|
70692
72775
|
const envResult = resolveEnvVars(lambda.logicalId, templateEnv, overrides);
|
|
70693
72776
|
for (const key of envResult.unresolved) {
|
|
70694
72777
|
if (stateAudit && stateAudit.unresolved.some((u) => u.key === key))
|
|
@@ -70701,7 +72784,6 @@ async function localInvokeCommand(target, options) {
|
|
|
70701
72784
|
suggestAssumeRoleFromState(stateForRoleHint, lambda.logicalId);
|
|
70702
72785
|
}
|
|
70703
72786
|
const event = await readEvent(options);
|
|
70704
|
-
const image = resolveRuntimeImage(lambda.runtime);
|
|
70705
72787
|
const dockerEnv = {
|
|
70706
72788
|
AWS_LAMBDA_FUNCTION_NAME: lambda.logicalId,
|
|
70707
72789
|
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: String(lambda.memoryMb),
|
|
@@ -70713,14 +72795,14 @@ async function localInvokeCommand(target, options) {
|
|
|
70713
72795
|
};
|
|
70714
72796
|
if (options.assumeRole) {
|
|
70715
72797
|
const stsRegion = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"];
|
|
70716
|
-
const creds = await
|
|
72798
|
+
const creds = await assumeLambdaExecutionRole2(options.assumeRole, stsRegion);
|
|
70717
72799
|
dockerEnv["AWS_ACCESS_KEY_ID"] = creds.accessKeyId;
|
|
70718
72800
|
dockerEnv["AWS_SECRET_ACCESS_KEY"] = creds.secretAccessKey;
|
|
70719
72801
|
dockerEnv["AWS_SESSION_TOKEN"] = creds.sessionToken;
|
|
70720
72802
|
if (stsRegion)
|
|
70721
72803
|
dockerEnv["AWS_REGION"] = stsRegion;
|
|
70722
72804
|
} else {
|
|
70723
|
-
|
|
72805
|
+
forwardAwsEnv2(dockerEnv);
|
|
70724
72806
|
}
|
|
70725
72807
|
let debugPort;
|
|
70726
72808
|
if (options.debugPort) {
|
|
@@ -70729,19 +72811,26 @@ async function localInvokeCommand(target, options) {
|
|
|
70729
72811
|
throw new Error(`--debug-port must be an integer in 1..65535, got '${options.debugPort}'`);
|
|
70730
72812
|
}
|
|
70731
72813
|
dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
|
|
72814
|
+
if (lambda.kind === "image") {
|
|
72815
|
+
logger.warn(
|
|
72816
|
+
"--debug-port sets NODE_OPTIONS unconditionally on container Lambdas. If the image's runtime is not Node.js, this flag is a no-op."
|
|
72817
|
+
);
|
|
72818
|
+
}
|
|
70732
72819
|
}
|
|
70733
|
-
await pullImage(image, options.pull === false);
|
|
70734
72820
|
const hostPort = await pickFreePort();
|
|
70735
|
-
const containerHost = options.containerHost
|
|
70736
|
-
logger.info(`Starting container (image=${image}, port=${hostPort})...`);
|
|
72821
|
+
const containerHost = options.containerHost;
|
|
72822
|
+
logger.info(`Starting container (image=${imagePlan.image}, port=${hostPort})...`);
|
|
70737
72823
|
const containerId = await runDetached({
|
|
70738
|
-
image,
|
|
70739
|
-
mounts:
|
|
72824
|
+
image: imagePlan.image,
|
|
72825
|
+
mounts: imagePlan.mounts,
|
|
70740
72826
|
env: dockerEnv,
|
|
70741
|
-
cmd:
|
|
72827
|
+
cmd: imagePlan.cmd,
|
|
70742
72828
|
hostPort,
|
|
70743
72829
|
host: containerHost,
|
|
70744
|
-
...debugPort !== void 0 && { debugPort }
|
|
72830
|
+
...debugPort !== void 0 && { debugPort },
|
|
72831
|
+
...imagePlan.platform !== void 0 && { platform: imagePlan.platform },
|
|
72832
|
+
...imagePlan.entryPoint !== void 0 && { entryPoint: imagePlan.entryPoint },
|
|
72833
|
+
...imagePlan.workingDir !== void 0 && { workingDir: imagePlan.workingDir }
|
|
70745
72834
|
});
|
|
70746
72835
|
const stopLogs = streamLogs(containerId);
|
|
70747
72836
|
const sigintHandler = () => {
|
|
@@ -70762,9 +72851,94 @@ async function localInvokeCommand(target, options) {
|
|
|
70762
72851
|
process.off("SIGINT", sigintHandler);
|
|
70763
72852
|
stopLogs();
|
|
70764
72853
|
await removeContainer(containerId);
|
|
72854
|
+
if (imagePlan.inlineTmpDir) {
|
|
72855
|
+
try {
|
|
72856
|
+
rmSync3(imagePlan.inlineTmpDir, { recursive: true, force: true });
|
|
72857
|
+
} catch (err) {
|
|
72858
|
+
getLogger().debug(
|
|
72859
|
+
`Failed to remove inline-code tmpdir ${imagePlan.inlineTmpDir}: ${err instanceof Error ? err.message : String(err)}`
|
|
72860
|
+
);
|
|
72861
|
+
}
|
|
72862
|
+
}
|
|
70765
72863
|
}
|
|
70766
72864
|
}
|
|
70767
|
-
function
|
|
72865
|
+
async function resolveImagePlan(lambda, options) {
|
|
72866
|
+
if (lambda.kind === "zip") {
|
|
72867
|
+
return resolveZipImagePlan(lambda, options);
|
|
72868
|
+
}
|
|
72869
|
+
return resolveContainerImagePlan(lambda, options);
|
|
72870
|
+
}
|
|
72871
|
+
async function resolveZipImagePlan(lambda, options) {
|
|
72872
|
+
let inlineTmpDir;
|
|
72873
|
+
let codeDir = lambda.codePath;
|
|
72874
|
+
if (codeDir === null) {
|
|
72875
|
+
inlineTmpDir = materializeInlineCode2(
|
|
72876
|
+
lambda.handler,
|
|
72877
|
+
lambda.inlineCode ?? "",
|
|
72878
|
+
resolveRuntimeFileExtension(lambda.runtime)
|
|
72879
|
+
);
|
|
72880
|
+
codeDir = inlineTmpDir;
|
|
72881
|
+
}
|
|
72882
|
+
const image = resolveRuntimeImage(lambda.runtime);
|
|
72883
|
+
await pullImage(image, options.pull === false);
|
|
72884
|
+
return {
|
|
72885
|
+
image,
|
|
72886
|
+
mounts: [{ hostPath: codeDir, containerPath: "/var/task", readOnly: true }],
|
|
72887
|
+
cmd: [lambda.handler],
|
|
72888
|
+
...inlineTmpDir !== void 0 && { inlineTmpDir }
|
|
72889
|
+
};
|
|
72890
|
+
}
|
|
72891
|
+
async function resolveContainerImagePlan(lambda, options) {
|
|
72892
|
+
const logger = getLogger();
|
|
72893
|
+
const platform = architectureToPlatform(lambda.architecture);
|
|
72894
|
+
const localBuild = await resolveLocalBuildPlan(lambda);
|
|
72895
|
+
let imageRef;
|
|
72896
|
+
if (localBuild) {
|
|
72897
|
+
imageRef = await buildContainerImage(localBuild.asset, localBuild.cdkOutDir, {
|
|
72898
|
+
architecture: lambda.architecture
|
|
72899
|
+
});
|
|
72900
|
+
} else {
|
|
72901
|
+
if (!parseEcrUri(lambda.imageUri)) {
|
|
72902
|
+
throw new Error(
|
|
72903
|
+
`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.`
|
|
72904
|
+
);
|
|
72905
|
+
}
|
|
72906
|
+
logger.info(
|
|
72907
|
+
`No matching cdk.out asset for ${lambda.imageUri}; falling back to ECR pull (same-acct/region only)...`
|
|
72908
|
+
);
|
|
72909
|
+
imageRef = await pullEcrImage(lambda.imageUri, {
|
|
72910
|
+
skipPull: options.pull === false,
|
|
72911
|
+
...options.region !== void 0 && { region: options.region }
|
|
72912
|
+
});
|
|
72913
|
+
}
|
|
72914
|
+
return {
|
|
72915
|
+
image: imageRef,
|
|
72916
|
+
mounts: [],
|
|
72917
|
+
cmd: lambda.imageConfig.command ?? [],
|
|
72918
|
+
platform,
|
|
72919
|
+
...lambda.imageConfig.entryPoint && lambda.imageConfig.entryPoint.length > 0 && {
|
|
72920
|
+
entryPoint: lambda.imageConfig.entryPoint
|
|
72921
|
+
},
|
|
72922
|
+
...lambda.imageConfig.workingDirectory !== void 0 && {
|
|
72923
|
+
workingDir: lambda.imageConfig.workingDirectory
|
|
72924
|
+
}
|
|
72925
|
+
};
|
|
72926
|
+
}
|
|
72927
|
+
async function resolveLocalBuildPlan(lambda) {
|
|
72928
|
+
const manifestPath = lambda.stack.assetManifestPath;
|
|
72929
|
+
if (!manifestPath)
|
|
72930
|
+
return void 0;
|
|
72931
|
+
const cdkOutDir = dirname3(manifestPath);
|
|
72932
|
+
const loader = new AssetManifestLoader();
|
|
72933
|
+
const manifest = await loader.loadManifest(cdkOutDir, lambda.stack.stackName);
|
|
72934
|
+
if (!manifest)
|
|
72935
|
+
return void 0;
|
|
72936
|
+
const entry = getDockerImageBySourceHash(manifest, lambda.imageUri);
|
|
72937
|
+
if (!entry)
|
|
72938
|
+
return void 0;
|
|
72939
|
+
return { asset: entry.asset, cdkOutDir };
|
|
72940
|
+
}
|
|
72941
|
+
function getTemplateEnv2(resource) {
|
|
70768
72942
|
const props = resource.Properties ?? {};
|
|
70769
72943
|
const env = props["Environment"];
|
|
70770
72944
|
if (!env || typeof env !== "object")
|
|
@@ -70774,12 +72948,12 @@ function getTemplateEnv(resource) {
|
|
|
70774
72948
|
return void 0;
|
|
70775
72949
|
return vars;
|
|
70776
72950
|
}
|
|
70777
|
-
function
|
|
72951
|
+
function readEnvOverridesFile2(filePath) {
|
|
70778
72952
|
if (!filePath)
|
|
70779
72953
|
return void 0;
|
|
70780
72954
|
let raw;
|
|
70781
72955
|
try {
|
|
70782
|
-
raw =
|
|
72956
|
+
raw = readFileSync7(filePath, "utf-8");
|
|
70783
72957
|
} catch (err) {
|
|
70784
72958
|
throw new Error(
|
|
70785
72959
|
`Failed to read --env-vars file '${filePath}': ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -70807,7 +72981,7 @@ async function readEvent(options) {
|
|
|
70807
72981
|
return parseEvent(raw, "<stdin>");
|
|
70808
72982
|
}
|
|
70809
72983
|
if (options.event) {
|
|
70810
|
-
const raw =
|
|
72984
|
+
const raw = readFileSync7(options.event, "utf-8");
|
|
70811
72985
|
return parseEvent(raw, options.event);
|
|
70812
72986
|
}
|
|
70813
72987
|
return {};
|
|
@@ -70828,9 +73002,9 @@ async function readStdin() {
|
|
|
70828
73002
|
}
|
|
70829
73003
|
return Buffer.concat(chunks).toString("utf-8");
|
|
70830
73004
|
}
|
|
70831
|
-
async function
|
|
70832
|
-
const { STSClient:
|
|
70833
|
-
const sts = new
|
|
73005
|
+
async function assumeLambdaExecutionRole2(roleArn, region) {
|
|
73006
|
+
const { STSClient: STSClient11, AssumeRoleCommand: AssumeRoleCommand2 } = await import("@aws-sdk/client-sts");
|
|
73007
|
+
const sts = new STSClient11({ ...region && { region } });
|
|
70834
73008
|
try {
|
|
70835
73009
|
const response = await sts.send(
|
|
70836
73010
|
new AssumeRoleCommand2({
|
|
@@ -70852,7 +73026,7 @@ async function assumeLambdaExecutionRole(roleArn, region) {
|
|
|
70852
73026
|
sts.destroy();
|
|
70853
73027
|
}
|
|
70854
73028
|
}
|
|
70855
|
-
function
|
|
73029
|
+
function forwardAwsEnv2(env) {
|
|
70856
73030
|
const passThrough = [
|
|
70857
73031
|
"AWS_ACCESS_KEY_ID",
|
|
70858
73032
|
"AWS_SECRET_ACCESS_KEY",
|
|
@@ -70866,16 +73040,16 @@ function forwardAwsEnv(env) {
|
|
|
70866
73040
|
env[key] = value;
|
|
70867
73041
|
}
|
|
70868
73042
|
}
|
|
70869
|
-
function
|
|
73043
|
+
function materializeInlineCode2(handler, source, fileExtension) {
|
|
70870
73044
|
const lastDot = handler.lastIndexOf(".");
|
|
70871
73045
|
if (lastDot <= 0) {
|
|
70872
73046
|
throw new Error(`Handler '${handler}' is malformed: expected '<modulePath>.<exportName>'.`);
|
|
70873
73047
|
}
|
|
70874
73048
|
const modulePath = handler.substring(0, lastDot);
|
|
70875
|
-
const dir =
|
|
70876
|
-
const filePath =
|
|
70877
|
-
|
|
70878
|
-
|
|
73049
|
+
const dir = mkdtempSync3(path2.join(tmpdir3(), "cdkd-local-invoke-"));
|
|
73050
|
+
const filePath = path2.join(dir, `${modulePath}${fileExtension}`);
|
|
73051
|
+
mkdirSync3(path2.dirname(filePath), { recursive: true });
|
|
73052
|
+
writeFileSync6(filePath, source, "utf-8");
|
|
70879
73053
|
return dir;
|
|
70880
73054
|
}
|
|
70881
73055
|
async function loadStateForStack(stackName, synthRegion, opts) {
|
|
@@ -70982,30 +73156,35 @@ function pickReferencedLogicalId(intrinsic) {
|
|
|
70982
73156
|
return void 0;
|
|
70983
73157
|
}
|
|
70984
73158
|
function createLocalCommand() {
|
|
70985
|
-
const local = new
|
|
73159
|
+
const local = new Command15("local").description(
|
|
70986
73160
|
"Local Lambda execution against the AWS Lambda Runtime Interface Emulator (Docker required)"
|
|
70987
73161
|
);
|
|
70988
|
-
const invoke = new
|
|
73162
|
+
const invoke = new Command15("invoke").description(
|
|
70989
73163
|
"Run a Lambda function locally in a Docker container (RIE-backed). Target accepts a CDK display path (MyStack/MyApi/Handler) or stack-qualified logical ID (MyStack:MyApiHandler1234ABCD). Single-stack apps may omit the stack prefix."
|
|
70990
|
-
).argument("<target>", "CDK display path or stack-qualified logical ID of the Lambda to invoke").addOption(new
|
|
70991
|
-
new
|
|
73164
|
+
).argument("<target>", "CDK display path or stack-qualified logical ID of the Lambda to invoke").addOption(new Option8("-e, --event <file>", "JSON event payload file (default: {})")).addOption(new Option8("--event-stdin", "Read event JSON from stdin").default(false)).addOption(
|
|
73165
|
+
new Option8(
|
|
70992
73166
|
"--env-vars <file>",
|
|
70993
73167
|
'JSON env-var overrides (SAM-compatible: {"LogicalId":{"KEY":"VALUE"}})'
|
|
70994
73168
|
)
|
|
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(
|
|
70996
|
-
new Option7("--container-host <host>", "Host to bind the RIE port to").default("127.0.0.1")
|
|
70997
73169
|
).addOption(
|
|
70998
|
-
new
|
|
73170
|
+
new Option8(
|
|
73171
|
+
"--no-pull",
|
|
73172
|
+
"Skip docker pull (use cached image) \u2014 no-op for IMAGE local-build path; `docker build` does not pull base layers by default"
|
|
73173
|
+
)
|
|
73174
|
+
).addOption(new Option8("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(
|
|
73175
|
+
new Option8("--container-host <host>", "Host to bind the RIE port to").default("127.0.0.1")
|
|
73176
|
+
).addOption(
|
|
73177
|
+
new Option8(
|
|
70999
73178
|
"--assume-role <arn>",
|
|
71000
73179
|
`Assume the Lambda's deployed execution role and forward STS-issued temp credentials to the container so the handler runs with the deployed function's narrow permissions (closes the "developer admin / function narrow" skew). Off by default \u2014 when omitted, the developer's shell credentials are forwarded unchanged (SAM-compatible default).`
|
|
71001
73180
|
)
|
|
71002
73181
|
).addOption(
|
|
71003
|
-
new
|
|
73182
|
+
new Option8(
|
|
71004
73183
|
"--from-state",
|
|
71005
73184
|
"Read cdkd S3 state for the target stack and substitute Ref / Fn::GetAtt / Fn::Sub in env vars with the deployed physical IDs / attributes. Off by default \u2014 keep PR 1 warn-and-drop semantics; turn on for stacks already deployed via cdkd deploy."
|
|
71006
73185
|
).default(false)
|
|
71007
73186
|
).addOption(
|
|
71008
|
-
new
|
|
73187
|
+
new Option8(
|
|
71009
73188
|
"--stack-region <region>",
|
|
71010
73189
|
"Region of the cdkd state record to read (used with --from-state when the same stack name has state in multiple regions)."
|
|
71011
73190
|
)
|
|
@@ -71015,6 +73194,7 @@ function createLocalCommand() {
|
|
|
71015
73194
|
);
|
|
71016
73195
|
invoke.addOption(deprecatedRegionOption);
|
|
71017
73196
|
local.addCommand(invoke);
|
|
73197
|
+
local.addCommand(createLocalStartApiCommand());
|
|
71018
73198
|
return local;
|
|
71019
73199
|
}
|
|
71020
73200
|
|
|
@@ -71046,8 +73226,8 @@ function reorderArgs(argv) {
|
|
|
71046
73226
|
return [...prefix, ...cmdAndAfter, ...beforeCmd];
|
|
71047
73227
|
}
|
|
71048
73228
|
async function main() {
|
|
71049
|
-
const program = new
|
|
71050
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
73229
|
+
const program = new Command16();
|
|
73230
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.71.0");
|
|
71051
73231
|
program.addCommand(createBootstrapCommand());
|
|
71052
73232
|
program.addCommand(createSynthCommand());
|
|
71053
73233
|
program.addCommand(createListCommand());
|