1import * as cloudhsm from "@distilled.cloud/aws/cloudhsm-v2";
2import * as Effect from "effect/Effect";
3
4/**
5 * Convert CloudHSM's `[{ Key, Value }]` tag list into a plain record.
6 */
7export const toTagRecord = (
8 tags: ReadonlyArray<{ Key?: string; Value?: string }> | undefined,
9): Record<string, string> =>
10 Object.fromEntries(
11 (tags ?? [])
12 .filter(
13 (tag): tag is { Key: string; Value: string } =>
14 typeof tag.Key === "string" && typeof tag.Value === "string",
15 )
16 .map((tag) => [tag.Key, tag.Value]),
17 );
18
19/**
20 * Look up a single CloudHSM cluster by its cluster id. `describeClusters` is
21 * a filtered list — an unknown id simply yields an empty page, so a miss is
22 * `undefined` rather than a typed NotFound.
23 */
24export const findClusterById = Effect.fn(function* (clusterId: string) {
25 const response = yield* cloudhsm.describeClusters({
26 Filters: { clusterIds: [clusterId] },
27 });
28 return response.Clusters?.[0];
29});
30
31/** True when two string sets are equal ignoring order and duplicates. */
32export const sameStringSet = (
33 a: readonly string[] | undefined,
34 b: readonly string[] | undefined,
35): boolean => {
36 const left = [...new Set(a ?? [])].sort();
37 const right = [...new Set(b ?? [])].sort();
38 return left.length === right.length && left.every((v, i) => v === right[i]);
39};