Skip to content

Commit 8401324

Browse files
committed
feat: centralize ARN validation with isValidArn utility
1 parent 2424e85 commit 8401324

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed

src/cli/commands/add/validate.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
getSupportedModelProviders,
1616
matchEnumValue,
1717
} from '../../../schema';
18+
import { ARN_VALIDATION_MESSAGE, isValidArn } from '../shared/arn-utils';
1819
import { parseAndValidateLifecycleOptions } from '../shared/lifecycle-utils';
1920
import { validateVpcOptions } from '../shared/vpc-utils';
2021
import { validateJwtAuthorizerOptions } from './auth-options';
@@ -697,8 +698,8 @@ export function validateAddMemoryOptions(options: AddMemoryOptions): ValidationR
697698
return { valid: false, error: '--data-stream-arn is required when --delivery-type is set' };
698699
}
699700

700-
if (options.dataStreamArn && !options.dataStreamArn.startsWith('arn:')) {
701-
return { valid: false, error: '--data-stream-arn must be a valid ARN (starts with arn:)' };
701+
if (options.dataStreamArn && !isValidArn(options.dataStreamArn)) {
702+
return { valid: false, error: `--data-stream-arn: ${ARN_VALIDATION_MESSAGE}` };
702703
}
703704

704705
if (
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { isValidArn } from '../arn-utils';
2+
import { describe, expect, it } from 'vitest';
3+
4+
describe('isValidArn', () => {
5+
it('accepts a valid Kinesis stream ARN', () => {
6+
expect(isValidArn('arn:aws:kinesis:us-west-2:123456789012:stream/my-stream')).toBe(true);
7+
});
8+
9+
it('accepts a valid Lambda ARN', () => {
10+
expect(isValidArn('arn:aws:lambda:us-east-1:123456789012:function:my-func')).toBe(true);
11+
});
12+
13+
it('rejects a string that does not start with arn:', () => {
14+
expect(isValidArn('not-an-arn')).toBe(false);
15+
});
16+
17+
it('rejects an ARN with too few parts', () => {
18+
expect(isValidArn('arn:aws:kinesis:us-west-2:123456789012')).toBe(false);
19+
});
20+
21+
it('accepts an ARN with colons in the resource part', () => {
22+
expect(isValidArn('arn:aws:kinesis:us-west-2:123456789012:stream:extra:parts')).toBe(true);
23+
});
24+
25+
it('rejects an empty string', () => {
26+
expect(isValidArn('')).toBe(false);
27+
});
28+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const ARN_PART_COUNT = 6;
2+
const ARN_FORMAT = 'arn:partition:service:region:account:resource';
3+
4+
/**
5+
* Check whether a string looks like a valid ARN (starts with `arn:` and has at least 6 colon-separated parts).
6+
*/
7+
export function isValidArn(value: string): boolean {
8+
return value.startsWith('arn:') && value.split(':').length >= ARN_PART_COUNT;
9+
}
10+
11+
export const ARN_VALIDATION_MESSAGE = `Must be a valid ARN (${ARN_FORMAT})`;

src/cli/tui/screens/memory/AddMemoryScreen.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { MemoryStrategyType } from '../../../../schema';
22
import { AgentNameSchema, StreamContentLevelSchema } from '../../../../schema';
3+
import { ARN_VALIDATION_MESSAGE, isValidArn } from '../../../commands/shared/arn-utils';
34
import {
45
ConfirmReview,
56
Panel,
@@ -173,7 +174,7 @@ export function AddMemoryScreen({ onComplete, onExit, existingMemoryNames }: Add
173174
initialValue=""
174175
onSubmit={wizard.setStreamArn}
175176
onCancel={() => wizard.goBack()}
176-
customValidation={value => value.startsWith('arn:') || 'Must be a valid ARN (starts with arn:)'}
177+
customValidation={value => isValidArn(value) || ARN_VALIDATION_MESSAGE}
177178
/>
178179
)}
179180

0 commit comments

Comments
 (0)