@datacamp/learn-vm-scripts 1.8.8 → 1.10.0

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.
Files changed (2) hide show
  1. package/dist/index.cjs +83 -27
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -366649,13 +366649,47 @@ var setFullscreen = async (page, provider) => {
366649
366649
  log(`Failed to set fullscreen for ${provider}: ${error}`);
366650
366650
  }
366651
366651
  };
366652
+ var waitForStableBox = async (page, selector, stableMs = 200) => {
366653
+ await page.waitForSelector(selector, { visible: true });
366654
+ return page.waitForFunction(
366655
+ (sel, stable) => {
366656
+ const el = document.querySelector(sel);
366657
+ if (!el) return false;
366658
+ const now = performance.now();
366659
+ const rect = el.getBoundingClientRect();
366660
+ if (!window.__stableBox) {
366661
+ window.__stableBox = {};
366662
+ }
366663
+ const previous = window.__stableBox[sel];
366664
+ if (!previous) {
366665
+ window.__stableBox[sel] = { rect, t: now };
366666
+ return false;
366667
+ }
366668
+ const samePos = Math.abs(previous.rect.x - rect.x) < 0.5 && Math.abs(previous.rect.y - rect.y) < 0.5 && Math.abs(previous.rect.width - rect.width) < 0.5 && Math.abs(previous.rect.height - rect.height) < 0.5;
366669
+ if (!samePos) {
366670
+ window.__stableBox[sel] = { rect, t: now };
366671
+ return false;
366672
+ }
366673
+ return now - previous.t >= stable;
366674
+ },
366675
+ { timeout: 3e3 },
366676
+ selector,
366677
+ stableMs
366678
+ );
366679
+ };
366652
366680
 
366653
366681
  // src/setInput.ts
