Skip to content

Commit 75f6712

Browse files
committed
chore: ensure that error codes are string literals
We have concerns that future maintainers may accidentally pass message strings with interpolated variables where error codes are expected. To prevent that, introduce a new type `LiteralString`, with only possible way of obtaining one: ```ts const x: LiteralString = lit`this does not have variables`; ``` Any attempt to use variables inside this string throws an error at runtime, so code that does that can never execute. Then update all locations in which we expect error codes to take `LiteralString`s.
1 parent 09e3daf commit 75f6712

File tree

741 files changed

+4305
-3566
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

741 files changed

+4305
-3566
lines changed

packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.client-vpn-endpoint-client-route-enforcement.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { StackProps } from 'aws-cdk-lib';
22
import { App, RemovalPolicy, Stack, UnscopedValidationError } from 'aws-cdk-lib';
3+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
34
import * as acm from 'aws-cdk-lib/aws-certificatemanager';
45
import * as ec2 from 'aws-cdk-lib/aws-ec2';
56
import * as logs from 'aws-cdk-lib/aws-logs';
@@ -12,9 +13,9 @@ import type { Construct } from 'constructs';
1213
* to validate the domain identity.
1314
*/
1415
const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID;
15-
if (!hostedZoneId) throw new UnscopedValidationError('HostedZoneIdRequired', 'For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.');
16+
if (!hostedZoneId) throw new UnscopedValidationError(lit`HostedZoneIdRequired`, 'For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.');
1617
const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME;
17-
if (!hostedZoneName) throw new UnscopedValidationError('HostedZoneNameRequired', 'For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.');
18+
if (!hostedZoneName) throw new UnscopedValidationError(lit`HostedZoneNameRequired`, 'For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.');
1819

