@thetypefounders/continue-with-google 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export type Options = {
8
8
  challengeTimeoutSeconds?: number;
9
9
  trialCount?: number;
10
10
  trialTimeoutSeconds?: number;
11
+ screenshot?: boolean;
11
12
  waitForSelector?: WaitForSelectorOptions;
12
13
  };
13
14
  export declare function authenticate(page: Page, email: string, password: string, secret: string, selector: string, options?: Options, logger?: Logger): Promise<ElementHandle | null>;
package/dist/index.js CHANGED
@@ -7,23 +7,32 @@ const DEFAULTS = {
7
7
  trialTimeoutSeconds: 2,
8
8
  };
9
9
  export async function authenticate(page, email, password, secret, selector, options = DEFAULTS, logger = console) {
10
+ const mergedOptions = { ...DEFAULTS, ...options };
10
11
  logger.info('Waiting to enter the email...');
12
+ if (mergedOptions.screenshot)
13
+ await takeScreenshotToDisplay(page);
11
14
  await page.waitForSelector('input[type=email]', { visible: true });
12
15
  logger.info('Entering the email...');
16
+ if (mergedOptions.screenshot)
17
+ await takeScreenshotToDisplay(page);
13
18
  await page.type('input[type=email]', email);
14
19
  await page.keyboard.press('Enter');
15
20
  logger.info('Waiting to enter the password...');
21
+ if (mergedOptions.screenshot)
22
+ await takeScreenshotToDisplay(page);
16
23
  await page.waitForSelector('input[type=password]', { visible: true });
17
24
  logger.info('Entering the password...');
25
+ if (mergedOptions.screenshot)
26
+ await takeScreenshotToDisplay(page);
18
27
  await page.type('input[type=password]', password);
19
28
  await page.keyboard.press('Enter');
20
- for (let attempt = 0, found = false; attempt < (options.challengeCount || DEFAULTS.challengeCount) && !found; attempt++) {
29
+ for (let attempt = 0, found = false; attempt < mergedOptions.challengeCount && !found; attempt++) {
21
30
  if (attempt > 0) {
22
31
  logger.warn(`Challenged on attempt ${attempt}. Entering the code...`);
32
+ if (mergedOptions.screenshot)
33
+ await takeScreenshotToDisplay(page);
23
34
  if (attempt > 1) {
24
- await setTimeout(1000 *
25
- (options.challengeTimeoutSeconds ||
26
- DEFAULTS.challengeTimeoutSeconds));
35
+ await setTimeout(1000 * mergedOptions.challengeTimeoutSeconds);
27
36
  }
28
37
  const code = generateToken(secret);
29
38
  await page.evaluate(() => {
@@ -32,10 +41,12 @@ export async function authenticate(page, email, password, secret, selector, opti
32
41
  });
33
42
  await page.type('input[type=tel]', code);
34
43
  await page.keyboard.press('Enter');
35
- await waitForTrial(page, options.trialCount || DEFAULTS.trialCount, options.trialTimeoutSeconds || DEFAULTS.trialTimeoutSeconds, logger);
44
+ await waitForTrial(page, mergedOptions.trialCount, mergedOptions.trialTimeoutSeconds, mergedOptions.screenshot, logger);
36
45
  }
37
46
  found = await Promise.any([
38
- page.waitForSelector(selector, options.waitForSelector).then(() => true),
47
+ page
48
+ .waitForSelector(selector, mergedOptions.waitForSelector)
49
+ .then(() => true),
39
50
  page
40
51
  .waitForSelector('input[type=tel]', { visible: true })
41
52
  .then(() => false),
@@ -43,22 +54,24 @@ export async function authenticate(page, email, password, secret, selector, opti
43
54
  }
44
55
  return await page.$(selector);
45
56
  }
46
- async function waitForTrial(page, attemptCount, attemptTimeoutSeconds, logger) {
57
+ async function waitForTrial(page, attemptCount, attemptTimeoutSeconds, screenshot, logger) {
47
58
  for (let attempt = -1, previous = undefined, current = undefined; attempt < attemptCount && (current === undefined || previous !== current); attempt++) {
48
59
  if (attempt > 0) {
49
60
  logger.warn(`Tried on attempt ${attempt}. Waiting to finish...`);
61
+ if (screenshot)
62
+ await takeScreenshotToDisplay(page);
50
63
  }
51
64
  if (attempt > -1) {
52
65
  await setTimeout(1000 * attemptTimeoutSeconds);
53
66
  }
54
- const future = await screenshot(page);
67
+ const future = await takeScreenshotToCompare(page);
55
68
  if (future) {
56
69
  previous = current;
57
70
  current = future;
58
71
  }
59
72
  }
60
73
  }
61
- async function screenshot(page) {
74
+ async function takeScreenshotToCompare(page) {
62
75
  try {
63
76
  const content = '* { caret-color: transparent !important; }';
64
77
  await page.addStyleTag({ content });
@@ -68,3 +81,8 @@ async function screenshot(page) {
68
81
  return undefined;
69
82
  }
70
83
  }
84
+ async function takeScreenshotToDisplay(page) {
85
+ await page.screenshot({
86
+ path: `continue-with-google-${Date.now()}.png`,
87
+ });
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thetypefounders/continue-with-google",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Ivan Ukhov <ivan.ukhov@gmail.com>",
6
6
  "description": "Two-factor authentication with Google via Puppeteer",
@@ -13,13 +13,13 @@
13
13
  "types": "dist/index.d.ts",
14
14
  "dependencies": {
15
15
  "authenticator": "^1.1.5",
16
- "puppeteer": "^24.1.1"
16
+ "puppeteer": "^24.9.0"
17
17
  },
18
18
  "devDependencies": {
19
- "@trivago/prettier-plugin-sort-imports": "^5.2.1",
19
+ "@trivago/prettier-plugin-sort-imports": "^5.2.2",
20
20
  "@types/authenticator": "^1.1.4",
21
- "prettier": "^3.4.2",
22
- "typescript": "^5.7.3"
21
+ "prettier": "^3.5.3",
22
+ "typescript": "^5.8.3"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "tsc",
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export type Options = {
12
12
  challengeTimeoutSeconds?: number;
13
13
  trialCount?: number;
14
14
  trialTimeoutSeconds?: number;
15
+ screenshot?: boolean;
15
16
  waitForSelector?: WaitForSelectorOptions;
16
17
  };
17
18
 
@@ -31,31 +32,36 @@ export async function authenticate(
31
32
  options: Options = DEFAULTS,
32
33
  logger: Logger = console
33
34
  ): Promise<ElementHandle | null> {
35
+ const mergedOptions = { ...DEFAULTS, ...options };
36
+
34
37
  logger.info('Waiting to enter the email...');
38
+ if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
35
39
  await page.waitForSelector('input[type=email]', { visible: true });
40
+
36
41
  logger.info('Entering the email...');
42
+ if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
37
43
  await page.type('input[type=email]', email);
38
44
  await page.keyboard.press('Enter');
39
45
 
40
46
  logger.info('Waiting to enter the password...');
47
+ if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
41
48
  await page.waitForSelector('input[type=password]', { visible: true });
49
+
42
50
  logger.info('Entering the password...');
51
+ if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
43
52
  await page.type('input[type=password]', password);
44
53
  await page.keyboard.press('Enter');
45
54
 
46
55
  for (
47
56
  let attempt = 0, found = false;
48
- attempt < (options.challengeCount || DEFAULTS.challengeCount!) && !found;
57
+ attempt < mergedOptions.challengeCount! && !found;
49
58
  attempt++
50
59
  ) {
51
60
  if (attempt > 0) {
52
61
  logger.warn(`Challenged on attempt ${attempt}. Entering the code...`);
62
+ if (mergedOptions.screenshot) await takeScreenshotToDisplay(page);
53
63
  if (attempt > 1) {
54
- await setTimeout(
55
- 1000 *
56
- (options.challengeTimeoutSeconds ||
57
- DEFAULTS.challengeTimeoutSeconds!)
58
- );
64
+ await setTimeout(1000 * mergedOptions.challengeTimeoutSeconds!);
59
65
  }
60
66
  const code = generateToken(secret);
61
67
  await page.evaluate(() => {
@@ -66,13 +72,16 @@ export async function authenticate(
66
72
  await page.keyboard.press('Enter');
67
73
  await waitForTrial(
68
74
  page,
69
- options.trialCount || DEFAULTS.trialCount!,
70
- options.trialTimeoutSeconds || DEFAULTS.trialTimeoutSeconds!,
75
+ mergedOptions.trialCount!,
76
+ mergedOptions.trialTimeoutSeconds!,
77
+ mergedOptions.screenshot,
71
78
  logger
72
79
  );
73
80
  }
74
81
  found = await Promise.any([
75
- page.waitForSelector(selector, options.waitForSelector).then(() => true),
82
+ page
83
+ .waitForSelector(selector, mergedOptions.waitForSelector)
84
+ .then(() => true),
76
85
  page
77
86
  .waitForSelector('input[type=tel]', { visible: true })
78
87
  .then(() => false),
@@ -86,6 +95,7 @@ async function waitForTrial(
86
95
  page: Page,
87
96
  attemptCount: number,
88
97
  attemptTimeoutSeconds: number,
98
+ screenshot: boolean | undefined,
89
99
  logger: Logger
90
100
  ): Promise<void> {
91
101
  for (
@@ -95,11 +105,12 @@ async function waitForTrial(
95
105
  ) {
96
106
  if (attempt > 0) {
97
107
  logger.warn(`Tried on attempt ${attempt}. Waiting to finish...`);
108
+ if (screenshot) await takeScreenshotToDisplay(page);
98
109
  }
99
110
  if (attempt > -1) {
100
111
  await setTimeout(1000 * attemptTimeoutSeconds);
101
112
  }
102
- const future = await screenshot(page);
113
+ const future = await takeScreenshotToCompare(page);
103
114
  if (future) {
104
115
  previous = current;
105
116
  current = future;
@@ -107,7 +118,9 @@ async function waitForTrial(
107
118
  }
108
119
  }
109
120
 
110
- async function screenshot(page: Page): Promise<string | undefined> {
121
+ async function takeScreenshotToCompare(
122
+ page: Page
123
+ ): Promise<string | undefined> {
111
124
  try {
112
125
  const content = '* { caret-color: transparent !important; }';
113
126
  await page.addStyleTag({ content });
@@ -116,3 +129,9 @@ async function screenshot(page: Page): Promise<string | undefined> {
116
129
  return undefined;
117
130
  }
118
131
  }
132
+
133
+ async function takeScreenshotToDisplay(page: Page): Promise<void> {
134
+ await page.screenshot({
135
+ path: `continue-with-google-${Date.now()}.png`,
136
+ });
137
+ }