366654
- var setInput = ({
366682
+ var setInput = async ({
366655
366683
  page,
366656
366684
  querySelector,
366657
366685
  value
366658
366686
  }) => {
366687
+ try {
366688
+ await waitForStableBox(page, querySelector);
366689
+ } catch (error) {
366690
+ log(`Error waiting for stable box: ${error}`);
366691
+ }
366692
+ await page.type(querySelector, value);
366659
366693
  return page.evaluate(
366660
366694
  ({ querySelector: querySelector2, value: value2 }) => {
366661
366695
  document.querySelector(querySelector2).value = value2;
@@ -366697,11 +366731,9 @@ async function loginToAzure({
366697
366731
  log("Navigating to Azure login page...");
366698
366732
  await Promise.all([page.waitForNavigation(), page.goto(ensureHttps(url))]);
366699
366733
  log("Entering email...");
366700
- const usernameQuerySelector = '[name="loginfmt"]';
366701
- await page.waitForSelector(usernameQuerySelector);
366702
366734
  await setInput({
366703
366735
  page,
366704
- querySelector: usernameQuerySelector,
366736
+ querySelector: '[name="loginfmt"]',
366705
366737
  value: username
366706
366738
  });
366707
366739
  await Promise.all([
@@ -366710,11 +366742,9 @@ async function loginToAzure({
366710
366742
  ]);
366711
366743
  log("Email entered successfully");
366712
366744
  log("Entering password...");
366713
- const passwordQuerySelector = 'input[type="password"]';
366714
- await page.waitForSelector(passwordQuerySelector, { visible: true });
366715
366745
  await setInput({
366716
366746
  page,
366717
- querySelector: passwordQuerySelector,
366747
+ querySelector: 'input[type="password"]',
366718
366748
  value: password
366719
366749
  });
366720
366750
  await Promise.all([
@@ -366751,15 +366781,11 @@ async function loginToAWS({
366751
366781
  }) {
366752
366782
  log("Navigating to AWS login page...");
366753
366783
  await page.goto(ensureHttps(url));
366754
- await page.waitForSelector('input[name="username"]');
366755
- await page.type('input[name="username"]', username);
366756
366784
  await setInput({
366757
366785
  page,
366758
366786
  querySelector: 'input[name="username"]',
366759
366787
  value: username
366760
366788
  });
366761
- await page.waitForSelector('input[name="password"]');
366762
- await page.type('input[name="password"]', password);
366763
366789
  await setInput({
366764
366790
  page,
366765
366791
  querySelector: 'input[name="password"]',
@@ -366835,30 +366861,34 @@ var resetChrome = async ({ userDataDir }) => {
366835
366861
  };
366836
366862
 
366837
366863
  // src/snowflakeLogin.ts
366864
+ var USERNAME_SELECTOR = 'input[autocomplete="username"]';
366865
+ var PASSWORD_SELECTOR = 'input[autocomplete="current-password"]';
366866
+ var OTP_SELECTOR = 'input[autocomplete="one-time-code"]';
366838
366867
  async function loginToSnowflake({
366839
366868
  url,
366840
366869
  username,
366841
366870
  page,
366842
- password
366871
+ password,
366872
+ otp
366843
366873
  }) {
366844
366874
  log("Navigating to Snowflake login page...");
366845
366875
  await page.goto(ensureHttps(url));
366846
- await page.waitForSelector('input[autocomplete="username"]');
366847
- const usernameField = await page.$('input[autocomplete="username"]');
366876
+ await page.waitForSelector(USERNAME_SELECTOR);
366877
+ const usernameField = await page.$(USERNAME_SELECTOR);
366848
366878
  if (!usernameField) {
366849
366879
  throw new Error("Username field not found");
366850
366880
  }
366851
366881
  await usernameField.click({ clickCount: 3 });
366852
366882
  await page.keyboard.press("Backspace");
366853
- await page.type('input[autocomplete="username"]', username);
366854
- await page.waitForSelector('input[autocomplete="current-password"]');
366855
- const passwordField = await page.$('input[autocomplete="current-password"]');
366883
+ await page.type(USERNAME_SELECTOR, username);
366884
+ await page.waitForSelector(PASSWORD_SELECTOR);
366885
+ const passwordField = await page.$(PASSWORD_SELECTOR);
366856
366886
  if (!passwordField) {
366857
366887
  throw new Error("Password field not found");
366858
366888
  }
366859
366889
  await passwordField.click({ clickCount: 3 });
366860
366890
  await page.keyboard.press("Backspace");
366861
- await page.type('input[autocomplete="current-password"]', password);
366891
+ await page.type(PASSWORD_SELECTOR, password);
366862
366892
  await page.waitForSelector("button:not([disabled])");
366863
366893
  const buttons = await page.$$("button:not([disabled])");
366864
366894
  let signInButtonHandle;
@@ -366876,7 +366906,37 @@ async function loginToSnowflake({
366876
366906
  throw new Error("Could not find an enabled Sign in button on the page.");
366877
366907
  }
366878
366908
  await signInButtonHandle.click();
366879
- log("Logged in to Snowflake!");
366909
+ if (otp != null) {
366910
+ log("Handling Snowflake OTP challenge...");
366911
+ await page.waitForSelector(OTP_SELECTOR, {
366912
+ timeout: 15e3
366913
+ });
366914
+ const otpField = await page.$(OTP_SELECTOR);
366915
+ if (!otpField) {
366916
+ throw new Error("OTP field not found");
366917
+ }
366918
+ await otpField.click({ clickCount: 3 });
366919
+ await page.keyboard.press("Backspace");
366920
+ await page.type(OTP_SELECTOR, otp);
366921
+ const enabledButtons = await page.$$("button:not([disabled])");
366922
+ let continueButtonHandle;
366923
+ for (const btn of enabledButtons) {
366924
+ const textContent = await page.evaluate(
366925
+ (el) => el.textContent?.trim(),
366926
+ btn
366927
+ );
366928
+ if (textContent === "Continue") {
366929
+ continueButtonHandle = btn;
366930
+ break;
366931
+ }
366932
+ }
366933
+ if (!continueButtonHandle) {
366934
+ throw new Error("Could not find an enabled Continue button on the page.");
366935
+ }
366936
+ await continueButtonHandle.click();
366937
+ log("Snowflake OTP challenge completed");
366938
+ }
366939
+ log("Logged in to Snowflake");
366880
366940
  }
366881
366941
 
366882
366942
  // src/fabricLogin.ts
@@ -366889,7 +366949,6 @@ async function loginToFabric({
366889
366949
  log("Navigating to Fabric login page...");
366890
366950
  await page.goto(ensureHttps(url));
366891
366951
  log("Entering email...");
366892
- await page.waitForSelector('input[id="email"]');
366893
366952
  await setInput({
366894
366953
  page,
366895
366954
  querySelector: 'input[id="email"]',
@@ -366902,7 +366961,6 @@ async function loginToFabric({
366902
366961
  maxRetries: 10
366903
366962
  });
366904
366963
  log("Entering password...");
366905
- await page.waitForSelector('input[type="password"]');
366906
366964
  await setInput({
366907
366965
  page,
366908
366966
  querySelector: 'input[type="password"]',
@@ -366960,15 +367018,11 @@ async function loginToN8N({
366960
367018
  }) {
366961
367019
  log("Navigating to N8N login page...");
366962
367020
  await page.goto(ensureHttps(url));
366963
- await page.waitForSelector(usernameInputSelector);
366964
- await page.type(usernameInputSelector, username);
366965
367021
  await setInput({
366966
367022
  page,
366967
367023
  querySelector: usernameInputSelector,
366968
367024
  value: username
366969
367025
  });
366970
- await page.waitForSelector(passwordInputSelector);
366971
- await page.type(passwordInputSelector, password);
366972
367026
  await setInput({
366973
367027
  page,
366974
367028
  querySelector: passwordInputSelector,
@@ -366989,7 +367043,8 @@ var LoggedInProvidersSchema = objectType({
366989
367043
  cloudProvider: enumType(["aws", "azure", "snowflake", "n8n"]),
366990
367044
  username: stringType(),
366991
367045
  password: stringType(),
366992
- url: stringType()
367046
+ url: stringType(),
367047
+ otp: stringType().min(1).optional()
366993
367048
  });
366994
367049
  var Input = discriminatedUnionType("cloudProvider", [
366995
367050
  LoggedOutProvidersSchema,
@@ -367045,7 +367100,8 @@ var handleInput = async ({ line, page }) => {
367045
367100
  url: input.url,
367046
367101
  username: input.username,
367047
367102
  page,
367048
- password: input.password
367103
+ password: input.password,
367104
+ otp: input.otp
367049
367105
  });
367050
367106
  break;
367051
367107
  case "perplexity":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datacamp/learn-vm-scripts",
3
- "version": "1.8.8",
3
+ "version": "1.10.0",
4
4
  "repository": "git@github.com:datacamp-engineering/learn-vm-scripts.git",
5
5
  "description": "Scripts used by VMs in learn.",
6
6
  "main": "./dist/index.cjs",