Skip to content

Commit cc40cc3

Browse files
committed
refactor: extract account match utils
1 parent 5a91058 commit cc40cc3

2 files changed

Lines changed: 64 additions & 49 deletions

File tree

lib/storage.ts

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ export {
4747
} from "./storage/identity.js";
4848
export type { NamedBackupSummary } from "./storage/named-backups.js";
4949

50+
import {
51+
collectDistinctIdentityValues,
52+
findNewestMatchingIndex,
53+
selectNewestAccount,
54+
} from "./storage/account-match-utils.js";
5055
import {
5156
getFlaggedAccountsPath as buildFlaggedAccountsPath,
5257
getLegacyFlaggedAccountsPath as buildLegacyFlaggedAccountsPath,
@@ -729,69 +734,22 @@ async function loadNormalizedStorageFromPath(
729734
});
730735
}
731736

732-
function selectNewestAccount<T extends AccountLike>(
733-
current: T | undefined,
734-
candidate: T,
735-
): T {
736-
if (!current) return candidate;
737-
const currentLastUsed = current.lastUsed || 0;
738-
const candidateLastUsed = candidate.lastUsed || 0;
739-
if (candidateLastUsed > currentLastUsed) return candidate;
740-
if (candidateLastUsed < currentLastUsed) return current;
741-
const currentAddedAt = current.addedAt || 0;
742-
const candidateAddedAt = candidate.addedAt || 0;
743-
return candidateAddedAt >= currentAddedAt ? candidate : current;
744-
}
745-
746-
function collectDistinctIdentityValues(
747-
values: Array<string | undefined>,
748-
): Set<string> {
749-
const distinct = new Set<string>();
750-
for (const value of values) {
751-
if (value) distinct.add(value);
752-
}
753-
return distinct;
754-
}
755-
756737
type AccountMatchOptions = {
757738
allowUniqueAccountIdFallbackWithoutEmail?: boolean;
758739
};
759740

760-
function findNewestMatchingIndex<T extends AccountLike>(
761-
accounts: readonly T[],
762-
predicate: (ref: AccountIdentityRef) => boolean,
763-
): number | undefined {
764-
let matchIndex: number | undefined;
765-
let match: T | undefined;
766-
for (let i = 0; i < accounts.length; i += 1) {
767-
const account = accounts[i];
768-
if (!account) continue;
769-
const ref = toAccountIdentityRef(account);
770-
if (!predicate(ref)) continue;
771-
if (matchIndex === undefined) {
772-
matchIndex = i;
773-
match = account;
774-
continue;
775-
}
776-
const newest = selectNewestAccount(match, account);
777-
if (newest === account) {
778-
matchIndex = i;
779-
match = account;
780-
}
781-
}
782-
return matchIndex;
783-
}
784-
785741
function findCompositeAccountMatchIndex<T extends AccountLike>(
786742
accounts: readonly T[],
787743
candidateRef: AccountIdentityRef,
788744
): number | undefined {
789745
if (!candidateRef.accountId || !candidateRef.emailKey) return undefined;
790746
return findNewestMatchingIndex(
791747
accounts,
748+
(account) => toAccountIdentityRef(account),
792749
(ref) =>
793750
ref.accountId === candidateRef.accountId &&
794751
ref.emailKey === candidateRef.emailKey,
752+
selectNewestAccount,
795753
);
796754
}
797755

@@ -819,7 +777,9 @@ function findSafeEmailMatchIndex<T extends AccountLike>(
819777

820778
return findNewestMatchingIndex(
821779
accounts,
780+
(account) => toAccountIdentityRef(account),
822781
(ref) => ref.emailKey === candidateRef.emailKey,
782+
selectNewestAccount,
823783
);
824784
}
825785

lib/storage/account-match-utils.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
type AccountLike = {
2+
addedAt?: number;
3+
lastUsed?: number;
4+
};
5+
6+
export function selectNewestAccount<T extends AccountLike>(
7+
current: T | undefined,
8+
candidate: T,
9+
): T {
10+
if (!current) return candidate;
11+
const currentLastUsed = current.lastUsed || 0;
12+
const candidateLastUsed = candidate.lastUsed || 0;
13+
if (candidateLastUsed > currentLastUsed) return candidate;
14+
if (candidateLastUsed < currentLastUsed) return current;
15+
const currentAddedAt = current.addedAt || 0;
16+
const candidateAddedAt = candidate.addedAt || 0;
17+
return candidateAddedAt >= currentAddedAt ? candidate : current;
18+
}
19+
20+
export function collectDistinctIdentityValues(
21+
values: Array<string | undefined>,
22+
): Set<string> {
23+
const distinct = new Set<string>();
24+
for (const value of values) {
25+
if (value) distinct.add(value);
26+
}
27+
return distinct;
28+
}
29+
30+
export function findNewestMatchingIndex<T, TRef>(
31+
accounts: readonly T[],
32+
toRef: (account: T) => TRef,
33+
predicate: (ref: TRef) => boolean,
34+
selectNewest: (current: T | undefined, candidate: T) => T,
35+
): number | undefined {
36+
let matchIndex: number | undefined;
37+
let match: T | undefined;
38+
for (let i = 0; i < accounts.length; i += 1) {
39+
const account = accounts[i];
40+
if (!account) continue;
41+
const ref = toRef(account);
42+
if (!predicate(ref)) continue;
43+
if (matchIndex === undefined) {
44+
matchIndex = i;
45+
match = account;
46+
continue;
47+
}
48+
const newest = selectNewest(match, account);
49+
if (newest === account) {
50+
matchIndex = i;
51+
match = account;
52+
}
53+
}
54+
return matchIndex;
55+
}

0 commit comments

Comments
 (0)