@@ -2,36 +2,30 @@ import fs from "node:fs";
22import path from "node:path" ;
33
44/**
5- * Reads the Firebase emulator debug log and extracts the password reset code
6- * @param email The email address for which the password reset was requested
7- * @returns The password reset code (oobCode) or null if not found
5+ * Reads the Firebase emulator debug log and extracts a specific code from the logs.
6+ * @param email The email address for which the code was requested.
7+ * @param logPattern A regular expression pattern to match the log entry.
8+ * @param extractCodeFn A function to extract the code from the relevant log line.
9+ * @returns The extracted code or null if not found.
810 */
9- async function getPasswordResetCodeFromLogs (
11+ async function getCodeFromLogs (
1012 email : string ,
13+ logPattern : RegExp ,
14+ extractCodeFn : ( line : string ) => string | null
1115) : Promise < string | null > {
1216 try {
1317 // Read the firebase-debug.log file
1418 const logPath = path . join ( process . cwd ( ) , "firebase-debug.log" ) ;
1519 const logContent = await fs . promises . readFile ( logPath , "utf8" ) ;
1620
17- // Find the most recent password reset link for the given email
21+ // Reverse lines to start with the most recent logs
1822 const lines = logContent . split ( "\n" ) . reverse ( ) ;
19- const resetLinkPattern = new RegExp (
20- `To reset the password for ${ email . replace (
21- "." ,
22- "\\." ,
23- ) } .*?http://127\\.0\\.0\\.1:9099.*`,
24- "i" ,
25- ) ;
2623
2724 for ( const line of lines ) {
28- const match = line . match ( resetLinkPattern ) ;
29- if ( match ) {
30- // Extract oobCode from the reset link
31- const url = match [ 0 ] . match ( / h t t p : \/ \/ 1 2 7 \. 0 \. 0 \. 1 : 9 0 9 9 \/ .* ?$ / ) ?. [ 0 ] ;
32- if ( url ) {
33- const oobCode = new URL ( url ) . searchParams . get ( "oobCode" ) ;
34- return oobCode ;
25+ if ( logPattern . test ( line ) ) {
26+ const code = extractCodeFn ( line ) ;
27+ if ( code ) {
28+ return code ;
3529 }
3630 }
3731 }
@@ -44,21 +38,25 @@ async function getPasswordResetCodeFromLogs(
4438}
4539
4640/**
47- * Waits for the password reset code to appear in the logs
48- * @param email The email address for which the password reset was requested
49- * @param timeout Maximum time to wait in milliseconds
50- * @param interval Interval between checks in milliseconds
51- * @returns The password reset code or null if timeout is reached
41+ * Waits for a specific code to appear in the logs.
42+ * @param email The email address for which the code was requested.
43+ * @param logPattern A regular expression pattern to match the log entry.
44+ * @param extractCodeFn A function to extract the code from the relevant log line.
45+ * @param timeout Maximum time to wait in milliseconds.
46+ * @param interval Interval between checks in milliseconds.
47+ * @returns The extracted code or null if timeout is reached.
5248 */
53- async function waitForPasswordResetCode (
49+ async function waitForCode (
5450 email : string ,
51+ logPattern : RegExp ,
52+ extractCodeFn : ( line : string ) => string | null ,
5553 timeout = 5000 ,
56- interval = 100 ,
54+ interval = 100
5755) : Promise < string | null > {
5856 const startTime = Date . now ( ) ;
5957
6058 while ( Date . now ( ) - startTime < timeout ) {
61- const code = await getPasswordResetCodeFromLogs ( email ) ;
59+ const code = await getCodeFromLogs ( email , logPattern , extractCodeFn ) ;
6260 if ( code ) {
6361 return code ;
6462 }
@@ -68,4 +66,36 @@ async function waitForPasswordResetCode(
6866 return null ;
6967}
7068
71- export { getPasswordResetCodeFromLogs , waitForPasswordResetCode } ;
69+ /**
70+ * Extracts the oobCode from a log line.
71+ * @param line The log line containing the oobCode link.
72+ * @returns The oobCode or null if not found.
73+ */
74+ function extractOobCode ( line : string ) : string | null {
75+ const url = line . match ( / h t t p : \/ \/ 1 2 7 \. 0 \. 0 \. 1 : 9 0 9 9 \/ e m u l a t o r \/ a c t i o n \? .* ?$ / ) ?. [ 0 ] ;
76+ return url ? new URL ( url ) . searchParams . get ( "oobCode" ) : null ;
77+ }
78+
79+ export async function waitForPasswordResetCode (
80+ email : string ,
81+ timeout = 5000 ,
82+ interval = 100
83+ ) : Promise < string | null > {
84+ const logPattern = new RegExp (
85+ `To reset the password for ${ email . replace ( "." , "\\." ) } .*?http://127\\.0\\.0\\.1:9099.*` ,
86+ "i"
87+ ) ;
88+ return waitForCode ( email , logPattern , extractOobCode , timeout , interval ) ;
89+ }
90+
91+ export async function waitForVerificationCode (
92+ email : string ,
93+ timeout = 5000 ,
94+ interval = 100
95+ ) : Promise < string | null > {
96+ const logPattern = new RegExp (
97+ `To verify the email address ${ email . replace ( "." , "\\." ) } .*?http://127\\.0\\.0\\.1:9099.*` ,
98+ "i"
99+ ) ;
100+ return waitForCode ( email , logPattern , extractOobCode , timeout , interval ) ;
101+ }
0 commit comments