1import * as memorydb from "@distilled.cloud/aws/memorydb";
2import * as Effect from "effect/Effect";
3
4/**
5 * Convert MemoryDB's `[{ Key, Value }]` tag list into a plain record,
6 * dropping any entry missing a key or value.
7 */
8export const toTagRecord = (
9 tags: Array<{ Key?: string; Value?: string }> | undefined,
10): Record<string, string> =>
11 Object.fromEntries(
12 (tags ?? [])
13 .filter(
14 (tag): tag is { Key: string; Value: string } =>
15 typeof tag.Key === "string" && typeof tag.Value === "string",
16 )
17 .map((tag) => [tag.Key, tag.Value]),
18 );
19
20/**
21 * Read the observed tags for a MemoryDB resource by ARN. A resource that has
22 * just been created (or is mid-transition) can transiently reject `listTags`;
23 * treat any failure as "no observed tags" so tag reconciliation still runs.
24 */
25export const readMemoryDbTags = Effect.fn(function* (arn: string) {
26 const response = yield* memorydb
27 .listTags({ ResourceArn: arn })
28 .pipe(Effect.catch(() => Effect.succeed(undefined)));
29 return toTagRecord(response?.TagList);
30});
31
32/** True when two string sets are equal ignoring order and duplicates. */
33export const sameStringSet = (
34 a: readonly string[] | undefined,
35 b: readonly string[] | undefined,
36): boolean => {
37 const left = [...new Set(a ?? [])].sort();
38 const right = [...new Set(b ?? [])].sort();
39 return left.length === right.length && left.every((v, i) => v === right[i]);
40};