@aws/nx-plugin 0.82.2 → 0.83.1

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.
Files changed (48) hide show
  1. package/LICENSE-THIRD-PARTY +34 -6
  2. package/package.json +1 -1
  3. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +82 -18
  4. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +53 -3
  5. package/src/py/mcp-server/generator.js +1 -0
  6. package/src/py/mcp-server/generator.js.map +1 -1
  7. package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +53 -3
  8. package/src/py/strands-agent/generator.js +1 -0
  9. package/src/py/strands-agent/generator.js.map +1 -1
  10. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +52 -8
  11. package/src/smithy/ts/api/generator.js +2 -0
  12. package/src/smithy/ts/api/generator.js.map +1 -1
  13. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +98 -18
  14. package/src/trpc/backend/generator.js +2 -0
  15. package/src/trpc/backend/generator.js.map +1 -1
  16. package/src/ts/lambda-function/generator.js +2 -0
  17. package/src/ts/lambda-function/generator.js.map +1 -1
  18. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +54 -3
  19. package/src/ts/mcp-server/generator.js +7 -1
  20. package/src/ts/mcp-server/generator.js.map +1 -1
  21. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +366 -20
  22. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +2 -2
  23. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -0
  24. package/src/ts/strands-agent/__snapshots__/generator.spec.ts.snap +52 -3
  25. package/src/ts/strands-agent/generator.js +3 -1
  26. package/src/ts/strands-agent/generator.js.map +1 -1
  27. package/src/utils/__snapshots__/shared-constructs.spec.ts.snap +157 -5
  28. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +14 -0
  29. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +37 -2
  30. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +1 -1
  31. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +4 -0
  32. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +4 -0
  33. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +4 -3
  34. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +4 -3
  35. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +11 -2
  36. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +11 -2
  37. package/src/utils/files/common/constructs/src/core/runtime-config.ts.template +157 -5
  38. package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +100 -0
  39. package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +19 -17
  40. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +12 -5
  41. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +2 -2
  42. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +2 -0
  43. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +10 -1
  44. package/src/utils/versions.d.ts +2 -0
  45. package/src/utils/versions.js +2 -0
  46. package/src/utils/versions.js.map +1 -1
  47. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +8 -3
  48. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +10 -1
@@ -33,6 +33,7 @@ import {
33
33
  Runtime,
34
34
  RuntimeProps,
35
35
  } from '@aws-cdk/aws-bedrock-agentcore-alpha';
36
+ import { RuntimeConfig } from '../../../core/runtime-config.js';
36
37
 
37
38
  export type SnapshotBedrockAgentProps = Omit<
38
39
  RuntimeProps,
