Skip to content

Commit 642b086

Browse files
committed
use selectiveUnion
1 parent 38d95fc commit 642b086

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

packages/snaps-utils/src/snaps.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ describe('assertIsValidSnapId', () => {
5252
// TODO: Either fix this lint violation or explain why it's necessary to
5353
// ignore.
5454
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-base-to-string
55-
`Invalid snap ID: Expected the value to satisfy a union of \`intersection | Base Snap Id\`, but received: ${value}.`,
55+
`Invalid snap ID: Expected a string, but received: ${value}.`,
5656
);
5757
},
5858
);
5959

6060
it('throws for invalid snap id', () => {
6161
expect(() => assertIsValidSnapId('foo:bar')).toThrow(
62-
`Invalid snap ID: Expected the value to satisfy a union of \`intersection | Base Snap Id\`, but received: "foo:bar".`,
62+
`Invalid snap ID: Invalid or no prefix found for "foo:bar".`,
6363
);
6464
});
6565

@@ -75,22 +75,27 @@ describe('assertIsValidSnapId', () => {
7575
).not.toThrow();
7676
});
7777

78+
it('disallows whitespace at the beginning', () => {
79+
expect(() => assertIsValidSnapId(' local:http://localhost:8000')).toThrow(
80+
'Invalid snap ID: Invalid or no prefix found for " local:http://localhost:8000".',
81+
);
82+
});
83+
7884
it.each([
79-
' local:http://localhost:8000',
8085
'local:http://localhost:8000 ',
8186
'local:http://localhost:8000\n',
8287
'local:http://localhost:8000\r',
8388
])('disallows whitespace #%#', (value) => {
8489
expect(() => assertIsValidSnapId(value)).toThrow(
85-
/Invalid snap ID: Expected the value to satisfy a union of `intersection \| Base Snap Id`, but received: .+\./u,
90+
/Invalid snap ID: Expected a value of type `Base Snap Id`, but received: .+\./u,
8691
);
8792
});
8893

8994
it.each(['local:😎', 'local:␡'])(
9095
'disallows non-ASCII symbols #%#',
9196
(value) => {
9297
expect(() => assertIsValidSnapId(value)).toThrow(
93-
`Invalid snap ID: Expected the value to satisfy a union of \`intersection | Base Snap Id\`, but received: "${value}".`,
98+
`"Invalid snap ID: Expected a value of type \`Base Snap Id\`, but received: "${value}".`,
9499
);
95100
},
96101
);

packages/snaps-utils/src/snaps.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import type {
44
PermissionConstraint,
55
} from '@metamask/permission-controller';
66
import type { BlockReason } from '@metamask/snaps-registry';
7-
import type { SnapId, Snap as TruncatedSnap } from '@metamask/snaps-sdk';
7+
import {
8+
selectiveUnion,
9+
type SnapId,
10+
type Snap as TruncatedSnap,
11+
} from '@metamask/snaps-sdk';
812
import type { Struct } from '@metamask/superstruct';
913
import {
1014
is,
@@ -14,7 +18,6 @@ import {
1418
literal,
1519
refine,
1620
string,
17-
union,
1821
validate,
1922
} from '@metamask/superstruct';
2023
import type { Json } from '@metamask/utils';
@@ -286,7 +289,31 @@ export const HttpSnapIdStruct = intersection([
286289
}),
287290
]) as unknown as Struct<string, null>;
288291

289-
export const SnapIdStruct = union([NpmSnapIdStruct, LocalSnapIdStruct]);
292+
export const SnapIdPrefixStruct = refine(
293+
string(),
294+
'Valid Prefix Snap Id',
295+
(value) => {
296+
if (
297+
Object.values(SnapIdPrefixes).some((prefix) => value.startsWith(prefix))
298+
) {
299+
return true;
300+
}
301+
302+
return `Invalid or no prefix found for "${value}"`;
303+
},
304+
);
305+
306+
export const SnapIdStruct = selectiveUnion((value) => {
307+
if (typeof value === 'string' && value.startsWith(SnapIdPrefixes.npm)) {
308+
return NpmSnapIdStruct;
309+
}
310+
311+
if (typeof value === 'string' && value.startsWith(SnapIdPrefixes.local)) {
312+
return LocalSnapIdStruct;
313+
}
314+
315+
return SnapIdPrefixStruct;
316+
});
290317

291318
/**
292319
* Extracts the snap prefix from a snap ID.

0 commit comments

Comments
 (0)