Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / recovery-kit / index.ts
blobc2003fa9bb76d3678f0d658c770bd1ecaac1f4c5
1 import type { Template } from '@pdfme/common';
2 import { generate } from '@pdfme/generator';
4 import chunk from '@proton/utils/chunk';
6 import interBold from './fonts/Inter-Bold.ttf';
7 import interRegular from './fonts/Inter-Regular.ttf';
8 import interSemiBold from './fonts/Inter-SemiBold.ttf';
9 import emptyTemplate from './templates/empty_template.pdf';
11 const getFonts = async () => {
12     const [interRegularData, interBoldData, interSemiBoldData] = await Promise.all(
13         [interRegular, interBold, interSemiBold].map((asset) => {
14             return fetch(asset).then((res) => res.arrayBuffer());
15         })
16     );
17     return [interRegularData, interBoldData, interSemiBoldData] as const;
20 const getPreload = (asset: string, as?: 'font') => {
21     const link = document.createElement('link');
22     link.setAttribute('rel', 'prefetch');
23     link.setAttribute('href', asset);
24     if (as) {
25         link.setAttribute('as', 'font');
26     }
27     return link;
30 export const getPrefetch = () => {
31     return [
32         getPreload(emptyTemplate),
33         ...[interRegular, interBold, interSemiBold].map((asset) => {
34             return getPreload(asset, 'font');
35         }),
36     ];
39 export const getFont = async () => {
40     const [interRegularData, interBoldData, interSemiBoldData] = await getFonts();
42     return {
43         interRegular: {
44             data: interRegularData,
45             fallback: true,
46         },
47         interBold: {
48             data: interBoldData,
49         },
50         interSemiBold: {
51             data: interSemiBoldData,
52         },
53     };
56 // Copy exported template here
57 const exportedTemplate = {
58     schemas: [
59         {
60             'email title': {
61                 type: 'text',
62                 position: {
63                     x: 60,
64                     y: 30,
65                 },
66                 width: 127.33,
67                 height: 6.73,
68                 alignment: 'right',
69                 fontSize: 16,
70                 characterSpacing: 0,
71                 lineHeight: 1,
72                 fontName: 'interBold',
73                 fontColor: '#6d4aff',
74             },
75             date: {
76                 type: 'text',
77                 position: {
78                     x: 60,
79                     y: 24,
80                 },
81                 width: 127.33,
82                 height: 5.68,
83                 alignment: 'right',
84                 fontSize: 12.5,
85                 characterSpacing: 0,
86                 lineHeight: 1,
87                 fontColor: '#706d6b',
88             },
89             'recovery phrase line 1': {
90                 type: 'text',
91                 position: {
92                     x: 35,
93                     y: 77,
94                 },
95                 width: 139,
96                 height: 6,
97                 lineHeight: 1,
98                 characterSpacing: 0.5,
99                 fontName: 'interBold',
100                 fontSize: 12,
101             },
102             'recovery phrase line 2': {
103                 type: 'text',
104                 position: {
105                     x: 35,
106                     y: 83,
107                 },
108                 width: 139,
109                 height: 6,
110                 lineHeight: 1,
111                 characterSpacing: 0.5,
112                 fontName: 'interBold',
113                 fontSize: 12,
114             },
115         },
116     ],
117     columns: ['email title', 'date', 'recovery phrase line 1', 'recovery phrase line 2'],
118     sampledata: [
119         {
120             'email title': 'eric.norbert@gmail.com',
121             date: 'Created on May 30, 2023',
122             'recovery phrase line 1': 'auto pottery age relief turkey face',
123             'recovery phrase line 2': 'tide useful near lottery alley wolf',
124         },
125     ],
128 export function getTemplate(basePdf: any): Template {
129     return {
130         basePdf,
131         ...(exportedTemplate as Omit<Template, 'basePdf'>),
132     };
135 type InputKeys = keyof (typeof exportedTemplate.schemas)[0];
136 type Input = { [key in InputKeys]: string };
138 export async function generatePDFKit({
139     emailAddress,
140     date,
141     recoveryPhrase,
142 }: {
143     emailAddress: string;
144     date: string;
145     recoveryPhrase: string;
146 }) {
147     const phraseArray = recoveryPhrase.split(' ').map((s) => s.trim());
148     const [phraseLine1 = [], phraseLine2 = []] = chunk(phraseArray, 6);
150     const inputs: Input[] = [
151         {
152             'recovery phrase line 1': phraseLine1.join(' '),
153             'recovery phrase line 2': phraseLine2.join(' '),
154             date,
155             'email title': emailAddress,
156         },
157     ];
159     const pdf = (await generate({
160         template: getTemplate(emptyTemplate),
161         inputs,
162         options: { font: await getFont() },
163     })) as Uint8Array<ArrayBuffer>; // TODO: Improve this type
165     return pdf;