@@ -2,36 +2,30 @@ import fs from "node:fs";
2
2
import path from "node:path" ;
3
3
4
4
/**
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.
8
10
*/
9
- async function getPasswordResetCodeFromLogs (
11
+ async function getCodeFromLogs (
10
12
email : string ,
13
+ logPattern : RegExp ,
14
+ extractCodeFn : ( line : string ) => string | null
11
15
) : Promise < string | null > {
12
16
try {
13
17
// Read the firebase-debug.log file
14
18
const logPath = path . join ( process . cwd ( ) , "firebase-debug.log" ) ;
15
19
const logContent = await fs . promises . readFile ( logPath , "utf8" ) ;
16
20
17
- // Find the most recent password reset link for the given email
21
+ // Reverse lines to start with the most recent logs
18
22
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
- ) ;
26
23
27
24
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 ;
35
29
}
36
30
}
37
31
}
@@ -44,21 +38,25 @@ async function getPasswordResetCodeFromLogs(
44
38
}
45
39
46
40
/**
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.
52
48
*/
53
- async function waitForPasswordResetCode (
49
+ async function waitForCode (
54
50
email : string ,
51
+ logPattern : RegExp ,
52
+ extractCodeFn : ( line : string ) => string | null ,
55
53
timeout = 5000 ,
56
- interval = 100 ,
54
+ interval = 100
57
55
) : Promise < string | null > {
58
56
const startTime = Date . now ( ) ;
59
57
60
58
while ( Date . now ( ) - startTime < timeout ) {
61
- const code = await getPasswordResetCodeFromLogs ( email ) ;
59
+ const code = await getCodeFromLogs ( email , logPattern , extractCodeFn ) ;
62
60
if ( code ) {
63
61
return code ;
64
62
}
@@ -68,4 +66,36 @@ async function waitForPasswordResetCode(
68
66
return null ;
69
67
}
70
68
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