@@ -46,6 +47,8 @@ export class SnapshotBedrockAgent extends Construct {
46
47
  constructor(scope: Construct, id: string, props?: SnapshotBedrockAgentProps) {
47
48
  super(scope, id);
48
49
 
50
+ const rc = RuntimeConfig.ensure(this);
51
+
49
52
  this.dockerImage = AgentRuntimeArtifact.fromAsset(
50
53
  path.dirname(url.fileURLToPath(new URL(import.meta.url))),
51
54
  {
@@ -65,6 +68,17 @@ export class SnapshotBedrockAgent extends Construct {
65
68
  protocolConfiguration: ProtocolType.HTTP,
66
69
  agentRuntimeArtifact: this.dockerImage,
67
70
  ...props,
71
+ environmentVariables: {
72
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
73
+ ...props?.environmentVariables,
74
+ },
75
+ });
76
+
77
+ rc.grantReadAppConfig(this.agentCoreRuntime);
78
+
79
+ rc.set('connection', 'agentRuntimes', {
80
+ ...rc.get('connection').agentRuntimes,
81
+ SnapshotBedrockAgent: this.agentCoreRuntime.agentRuntimeArn,
68
82
  });
69
83
  }
70
84
  }
@@ -111,6 +125,12 @@ variable "tags" {
111
125
  default = {}
112
126
  }
113
127
 
128
+ module "appconfig" {
129
+ source = "../../../core/runtime-config/appconfig"
130
+
131
+ application_name = "TerraformSnapshotAgent-runtime-config"
132
+ }
133
+
114
134
  module "agent_core_runtime" {
115
135
  source = "../../../core/agent-core"
116
136
  agent_runtime_name = "TerraformSnapshotAgent"
@@ -123,9 +143,33 @@ module "agent_core_runtime" {
123
143
  # }
124
144
  # }
125
145
 
126
- env = var.env
127
- additional_iam_policy_statements = var.additional_iam_policy_statements
146
+ env = merge({
147
+ RUNTIME_CONFIG_APP_ID = module.appconfig.application_id
148
+ }, var.env)
149
+ additional_iam_policy_statements = concat([
150
+ {
151
+ Effect = "Allow"
152
+ Action = [
153
+ "appconfig:StartConfigurationSession",
154
+ "appconfig:GetLatestConfiguration"
155
+ ]
156
+ Resource = ["\${module.appconfig.application_arn}/*"]
157
+ }
158
+ ], var.additional_iam_policy_statements)
128
159
  tags = var.tags
160
+
161
+ depends_on = [module.appconfig]
162
+ }
163
+
164
+ # Add agent runtime ARN to runtime config
165
+ module "add_agent_runtime_to_runtime_config" {
166
+ source = "../../../core/runtime-config/entry"
167
+
168
+ namespace = "connection"
169
+ key = "agentRuntimes"
170
+ value = { "TerraformSnapshotAgent" = module.agent_core_runtime.agent_core_runtime_arn }
171
+
172
+ depends_on = [module.agent_core_runtime]
129
173
  }
130
174
 
131
175
  output "agent_core_runtime_role_arn" {
@@ -137,6 +181,11 @@ output "agent_core_runtime_arn" {
137
181
  description = "ARN of the Bedrock Agent Core runtime"
138
182
  value = module.agent_core_runtime.agent_core_runtime_arn
139
183
  }
184
+
185
+ output "appconfig_application_id" {
186
+ description = "AppConfig Application ID for runtime config"
187
+ value = module.appconfig.application_id
188
+ }
140
189
  "
141
190
  `;
142
191
 
@@ -474,7 +523,7 @@ resource "aws_bedrockagentcore_agent_runtime" "agent_runtime" {
474
523
 
475
524
  depends_on = [
476
525
  null_resource.docker_publish,
477
- aws_iam_role_policy.agent_core_runtime_policy
526
+ aws_iam_role_policy_attachment.agent_core_policy
478
527
  ]
479
528
  }
480
529
 
@@ -83,9 +83,11 @@ const tsStrandsAgentGenerator = (tree, options) => tslib_1.__awaiter(void 0, voi
83
83
  'ws',
84
84
  'cors',
85
85
  '@aws-sdk/credential-providers',
86
+ '@aws-sdk/client-appconfigdata',
87
+ '@aws-lambda-powertools/parameters',
86
88
  'aws4fetch',
87
89
  '@modelcontextprotocol/sdk',
88
- ]), (0, versions_1.withVersions)(['tsx', '@types/ws', '@types/cors']));
90
+ ]), (0, versions_1.withVersions)(['tsx', '@types/ws', '@types/cors', '@types/node']));
89
91
  // NB: we assign the local dev port from 8081 as 8080 is used by vscode server, and so conflicts
90
92
  // for those working on remote dev envirionments. The deployed agent in agentcore still runs on
91
93
  // 8080 as per the agentcore contract.
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../packages/nx-plugin/src/ts/strands-agent/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../packages/nx-plugin/src/ts/strands-agent/generator.ts"],"names":[],"mappings":"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"}
@@ -87,13 +87,44 @@ export * from './runtime-config.js';
87
87
  `;
88
88
 
89
89
  exports[`shared-constructs utils > sharedConstructsGenerator > should generate shared constructs when they do not exist > packages/common/constructs/src/core/runtime-config.ts 1`] = `
90
- "import { Stack, Stage } from 'aws-cdk-lib';
91
- import { Construct } from 'constructs';
90
+ "import {
91
+ ArnFormat,
92
+ Aspects,
93
+ CfnOutput,
94
+ Lazy,
95
+ Names,
96
+ Stack,
97
+ Stage,
98
+ } from 'aws-cdk-lib';
99
+ import {
100
+ CfnApplication,
101
+ CfnConfigurationProfile,
102
+ CfnDeployment,
103
+ CfnDeploymentStrategy,
104
+ CfnEnvironment,
105
+ CfnHostedConfigurationVersion,
106
+ } from 'aws-cdk-lib/aws-appconfig';
107
+ import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam';
108
+ import { Construct, IConstruct } from 'constructs';
92
109
 
93
110
  const RuntimeConfigKey = '__RuntimeConfig__';
94
111
 
112
+ /**
113
+ * Stage-scoped singleton that collects runtime configuration from CDK constructs
114
+ * and delivers it to server-side (AppConfig) and client-side (S3) consumers.
115
+ *
116
+ * Configuration is organised into namespaces (mapped to AppConfig Configuration Profiles):
117
+ * \`\`\`ts
118
+ * const rc = RuntimeConfig.ensure(this);
119
+ * rc.set('connection', 'cognitoProps', { region: '...', userPoolId: '...' });
120
+ * rc.set('tables', 'users', { tableName: '...', arn: '...' });
121
+ * \`\`\`
122
+ */
95
123
  export class RuntimeConfig extends Construct {
96
- private readonly _runtimeConfig: any = {};
124
+ private readonly _namespaces = new Map<string, Record<string, any>>();
125
+ private _appConfigApplicationId?: string;
126
+ private _appConfigApplicationArn?: string;
127
+ private _aspectRegistered = false;
97
128
 
98
129
  static ensure(scope: Construct): RuntimeConfig {
99
130
  const parent = Stage.of(scope) ?? Stack.of(scope);
@@ -113,8 +144,129 @@ export class RuntimeConfig extends Construct {
113
144
  super(scope, id);
114
145
  }
115
146
 
116
- get config(): any {
117
- return this._runtimeConfig;
147
+ /** Sets a key in the given namespace. Creates the namespace if it doesn't exist. */
148
+ set(namespace: string, key: string, value: any): void {
149
+ let data = this._namespaces.get(namespace);
150
+ if (!data) {
151
+ data = {};
152
+ this._namespaces.set(namespace, data);
153
+ }
154
+ data[key] = value;
155
+ }
156
+
157
+ /** Returns the config data for a namespace. Creates it if it doesn't exist. */
158
+ get(namespace: string): Record<string, any> {
159
+ let data = this._namespaces.get(namespace);
160
+ if (!data) {
161
+ data = {};
162
+ this._namespaces.set(namespace, data);
163
+ }
164
+ return data;
165
+ }
166
+
167
+ /** Returns a lazy token resolving to the AppConfig Application ID. */
168
+ get appConfigApplicationId(): string {
169
+ this.ensureAspect();
170
+ return Lazy.string({
171
+ produce: () => {
172
+ if (!this._appConfigApplicationId) {
173
+ throw new Error(
174
+ 'RuntimeConfig AppConfig resources were not created.',
175
+ );
176
+ }
177
+ return this._appConfigApplicationId;
178
+ },
179
+ });
180
+ }
181
+
182
+ /** Grants a server-side consumer permission to read from AppConfig. */
183
+ grantReadAppConfig(grantee: IGrantable): Grant {
184
+ this.ensureAspect();
185
+ return Grant.addToPrincipal({
186
+ grantee,
187
+ actions: [
188
+ 'appconfig:StartConfigurationSession',
189
+ 'appconfig:GetLatestConfiguration',
190
+ ],
191
+ resourceArns: [
192
+ Lazy.string({ produce: () => this._appConfigApplicationArn }),
193
+ ],
194
+ });
195
+ }
196
+
197
+ private ensureAspect(): void {
198
+ if (this._aspectRegistered) return;
199
+ this._aspectRegistered = true;
200
+ let created = false;
201
+
202
+ Aspects.of(this.node.scope!).add({
203
+ visit: (node: IConstruct) => {
204
+ if (created || !(node instanceof Stack)) return;
205
+ created = true;
206
+
207
+ const stack = node;
208
+ const name = Names.uniqueResourceName(this, {
209
+ maxLength: 64,
210
+ separator: '-',
211
+ });
212
+
213
+ const app = new CfnApplication(stack, 'RcAppConfigApp', { name });
214
+ const strategy = new CfnDeploymentStrategy(
215
+ stack,
216
+ 'RcAppConfigStrategy',
217
+ {
218
+ name,
219
+ deploymentDurationInMinutes: 0,
220
+ growthFactor: 100,
221
+ replicateTo: 'NONE',
222
+ finalBakeTimeInMinutes: 0,
223
+ },
224
+ );
225
+ const env = new CfnEnvironment(stack, 'RcAppConfigEnv', {
226
+ applicationId: app.ref,
227
+ name: 'default',
228
+ });
229
+
230
+ for (const [ns, data] of this._namespaces.entries()) {
231
+ const profile = new CfnConfigurationProfile(
232
+ stack,
233
+ \`RcAppConfigProfile\${ns}\`,
234
+ {
235
+ applicationId: app.ref,
236
+ name: ns,
237
+ locationUri: 'hosted',
238
+ type: 'AWS.Freeform',
239
+ },
240
+ );
241
+ const version = new CfnHostedConfigurationVersion(
242
+ stack,
243
+ \`RcAppConfigVersion\${ns}\`,
244
+ {
245
+ applicationId: app.ref,
246
+ configurationProfileId: profile.ref,
247
+ contentType: 'application/json',
248
+ content: Lazy.string({ produce: () => stack.toJsonString(data) }),
249
+ },
250
+ );
251
+ new CfnDeployment(stack, \`RcAppConfigDeploy\${ns}\`, {
252
+ applicationId: app.ref,
253
+ environmentId: env.ref,
254
+ configurationProfileId: profile.ref,
255
+ configurationVersion: version.ref,
256
+ deploymentStrategyId: strategy.ref,
257
+ });
258
+ }
259
+
260
+ new CfnOutput(stack, 'RuntimeConfigApplicationId', { value: app.ref });
261
+ this._appConfigApplicationId = app.ref;
262
+ this._appConfigApplicationArn = stack.formatArn({
263
+ service: 'appconfig',
264
+ resource: 'application',
265
+ resourceName: \`\${app.ref}/*\`,
266
+ arnFormat: ArnFormat.SLASH_RESOURCE_NAME,
267
+ });
268
+ },
269
+ });
118
270
  }
119
271
  }
120
272
  "
@@ -10,6 +10,7 @@ import {
10
10
  Runtime,
11
11
  RuntimeProps,
12
12
  } from '@aws-cdk/aws-bedrock-agentcore-alpha';
13
+ import { RuntimeConfig } from '../../../core/runtime-config.js';
13
14
 
14
15
  export type <%- nameClassName %>Props = Omit<
15
16
  RuntimeProps,
@@ -23,6 +24,8 @@ export class <%- nameClassName %> extends Construct {
23
24
  constructor(scope: Construct, id: string, props?: <%- nameClassName %>Props) {
24
25
  super(scope, id);
25
26
 
27
+ const rc = RuntimeConfig.ensure(this);
28
+
26
29
  this.dockerImage = AgentRuntimeArtifact.fromAsset(
27
30
  path.dirname(url.fileURLToPath(new URL(import.meta.url))),
28
31
  {
@@ -42,6 +45,17 @@ export class <%- nameClassName %> extends Construct {
42
45
  protocolConfiguration: ProtocolType.<%- serverProtocol %>,
43
46
  agentRuntimeArtifact: this.dockerImage,
44
47
  ...props,
48
+ environmentVariables: {
49
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
50
+ ...props?.environmentVariables,
51
+ },
52
+ });
53
+
54
+ rc.grantReadAppConfig(this.agentCoreRuntime);
55
+
56
+ rc.set('connection', 'agentRuntimes', {
57
+ ...rc.get('connection').agentRuntimes,
58
+ <%- nameClassName %>: this.agentCoreRuntime.agentRuntimeArn,
45
59
  });
46
60
  }
47
61
  }
@@ -20,6 +20,12 @@ variable "tags" {
20
20
  default = {}
21
21
  }
22
22
 
23
+ module "appconfig" {
24
+ source = "../../../core/runtime-config/appconfig"
25
+
26
+ application_name = "<%= nameClassName %>-runtime-config"
27
+ }
28
+
23
29
  module "agent_core_runtime" {
24
30
  source = "../../../core/agent-core"
25
31
  agent_runtime_name = "<%= nameClassName %>"
@@ -32,9 +38,33 @@ module "agent_core_runtime" {
32
38
  # }
33
39
  # }
34
40
 
35
- env = var.env
36
- additional_iam_policy_statements = var.additional_iam_policy_statements
41
+ env = merge({
42
+ RUNTIME_CONFIG_APP_ID = module.appconfig.application_id
43
+ }, var.env)
44
+ additional_iam_policy_statements = concat([
45
+ {
46
+ Effect = "Allow"
47
+ Action = [
48
+ "appconfig:StartConfigurationSession",
49
+ "appconfig:GetLatestConfiguration"
50
+ ]
51
+ Resource = ["${module.appconfig.application_arn}/*"]
52
+ }
53
+ ], var.additional_iam_policy_statements)
37
54
  tags = var.tags
55
+
56
+ depends_on = [module.appconfig]
57
+ }
58
+
59
+ # Add agent runtime ARN to runtime config
60
+ module "add_agent_runtime_to_runtime_config" {
61
+ source = "../../../core/runtime-config/entry"
62
+
63
+ namespace = "connection"
64
+ key = "agentRuntimes"
65
+ value = { "<%= nameClassName %>" = module.agent_core_runtime.agent_core_runtime_arn }
66
+
67
+ depends_on = [module.agent_core_runtime]
38
68
  }
39
69
 
40
70
  output "agent_core_runtime_role_arn" {
@@ -46,3 +76,8 @@ output "agent_core_runtime_arn" {
46
76
  description = "ARN of the Bedrock Agent Core runtime"
47
77
  value = module.agent_core_runtime.agent_core_runtime_arn
48
78
  }
79
+
80
+ output "appconfig_application_id" {
81
+ description = "AppConfig Application ID for runtime config"
82
+ value = module.appconfig.application_id
83
+ }
@@ -331,7 +331,7 @@ resource "aws_bedrockagentcore_agent_runtime" "agent_runtime" {
331
331
 
332
332
  depends_on = [
333
333
  null_resource.docker_publish,
334
- aws_iam_role_policy.agent_core_runtime_policy
334
+ aws_iam_role_policy_attachment.agent_core_policy
335
335
  ]
336
336
  }
337
337
 
@@ -13,6 +13,7 @@ import {
13
13
  <%_ } _%>
14
14
  } from 'aws-cdk-lib/aws-lambda';
15
15
  import { Duration<%_ if (backend.type === 'fastapi') { _%>, Stack<%_ } _%> } from 'aws-cdk-lib';
16
+ import { RuntimeConfig } from '../../core/runtime-config.js';
16
17
  import {
17
18
  CorsHttpMethod,
18
19
  CfnApi,
@@ -99,6 +100,7 @@ export class <%= apiNameClassName %><
99
100
  * @returns An IntegrationBuilder with default lambda integrations
100
101
  */
101
102
  public static defaultIntegrations = (scope: Construct) => {
103
+ const rc = RuntimeConfig.ensure(scope);
102
104
  return IntegrationBuilder.http({
103
105
  pattern: '<%= backend.integrationPattern %>',
104
106
  <%_ if (backend.type === 'trpc') { _%>
@@ -137,6 +139,7 @@ export class <%= apiNameClassName %><
137
139
  <%_ } _%>
138
140
  environment: {
139
141
  AWS_CONNECTION_REUSE_ENABLED: '1',
142
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
140
143
  <%_ if (backend.type === 'fastapi') { _%>
141
144
  PORT: '8000',
142
145
  AWS_LWA_INVOKE_MODE: 'buffered',
@@ -148,6 +151,7 @@ export class <%= apiNameClassName %><
148
151
  <%_ const lambdaTarget = backend.type === 'fastapi' ? 'handler.currentVersion' : 'handler'; _%>
149
152
  <%_ const integrationOptions = backend.integrationPattern === 'shared' ? ', { scopePermissionToRoute: false }' : ''; _%>
150
153
  const handler = new Function(scope, `<%= apiNameClassName %>${op}Handler`, props);
154
+ rc.grantReadAppConfig(handler);
151
155
  <%_ if (backend.type === 'fastapi') { _%>
152
156
  const stack = Stack.of(scope);
153
157
  handler.addLayers(
@@ -12,6 +12,7 @@ import {
12
12
  SnapStartConf,
13
13
  <%_ } _%>
14
14
  } from 'aws-cdk-lib/aws-lambda';
15
+ import { RuntimeConfig } from '../../core/runtime-config.js';
15
16
  import {
16
17
  AuthorizationType,
17
18
  LambdaIntegration,
@@ -100,6 +101,7 @@ export class <%= apiNameClassName %><
100
101
  * @returns An IntegrationBuilder with default lambda integrations
101
102
  */
102
103
  public static defaultIntegrations = (scope: Construct) => {
104
+ const rc = RuntimeConfig.ensure(scope);
103
105
  return IntegrationBuilder.rest({
104
106
  pattern: '<%= backend.integrationPattern %>',
105
107
  <%_ if (backend.type === 'trpc') { _%>
@@ -138,6 +140,7 @@ export class <%= apiNameClassName %><
138
140
  <%_ } _%>
139
141
  environment: {
140
142
  AWS_CONNECTION_REUSE_ENABLED: '1',
143
+ RUNTIME_CONFIG_APP_ID: rc.appConfigApplicationId,
141
144
  <%_ if (backend.type === 'fastapi') { _%>
142
145
  PORT: '8000',
143
146
  AWS_LWA_INVOKE_MODE: 'response_stream',
@@ -162,6 +165,7 @@ export class <%= apiNameClassName %><
162
165
  : '';
163
166
  _%>
164
167
  const handler = new Function(scope, `<%= apiNameClassName %>${op}Handler`, props);
168
+ rc.grantReadAppConfig(handler);
165
169
  <%_ if (backend.type === 'fastapi') { _%>
166
170
  const stack = Stack.of(scope);
167
171
  handler.addLayers(
@@ -138,10 +138,11 @@ export class HttpApi<
138
138
  });
139
139
 
140
140
  // Register the API URL in runtime configuration for client discovery
141
- RuntimeConfig.ensure(this).config.apis = {
142
- ...RuntimeConfig.ensure(this).config.apis!,
141
+ const rc = RuntimeConfig.ensure(this);
142
+ rc.set('connection', 'apis', {
143
+ ...rc.get('connection').apis,
143
144
  [apiName]: this.defaultStage.url!,
144
- };
145
+ });
145
146
  }
146
147
 
147
148
  /**
@@ -125,10 +125,11 @@ export class RestApi<
125
125
  );
126
126
 
127
127
  // Register the API URL in runtime configuration for client discovery
128
- RuntimeConfig.ensure(this).config.apis = {
129
- ...RuntimeConfig.ensure(this).config.apis!,
128
+ const rc = RuntimeConfig.ensure(this);
129
+ rc.set('connection', 'apis', {
130
+ ...rc.get('connection').apis,
130
131
  [apiName]: this.api.url!,
131
- };
132
+ });
132
133
  }
133
134
 
134
135
  /**
@@ -297,12 +297,21 @@ resource "aws_apigatewayv2_route" "proxy_routes" {
297
297
  module "add_url_to_runtime_config" {
298
298
  source = "../../../core/runtime-config/entry"
299
299
 
300
- key_path = "apis.<%- apiNameClassName %>"
301
- value = module.http_api.stage_invoke_url
300
+ namespace = "connection"
301
+ key = "apis"
302
+ value = { "<%- apiNameClassName %>" = module.http_api.stage_invoke_url }
302
303
 
303
304
  depends_on = [module.http_api]
304
305
  }
305
306
 
307
+ module "appconfig" {
308
+ source = "../../../core/runtime-config/appconfig"
309
+
310
+ application_name = "<%- apiNameClassName %>-runtime-config"
311
+
312
+ depends_on = [module.add_url_to_runtime_config]
313
+ }
314
+
306
315
  # Lambda permission for API Gateway to invoke the function<% if (backend.type === 'fastapi') { %> via alias<% } %>
307
316
  resource "aws_lambda_permission" "api_gateway_invoke" {
308
317
  statement_id = "AllowExecutionFromAPIGateway"
@@ -454,12 +454,21 @@ resource "aws_lambda_permission" "api_gateway_invoke_streaming" {
454
454
  module "add_url_to_runtime_config" {
455
455
  source = "../../../core/runtime-config/entry"
456
456
 
457
- key_path = "apis.<%- apiNameClassName %>"
458
- value = aws_api_gateway_stage.api_stage.invoke_url
457
+ namespace = "connection"
458
+ key = "apis"
459
+ value = { "<%- apiNameClassName %>" = aws_api_gateway_stage.api_stage.invoke_url }
459
460
 
460
461
  depends_on = [aws_api_gateway_stage.api_stage]
461
462
  }
462
463
 
464
+ module "appconfig" {
465
+ source = "../../../core/runtime-config/appconfig"
466
+
467
+ application_name = "<%- apiNameClassName %>-runtime-config"
468
+
469
+ depends_on = [module.add_url_to_runtime_config]
470
+ }
471
+
463
472
  # Outputs
464
473
 
465
474
  # API Gateway Outputs (from core module)