@intentius/chant-lexicon-aws 0.18.14 → 0.18.16

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.
@@ -697,6 +697,7 @@ export const IntegrationResourceProperty = createResource("AWS::Glue::Integratio
697
697
  export const IntegrationResponse = createResource("AWS::ApiGatewayV2::IntegrationResponse", "aws", {"IntegrationResponseId":"IntegrationResponseId"});
698
698
  export const IntelligentPromptRouter = createResource("AWS::Bedrock::IntelligentPromptRouter", "aws", {"CreatedAt":"CreatedAt","PromptRouterArn":"PromptRouterArn","Status":"Status","Type":"Type","UpdatedAt":"UpdatedAt"});
699
699
  export const InterconnectConnection = createResource("AWS::Interconnect::Connection", "aws", {"ConnectionId":"ConnectionId","Arn":"Arn","Provider":"Provider","Type":"Type","State":"State","SharedId":"SharedId","OwnerAccount":"OwnerAccount","BillingTier":"BillingTier"});
700
+ export const IntermediateTable = createResource("AWS::CleanRooms::IntermediateTable", "aws", {"IntermediateTableIdentifier":"IntermediateTableIdentifier","Arn":"Arn","MembershipArn":"MembershipArn","CollaborationIdentifier":"CollaborationIdentifier","CollaborationArn":"CollaborationArn","Status":"Status"});
700
701
  export const InternetGateway = createResource("AWS::EC2::InternetGateway", "aws", {"InternetGatewayId":"InternetGatewayId"});
701
702
  export const InternetMonitorMonitor = createResource("AWS::InternetMonitor::Monitor", "aws", {"CreatedAt":"CreatedAt","ModifiedAt":"ModifiedAt","MonitorArn":"MonitorArn","ProcessingStatus":"ProcessingStatus","ProcessingStatusInfo":"ProcessingStatusInfo"});
702
703
  export const InvestigationGroup = createResource("AWS::AIOps::InvestigationGroup", "aws", {"CreatedBy":"CreatedBy","CreatedAt":"CreatedAt","LastModifiedBy":"LastModifiedBy","LastModifiedAt":"LastModifiedAt","Arn":"Arn"});
@@ -5873,6 +5874,13 @@ export const InterconnectConnection_Tag = createProperty("AWS::Interconnect::Con
5873
5874
  export const Interface = createProperty("AWS::MediaConnect::FlowOutput.Interface", "aws");
5874
5875
  export const InterfaceMapping = createProperty("AWS::MediaLive::Cluster.InterfaceMapping", "aws");
5875
5876
  export const IntermediateStorage = createProperty("AWS::Bedrock::DataSource.IntermediateStorage", "aws");
5877
+ export const IntermediateTable_IntermediateTableAnalysisRule = createProperty("AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRule", "aws");
5878
+ export const IntermediateTable_IntermediateTableAnalysisRulePolicy = createProperty("AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRulePolicy", "aws");
5879
+ export const IntermediateTable_PopulationAnalysisConfiguration = createProperty("AWS::CleanRooms::IntermediateTable.PopulationAnalysisConfiguration", "aws");
5880
+ export const IntermediateTable_PopulationAnalysisSqlParameters = createProperty("AWS::CleanRooms::IntermediateTable.PopulationAnalysisSqlParameters", "aws");
5881
+ export const IntermediateTable_Tag = createProperty("AWS::CleanRooms::IntermediateTable.Tag", "aws");
5882
+ export const IntermediateTableAnalysisRule = createProperty("AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRule", "aws");
5883
+ export const IntermediateTableAnalysisRulePolicy = createProperty("AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRulePolicy", "aws");
5876
5884
  export const InternetGateway_Tag = createProperty("AWS::EC2::InternetGateway.Tag", "aws");
5877
5885
  export const InternetMeasurementsLogDelivery = createProperty("AWS::InternetMonitor::Monitor.InternetMeasurementsLogDelivery", "aws");
5878
5886
  export const InternetMonitorMonitor_HealthEventsConfig = createProperty("AWS::InternetMonitor::Monitor.HealthEventsConfig", "aws");
@@ -6427,6 +6435,7 @@ export const Listener_JwtValidationConfig = createProperty("AWS::ElasticLoadBala
6427
6435
  export const Listener_ListenerAttribute = createProperty("AWS::ElasticLoadBalancingV2::Listener.ListenerAttribute", "aws");
6428
6436
  export const Listener_MutualAuthentication = createProperty("AWS::ElasticLoadBalancingV2::Listener.MutualAuthentication", "aws");
6429
6437
  export const Listener_RedirectConfig = createProperty("AWS::ElasticLoadBalancingV2::Listener.RedirectConfig", "aws");
6438
+ export const Listener_Tag = createProperty("AWS::ElasticLoadBalancingV2::Listener.Tag", "aws");
6430
6439
  export const Listener_TargetGroupStickinessConfig = createProperty("AWS::ElasticLoadBalancingV2::Listener.TargetGroupStickinessConfig", "aws");
6431
6440
  export const Listener_TargetGroupTuple = createProperty("AWS::ElasticLoadBalancingV2::Listener.TargetGroupTuple", "aws");
6432
6441
  export const ListenerAttribute = createProperty("AWS::ElasticLoadBalancingV2::Listener.ListenerAttribute", "aws");
@@ -7919,6 +7928,8 @@ export const PolicyStore_ValidationSettings = createProperty("AWS::VerifiedPermi
7919
7928
  export const PolicyTag = createProperty("AWS::FMS::Policy.PolicyTag", "aws");
7920
7929
  export const Pool_OptionalKeyword = createProperty("AWS::SMSVOICE::Pool.OptionalKeyword", "aws");
7921
7930
  export const Pool_Tag = createProperty("AWS::SMSVOICE::Pool.Tag", "aws");
7931
+ export const PopulationAnalysisConfiguration = createProperty("AWS::CleanRooms::IntermediateTable.PopulationAnalysisConfiguration", "aws");
7932
+ export const PopulationAnalysisSqlParameters = createProperty("AWS::CleanRooms::IntermediateTable.PopulationAnalysisSqlParameters", "aws");
7922
7933
  export const Port = createProperty("AWS::Lightsail::Instance.Port", "aws");
7923
7934
  export const Portal = createProperty("AWS::IoTSiteWise::AccessPolicy.Portal", "aws");
7924
7935
  export const PortalOptionsConfiguration = createProperty("AWS::SSO::Application.PortalOptionsConfiguration", "aws");
@@ -8347,8 +8347,7 @@
8347
8347
  "KmsKeyArn": "KmsKeyArn"
8348
8348
  },
8349
8349
  "createOnly": [
8350
- "KmsKeyId",
8351
- "ForceDelete"
8350
+ "KmsKeyId"
8352
8351
  ],
8353
8352
  "writeOnly": [
8354
8353
  "KmsKeyId",
@@ -49451,6 +49450,92 @@
49451
49450
  "kind": "property",
49452
49451
  "lexicon": "aws"
49453
49452
  },
49453
+ "IntermediateTable": {
49454
+ "resourceType": "AWS::CleanRooms::IntermediateTable",
49455
+ "kind": "resource",
49456
+ "lexicon": "aws",
49457
+ "attrs": {
49458
+ "IntermediateTableIdentifier": "IntermediateTableIdentifier",
49459
+ "Arn": "Arn",
49460
+ "MembershipArn": "MembershipArn",
49461
+ "CollaborationIdentifier": "CollaborationIdentifier",
49462
+ "CollaborationArn": "CollaborationArn",
49463
+ "Status": "Status"
49464
+ },
49465
+ "propertyConstraints": {
49466
+ "Arn": {
49467
+ "maxLength": 256
49468
+ },
49469
+ "MembershipArn": {
49470
+ "maxLength": 100
49471
+ },
49472
+ "CollaborationArn": {
49473
+ "maxLength": 100
49474
+ },
49475
+ "Name": {
49476
+ "pattern": "^(?!\\s*$)[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDBFF-\\uDC00\\uDFFF\\t]*$",
49477
+ "minLength": 1,
49478
+ "maxLength": 100
49479
+ },
49480
+ "Description": {
49481
+ "pattern": "^[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDBFF-\\uDC00\\uDFFF\\t\\r\\n]*$",
49482
+ "maxLength": 255
49483
+ },
49484
+ "KmsKeyArn": {
49485
+ "minLength": 4,
49486
+ "maxLength": 2048
49487
+ }
49488
+ },
49489
+ "createOnly": [
49490
+ "MembershipIdentifier",
49491
+ "Name",
49492
+ "PopulationAnalysisConfiguration"
49493
+ ],
49494
+ "primaryIdentifier": [
49495
+ "IntermediateTableIdentifier",
49496
+ "MembershipIdentifier"
49497
+ ],
49498
+ "tagging": {
49499
+ "taggable": true,
49500
+ "tagOnCreate": true,
49501
+ "tagUpdatable": true
49502
+ }
49503
+ },
49504
+ "IntermediateTableAnalysisRule": {
49505
+ "resourceType": "AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRule",
49506
+ "kind": "property",
49507
+ "lexicon": "aws"
49508
+ },
49509
+ "IntermediateTableAnalysisRulePolicy": {
49510
+ "resourceType": "AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRulePolicy",
49511
+ "kind": "property",
49512
+ "lexicon": "aws"
49513
+ },
49514
+ "IntermediateTable_IntermediateTableAnalysisRule": {
49515
+ "resourceType": "AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRule",
49516
+ "kind": "property",
49517
+ "lexicon": "aws"
49518
+ },
49519
+ "IntermediateTable_IntermediateTableAnalysisRulePolicy": {
49520
+ "resourceType": "AWS::CleanRooms::IntermediateTable.IntermediateTableAnalysisRulePolicy",
49521
+ "kind": "property",
49522
+ "lexicon": "aws"
49523
+ },
49524
+ "IntermediateTable_PopulationAnalysisConfiguration": {
49525
+ "resourceType": "AWS::CleanRooms::IntermediateTable.PopulationAnalysisConfiguration",
49526
+ "kind": "property",
49527
+ "lexicon": "aws"
49528
+ },
49529
+ "IntermediateTable_PopulationAnalysisSqlParameters": {
49530
+ "resourceType": "AWS::CleanRooms::IntermediateTable.PopulationAnalysisSqlParameters",
49531
+ "kind": "property",
49532
+ "lexicon": "aws"
49533
+ },
49534
+ "IntermediateTable_Tag": {
49535
+ "resourceType": "AWS::CleanRooms::IntermediateTable.Tag",
49536
+ "kind": "property",
49537
+ "lexicon": "aws"
49538
+ },
49454
49539
  "InternetGateway": {
49455
49540
  "resourceType": "AWS::EC2::InternetGateway",
49456
49541
  "kind": "resource",
@@ -54791,7 +54876,12 @@
54791
54876
  ],
54792
54877
  "primaryIdentifier": [
54793
54878
  "ListenerArn"
54794
- ]
54879
+ ],
54880
+ "tagging": {
54881
+ "taggable": true,
54882
+ "tagOnCreate": true,
54883
+ "tagUpdatable": true
54884
+ }
54795
54885
  },
54796
54886
  "ListenerAttribute": {
54797
54887
  "resourceType": "AWS::ElasticLoadBalancingV2::Listener.ListenerAttribute",
@@ -55022,6 +55112,11 @@
55022
55112
  "kind": "property",
55023
55113
  "lexicon": "aws"
55024
55114
  },
55115
+ "Listener_Tag": {
55116
+ "resourceType": "AWS::ElasticLoadBalancingV2::Listener.Tag",
55117
+ "kind": "property",
55118
+ "lexicon": "aws"
55119
+ },
55025
55120
  "Listener_TargetGroupStickinessConfig": {
55026
55121
  "resourceType": "AWS::ElasticLoadBalancingV2::Listener.TargetGroupStickinessConfig",
55027
55122
  "kind": "property",
@@ -71684,6 +71779,16 @@
71684
71779
  "kind": "property",
71685
71780
  "lexicon": "aws"
71686
71781
  },
71782
+ "PopulationAnalysisConfiguration": {
71783
+ "resourceType": "AWS::CleanRooms::IntermediateTable.PopulationAnalysisConfiguration",
71784
+ "kind": "property",
71785
+ "lexicon": "aws"
71786
+ },
71787
+ "PopulationAnalysisSqlParameters": {
71788
+ "resourceType": "AWS::CleanRooms::IntermediateTable.PopulationAnalysisSqlParameters",
71789
+ "kind": "property",
71790
+ "lexicon": "aws"
71791
+ },
71687
71792
  "Port": {
71688
71793
  "resourceType": "AWS::Lightsail::Instance.Port",
71689
71794
  "kind": "property",
@@ -41,14 +41,24 @@ describe("aws exportResources I/O glue (#160)", () => {
41
41
  expect(ir.resources.map((r) => r.logicalId)).toEqual(["MyBucket"]);
42
42
  });
43
43
 
44
- test("a non-zero exit throws with the stderr surfaced", async () => {
44
+ test("a not-yet-deployed stack returns empty live state (pre-first-apply), not an error", async () => {
45
45
  spawnMock.mockResolvedValue({
46
46
  stdout: "",
47
- stderr: "Stack with id ghost does not exist",
47
+ stderr: "An error occurred (ValidationError) …: Stack with id ghost does not exist",
48
48
  exitCode: 254,
49
49
  });
50
- await expect(awsPlugin.exportResources!({ environment: "ghost" })).rejects.toThrow(
51
- /Failed to get template for stack "ghost".*does not exist/,
50
+ const ir = await awsPlugin.exportResources!({ environment: "ghost" });
51
+ expect(ir.resources).toEqual([]);
52
+ });
53
+
54
+ test("a genuine failure (not 'does not exist') still throws with the stderr surfaced", async () => {
55
+ spawnMock.mockResolvedValue({
56
+ stdout: "",
57
+ stderr: "An error occurred (AccessDenied) …: not authorized",
58
+ exitCode: 254,
59
+ });
60
+ await expect(awsPlugin.exportResources!({ environment: "prod" })).rejects.toThrow(
61
+ /Failed to get template for stack "prod".*AccessDenied/,
52
62
  );
53
63
  });
54
64
 
@@ -1,7 +1,19 @@
1
1
  import { describe, test, expect } from "vitest";
2
- import { awsPlugin } from "./plugin";
2
+ import { awsPlugin, stackDoesNotExist } from "./plugin";
3
3
  import { isLexiconPlugin } from "@intentius/chant/lexicon";
4
4
 
5
+ describe("stackDoesNotExist (pre-first-apply live state)", () => {
6
+ test("true for the CloudFormation 'does not exist' error", () => {
7
+ expect(stackDoesNotExist(
8
+ "An error occurred (ValidationError) when calling the DescribeStackResources operation: Stack with id prod does not exist",
9
+ )).toBe(true);
10
+ });
11
+ test("false for other failures (auth, network) — those still throw", () => {
12
+ expect(stackDoesNotExist("An error occurred (InvalidClientTokenId) ...")).toBe(false);
13
+ expect(stackDoesNotExist("Could not connect to the endpoint URL")).toBe(false);
14
+ });
15
+ });
16
+
5
17
  describe("awsPlugin", () => {
6
18
  // -----------------------------------------------------------------------
7
19
  // Basic interface
package/src/plugin.ts CHANGED
@@ -15,6 +15,7 @@ import { join, dirname } from "path";
15
15
  import { fileURLToPath } from "url";
16
16
  import { awsSerializer } from "./serializer";
17
17
  import { FLOCI_EMULATOR } from "./op/activities/floci";
18
+ import { applyAwsEndpointArgv } from "./components/cloud-executor";
18
19
  import { awsReferenceCatalog } from "./reference-catalog";
19
20
  import { resolveTemplateAttrs } from "./live-attrs";
20
21
  import { CFParser } from "./import/parser";
@@ -23,6 +24,13 @@ import { parseStackTemplate } from "./import/live-export";
23
24
  import { awsCompletions } from "./lsp/completions";
24
25
  import { awsHover } from "./lsp/hover";
25
26
 
27
+ /** True when a CloudFormation CLI error means the stack simply isn't there yet
28
+ * (`ValidationError … does not exist`) — the pre-first-apply state, which live
29
+ * queries should treat as "nothing deployed", not a failure. Exported for testing. */
30
+ export function stackDoesNotExist(stderr: string): boolean {
31
+ return /does not exist/i.test(stderr);
32
+ }
33
+
26
34
  /**
27
35
  * AWS CloudFormation lexicon plugin.
28
36
  *
@@ -486,14 +494,23 @@ aws cloudformation wait stack-update-complete --stack-name my-app-prod`,
486
494
  // Try to parse the build output to detect stack name from Metadata or use convention
487
495
  const stackName = `${options.environment}`;
488
496
 
489
- // Describe stack resources
490
- const listResult = await rt.spawn([
497
+ // Describe stack resources. Inject --endpoint-url from AWS_ENDPOINT_URL so a
498
+ // local emulator (Floci) is observed instead of real AWS (#926) — behold
499
+ // serve --local relies on this for the overlay.
500
+ const listResult = await rt.spawn(applyAwsEndpointArgv([
491
501
  "aws", "cloudformation", "describe-stack-resources",
492
502
  "--stack-name", stackName,
493
503
  "--output", "json",
494
- ]);
504
+ ], process.env.AWS_ENDPOINT_URL));
495
505
 
496
506
  if (listResult.exitCode !== 0) {
507
+ // A stack that doesn't exist yet is the pre-first-apply state: nothing is
508
+ // deployed for this env, so there are no live resources (every declared
509
+ // resource is "pending") — not an error. Returning empty lets `lifecycle
510
+ // diff --live` / the overlay show pending nodes instead of failing hard.
511
+ if (stackDoesNotExist(listResult.stderr)) {
512
+ return resources;
513
+ }
497
514
  throw new Error(`Failed to describe stack "${stackName}": ${listResult.stderr}`);
498
515
  }
499
516
 
@@ -514,11 +531,11 @@ aws cloudformation wait stack-update-complete --stack-name my-app-prod`,
514
531
  }
515
532
 
516
533
  // Get stack outputs
517
- const describeResult = await rt.spawn([
534
+ const describeResult = await rt.spawn(applyAwsEndpointArgv([
518
535
  "aws", "cloudformation", "describe-stacks",
519
536
  "--stack-name", stackName,
520
537
  "--output", "json",
521
- ]);
538
+ ], process.env.AWS_ENDPOINT_URL));
522
539
 
523
540
  let stackOutputs: Record<string, string> = {};
524
541
  if (describeResult.exitCode === 0) {
@@ -569,13 +586,19 @@ aws cloudformation wait stack-update-complete --stack-name my-app-prod`,
569
586
  // Same stack-name convention as describeResources.
570
587
  const stackName = `${options.environment}`;
571
588
 
572
- const result = await rt.spawn([
589
+ const result = await rt.spawn(applyAwsEndpointArgv([
573
590
  "aws", "cloudformation", "get-template",
574
591
  "--stack-name", stackName,
575
592
  "--template-stage", "Original",
576
593
  "--output", "json",
577
- ]);
594
+ ], process.env.AWS_ENDPOINT_URL));
578
595
  if (result.exitCode !== 0) {
596
+ // Not deployed yet → no template to export (nothing live), not an error.
597
+ // Keeps `chant graph --live` edge enrichment and `import --from` quiet
598
+ // before the first apply.
599
+ if (stackDoesNotExist(result.stderr)) {
600
+ return parseStackTemplate({ Resources: {} }, options.selector, options.owned);
601
+ }
579
602
  throw new Error(`Failed to get template for stack "${stackName}": ${result.stderr}`);
580
603
  }
581
604