1 import { useCallback } from 'react';
3 import { getCanonicalAddresses } from '@proton/shared/lib/api/addresses';
4 import { API_CODES, GET_CANONICAL_EMAILS_API_LIMIT } from '@proton/shared/lib/constants';
5 import type { GetCanonicalAddressesApiResponse } from '@proton/shared/lib/interfaces/calendar';
6 import type { GetCanonicalEmailsMap } from '@proton/shared/lib/interfaces/hooks/GetCanonicalEmailsMap';
7 import type { SimpleMap } from '@proton/shared/lib/interfaces/utils';
8 import chunk from '@proton/utils/chunk';
10 import useApi from './useApi';
11 import useCache from './useCache';
12 import { getIsRecordInvalid, getPromiseValue } from './useCachedModelResult';
14 const CACHE_KEY = 'CANONICAL_EMAILS';
16 export const useGetCanonicalEmailsMap = () => {
18 const cache = useCache();
20 const getCanonicalEmailsMap = useCallback(
21 async (emails: string[]): Promise<SimpleMap<string>> => {
23 return Promise.resolve({});
25 const encodedEmails = emails.map((email) => encodeURIComponent(email));
26 const batchedEmails = chunk(encodedEmails, GET_CANONICAL_EMAILS_API_LIMIT);
28 const maps = await Promise.all(
29 batchedEmails.map(async (batch) => {
30 const { Responses, Code } = await api<GetCanonicalAddressesApiResponse>(
31 getCanonicalAddresses(batch)
33 if (Code !== API_CODES.GLOBAL_SUCCESS) {
34 throw new Error('Canonicalize operation failed');
36 return Responses.reduce<SimpleMap<string>>((acc, { Email, Response: { CanonicalEmail } }) => {
37 acc[Email] = CanonicalEmail;
42 return maps.reduce<SimpleMap<string>>((acc, curr) => ({ ...acc, ...curr }), {});
47 return useCallback<GetCanonicalEmailsMap>(
48 (emails: string[]) => {
49 if (!cache.has(CACHE_KEY)) {
50 cache.set(CACHE_KEY, new Map());
52 const subCache = cache.get(CACHE_KEY);
53 const missing = emails.filter((email) => {
54 return getIsRecordInvalid(subCache.get(email));
56 const promise = getCanonicalEmailsMap(missing);
57 const miss = async (tzid: string) => {
58 const map = await promise;
62 emails.map(async (email) => {
63 const result = await getPromiseValue(subCache, email, miss);
66 result: result as string,
70 return result.reduce<SimpleMap<string>>((acc, { email, result }) => {
76 [cache, getCanonicalEmailsMap]