1920
interface TestStackProps extends StackProps {
2021
hostedZoneId: string;

packages/@aws-cdk-testing/framework-integ/test/aws-ec2/test/integ.client-vpn-endpoint-disconnect-on-session-timeout.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { StackProps } from 'aws-cdk-lib';
22
import { App, RemovalPolicy, Stack, UnscopedValidationError } from 'aws-cdk-lib';
3+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
34
import * as acm from 'aws-cdk-lib/aws-certificatemanager';
45
import * as ec2 from 'aws-cdk-lib/aws-ec2';
56
import * as logs from 'aws-cdk-lib/aws-logs';
@@ -12,9 +13,9 @@ import type { Construct } from 'constructs';
1213
* to validate the domain identity.
1314
*/
1415
const hostedZoneId = process.env.CDK_INTEG_HOSTED_ZONE_ID ?? process.env.HOSTED_ZONE_ID;
15-
if (!hostedZoneId) throw new UnscopedValidationError('HostedZoneIdRequired', 'For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.');
16+
if (!hostedZoneId) throw new UnscopedValidationError(lit`HostedZoneIdRequired`, 'For this test you must provide your own HostedZoneId as an env var "HOSTED_ZONE_ID". See framework-integ/README.md for details.');
1617
const hostedZoneName = process.env.CDK_INTEG_HOSTED_ZONE_NAME ?? process.env.HOSTED_ZONE_NAME;
17-
if (!hostedZoneName) throw new UnscopedValidationError('HostedZoneNameRequired', 'For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.');
18+
if (!hostedZoneName) throw new UnscopedValidationError(lit`HostedZoneNameRequired`, 'For this test you must provide your own HostedZoneName as an env var "HOSTED_ZONE_NAME". See framework-integ/README.md for details.');
1819

1920
interface TestStackProps extends StackProps {
2021
hostedZoneId: string;

packages/@aws-cdk-testing/framework-integ/test/core/test/tree-metadata.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Construct } from 'constructs';
77
import * as cxschema from 'aws-cdk-lib/cloud-assembly-schema';
88
import type { TreeInspector } from 'aws-cdk-lib';
99
import { App, AssumptionError, CfnParameter, CfnResource, Lazy, Stack } from 'aws-cdk-lib';
10+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
1011
import type { ForestFile, TreeFile } from 'aws-cdk-lib/core/lib/private/tree-metadata';
1112

1213
abstract class AbstractCfnResource extends CfnResource {
@@ -466,7 +467,7 @@ describe('tree metadata', () => {
466467
test('failing nodes', () => {
467468
class MyCfnResource extends CfnResource {
468469
public inspect(_: TreeInspector) {
469-
throw new AssumptionError('ForcedInspectError', 'Forcing an inspect error');
470+
throw new AssumptionError(lit`ForcedInspectError`, 'Forcing an inspect error');
470471
}
471472
}
472473

packages/@aws-cdk/aws-amplify-alpha/lib/app.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Branch } from './branch';
1212
import type { DomainOptions } from './domain';
1313
import { Domain } from './domain';
1414
import { renderEnvironmentVariables, isServerSideRendered } from './utils';
15+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
1516

1617
/**
1718
* An Amplify Console application
@@ -276,7 +277,7 @@ export class App extends Resource implements IApp, iam.IGrantable {
276277

277278
if (props.computeRole) {
278279
if (!isSSR) {
279-
throw new ValidationError('InvalidComputeRolePlatform', '`computeRole` can only be specified for `Platform.WEB_COMPUTE` or `Platform.WEB_DYNAMIC`.', this);
280+
throw new ValidationError(lit`InvalidComputeRolePlatform`, '`computeRole` can only be specified for `Platform.WEB_COMPUTE` or `Platform.WEB_DYNAMIC`.', this);
280281
}
281282
computedRole = props.computeRole;
282283
} else if (isSSR) {
@@ -611,15 +612,15 @@ export interface CustomResponseHeader {
611612
function renderCustomResponseHeaders(customHeaders: CustomResponseHeader[], scope: IConstruct): string {
612613
// Defensive assertion - should never happen due to call site validation
613614
if (customHeaders.length === 0) {
614-
throw new ValidationError('EmptyCustomResponseHeaders', 'renderCustomResponseHeaders called with empty array', scope);
615+
throw new ValidationError(lit`EmptyCustomResponseHeaders`, 'renderCustomResponseHeaders called with empty array', scope);
615616
}
616617

617618
const hasAppRoot = customHeaders[0].appRoot !== undefined;
618619
const yaml = [hasAppRoot ? 'applications:' : 'customHeaders:'];
619620

620621
for (const customHeader of customHeaders) {
621622
if ((customHeader.appRoot !== undefined) !== hasAppRoot) {
622-
throw new ValidationError('InconsistentAppRoot', 'appRoot must be either be present or absent across all custom response headers', scope);
623+
throw new ValidationError(lit`InconsistentAppRoot`, 'appRoot must be either be present or absent across all custom response headers', scope);
623624
}
624625

625626
const baseIndentation = ' '.repeat(hasAppRoot ? 6 : 2);

packages/@aws-cdk/aws-amplify-alpha/lib/branch.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { App } from './app';
2121
import type { BasicAuth } from './basic-auth';
2222
import { renderEnvironmentVariables, isServerSideRendered } from './utils';
2323
import { AssetDeploymentIsCompleteFunction, AssetDeploymentOnEventFunction } from '../custom-resource-handlers/dist/aws-amplify-alpha/asset-deployment-provider.generated';
24+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
2425

2526
/**
2627
* A branch
@@ -200,7 +201,7 @@ export class Branch extends Resource implements IBranch {
200201
const isSSR = isServerSideRendered(platform);
201202

202203
if (props.computeRole && !isSSR) {
203-
throw new ValidationError('InvalidBranchComputeRolePlatform', '`computeRole` can only be specified for branches of apps with `Platform.WEB_COMPUTE` or `Platform.WEB_DYNAMIC`.', this);
204+
throw new ValidationError(lit`InvalidBranchComputeRolePlatform`, '`computeRole` can only be specified for branches of apps with `Platform.WEB_COMPUTE` or `Platform.WEB_DYNAMIC`.', this);
204205
}
205206
}
206207

packages/@aws-cdk/aws-amplify-alpha/lib/domain.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable';
88
import type { Construct } from 'constructs';
99
import type { IApp } from './app';
1010
import type { IBranch } from './branch';
11+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
1112

1213
/**
1314
* Options to add a domain to an application
@@ -139,10 +140,10 @@ export class Domain extends Resource {
139140

140141
const domainName = props.domainName || id;
141142
if (!Token.isUnresolved(domainName) && domainName.length > 255) {
142-
throw new ValidationError('DomainNameTooLong', `Domain name must be 255 characters or less, got: ${domainName.length} characters.`, this);
143+
throw new ValidationError(lit`DomainNameTooLong`, `Domain name must be 255 characters or less, got: ${domainName.length} characters.`, this);
143144
}
144145
if (!Token.isUnresolved(domainName) && !/^(((?!-)[A-Za-z0-9-]{0,62}[A-Za-z0-9])\.)+((?!-)[A-Za-z0-9-]{1,62}[A-Za-z0-9])(\.)?$/.test(domainName)) {
145-
throw new ValidationError('InvalidDomainName', `Domain name must be a valid hostname, got: ${domainName}.`, this);
146+
throw new ValidationError(lit`InvalidDomainName`, `Domain name must be a valid hostname, got: ${domainName}.`, this);
146147
}
147148

148149
const domain = new CfnDomain(this, 'Resource', {

packages/@aws-cdk/aws-apprunner-alpha/lib/auto-scaling-configuration.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as cdk from 'aws-cdk-lib/core';
33
import { addConstructMetadata } from 'aws-cdk-lib/core/lib/metadata-resource';
44
import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable';
55
import type { Construct } from 'constructs';
6+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
67

78
/**
89
* Properties of the App Runner Auto Scaling Configuration.
@@ -123,7 +124,7 @@ export class AutoScalingConfiguration extends cdk.Resource implements IAutoScali
123124
const resourceParts = cdk.Fn.split('/', autoScalingConfigurationArn);
124125

125126
if (!resourceParts || resourceParts.length < 3) {
126-
throw new cdk.UnscopedValidationError('UnexpectedArnFormat', `Unexpected ARN format: ${autoScalingConfigurationArn}.`);
127+
throw new cdk.UnscopedValidationError(lit`UnexpectedArnFormat`, `Unexpected ARN format: ${autoScalingConfigurationArn}.`);
127128
}
128129

129130
const autoScalingConfigurationName = cdk.Fn.select(0, resourceParts);
@@ -181,13 +182,13 @@ export class AutoScalingConfiguration extends cdk.Resource implements IAutoScali
181182
if (props.autoScalingConfigurationName !== undefined && !cdk.Token.isUnresolved(props.autoScalingConfigurationName)) {
182183
if (props.autoScalingConfigurationName.length < 4 || props.autoScalingConfigurationName.length > 32) {
183184
throw new cdk.ValidationError(
184-
'InvalidAutoScalingConfigurationNameLength', `\`autoScalingConfigurationName\` must be between 4 and 32 characters, got: ${props.autoScalingConfigurationName.length} characters.`, this,
185+
lit`InvalidAutoScalingConfigurationNameLength`, `\`autoScalingConfigurationName\` must be between 4 and 32 characters, got: ${props.autoScalingConfigurationName.length} characters.`, this,
185186
);
186187
}
187188

188189
if (!/^[A-Za-z0-9][A-Za-z0-9\-_]*$/.test(props.autoScalingConfigurationName)) {
189190
throw new cdk.ValidationError(
190-
'InvalidAutoScalingConfigurationNameFormat', `\`autoScalingConfigurationName\` must start with an alphanumeric character and contain only alphanumeric characters, hyphens, or underscores after that, got: ${props.autoScalingConfigurationName}.`, this,
191+
lit`InvalidAutoScalingConfigurationNameFormat`, `\`autoScalingConfigurationName\` must start with an alphanumeric character and contain only alphanumeric characters, hyphens, or underscores after that, got: ${props.autoScalingConfigurationName}.`, this,
191192
);
192193
}
193194
}
@@ -197,19 +198,19 @@ export class AutoScalingConfiguration extends cdk.Resource implements IAutoScali
197198
const isMaxConcurrencyDefined = typeof props.maxConcurrency === 'number';
198199

199200
if (isMinSizeDefined && (props.minSize < 1 || props.minSize > 25)) {
200-
throw new cdk.ValidationError('InvalidMinSize', `minSize must be between 1 and 25, got ${props.minSize}.`, this);
201+
throw new cdk.ValidationError(lit`InvalidMinSize`, `minSize must be between 1 and 25, got ${props.minSize}.`, this);
201202
}
202203

203204
if (isMaxSizeDefined && (props.maxSize < 1 || props.maxSize > 25)) {
204-
throw new cdk.ValidationError('InvalidMaxSize', `maxSize must be between 1 and 25, got ${props.maxSize}.`, this);
205+
throw new cdk.ValidationError(lit`InvalidMaxSize`, `maxSize must be between 1 and 25, got ${props.maxSize}.`, this);
205206
}
206207

207208
if (isMinSizeDefined && isMaxSizeDefined && !(props.minSize < props.maxSize)) {
208-
throw new cdk.ValidationError('MaxSizeMustBeGreaterThanMinSize', 'maxSize must be greater than minSize.', this);
209+
throw new cdk.ValidationError(lit`MaxSizeMustBeGreaterThanMinSize`, 'maxSize must be greater than minSize.', this);
209210
}
210211

211212
if (isMaxConcurrencyDefined && (props.maxConcurrency < 1 || props.maxConcurrency > 200)) {
212-
throw new cdk.ValidationError('InvalidMaxConcurrency', `maxConcurrency must be between 1 and 200, got ${props.maxConcurrency}.`, this);
213+
throw new cdk.ValidationError(lit`InvalidMaxConcurrency`, `maxConcurrency must be between 1 and 200, got ${props.maxConcurrency}.`, this);
213214
}
214215
}
215216
}

packages/@aws-cdk/aws-apprunner-alpha/lib/observability-configuration.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as cdk from 'aws-cdk-lib/core';
33
import { addConstructMetadata } from 'aws-cdk-lib/core/lib/metadata-resource';
44
import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable';
55
import type { Construct } from 'constructs';
6+
import { lit } from 'aws-cdk-lib/core/lib/helpers-internal';
67

78
/**
89
* The implementation provider chosen for tracing App Runner services
@@ -109,7 +110,7 @@ export class ObservabilityConfiguration extends cdk.Resource implements IObserva
109110
const resourceParts = cdk.Fn.split('/', observabilityConfigurationArn);
110111

111112
if (!resourceParts || resourceParts.length < 3) {
112-
throw new cdk.UnscopedValidationError('UnexpectedArnFormat', `Unexpected ARN format: ${observabilityConfigurationArn}.`);
113+
throw new cdk.UnscopedValidationError(lit`UnexpectedArnFormat`, `Unexpected ARN format: ${observabilityConfigurationArn}.`);
113114
}
114115

115116
const observabilityConfigurationName = cdk.Fn.select(0, resourceParts);
@@ -152,14 +153,14 @@ export class ObservabilityConfiguration extends cdk.Resource implements IObserva
152153
if (props.observabilityConfigurationName !== undefined && !cdk.Token.isUnresolved(props.observabilityConfigurationName)) {
153154
if (props.observabilityConfigurationName.length < 4 || props.observabilityConfigurationName.length > 32) {
154155
throw new cdk.ValidationError(
155-
'InvalidObservabilityConfigurationNameLength',
156+
lit`InvalidObservabilityConfigurationNameLength`,
156157
`\`observabilityConfigurationName\` must be between 4 and 32 characters, got: ${props.observabilityConfigurationName.length} characters.`, this,
157158
);
158159
}
159160

160161
if (!/^[A-Za-z0-9][A-Za-z0-9\-_]*$/.test(props.observabilityConfigurationName)) {
161162
throw new cdk.ValidationError(
162-
'InvalidObservabilityConfigurationNameFormat',
163+
lit`InvalidObservabilityConfigurationNameFormat`,
163164
`\`observabilityConfigurationName\` must start with an alphanumeric character and contain only alphanumeric characters, hyphens, or underscores after that, got: ${props.observabilityConfigurationName}.`, this,
164165
);
165166
}

0 commit comments

Comments
 (0)