@datacamp/learn-vm-scripts 1.2.0 → 1.2.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.
@@ -0,0 +1,19 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { ensureHttps } from './utils.js';
4
+ export async function loginToAWS({ url, username, page, password, }) {
5
+ const spinner = ora('Launching browser...').start();
6
+ spinner.succeed('Browser launched');
7
+ spinner.start('Navigating to AWS login page...');
8
+ await page.goto(ensureHttps(url));
9
+ await page.waitForSelector('input[name="username"]');
10
+ await page.type('input[name="username"]', username);
11
+ await page.waitForSelector('input[name="password"]');
12
+ await page.type('input[name="password"]', password);
13
+ await page.waitForSelector('input[id="remember_account_checkbox"]');
14
+ await page.click('input[id="remember_account_checkbox"]');
15
+ await page.waitForSelector('a[id="signin_button"]');
16
+ await page.click('a[id="signin_button"]');
17
+ spinner.succeed(chalk.green('Logged in to AWS successfully'));
18
+ }
19
+ //# sourceMappingURL=awsLogin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"awsLogin.js","sourceRoot":"","sources":["../src/awsLogin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,EAC/B,GAAG,EACH,QAAQ,EACR,IAAI,EACJ,QAAQ,GAMT;IACC,MAAM,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IACpD,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAEpC,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACjD,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAElC,MAAM,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAAC;IACrD,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,CAAC;IAEpD,MAAM,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAAC;IACrD,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,CAAC;IAEpD,MAAM,IAAI,CAAC,eAAe,CAAC,uCAAuC,CAAC,CAAC;IACpE,MAAM,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAE1D,MAAM,IAAI,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;IACpD,MAAM,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC1C,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,30 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { AZURE_LOGIN_URL, ensureHttps } from './utils.js';
4
+ export async function loginToAzure({ url, username, page, password, }) {
5
+ const spinner = ora('Launching browser...').start();
6
+ spinner.succeed('Browser launched');
7
+ spinner.start('Navigating to Azure login page...');
8
+ await page.goto(ensureHttps(url || AZURE_LOGIN_URL));
9
+ spinner.start('Entering email...');
10
+ await page.waitForNavigation();
11
+ await page.waitForSelector('[name="loginfmt"]');
12
+ await page.type('[name="loginfmt"]', username);
13
+ await page.click('[type="submit"]');
14
+ spinner.start('Entering password...');
15
+ await new Promise((resolve) => {
16
+ setTimeout(resolve, 1000);
17
+ });
18
+ await page.waitForSelector('input[type="password"]', { visible: true });
19
+ await page.type('input[type="password"]', password);
20
+ await page.keyboard.press('Enter');
21
+ await page.waitForNavigation();
22
+ await page.waitForSelector('[type="submit"]');
23
+ await page.click('[type="submit"]');
24
+ // continue after "Stay signed-in" modal:
25
+ await page.keyboard.press('Enter');
26
+ spinner.start('Logging in...');
27
+ await page.waitForNavigation();
28
+ spinner.succeed(chalk.green('Logged in to Azure successfully'));
29
+ }
30
+ //# sourceMappingURL=azureLogin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azureLogin.js","sourceRoot":"","sources":["../src/azureLogin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG1D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EACjC,GAAG,EACH,QAAQ,EACR,IAAI,EACJ,QAAQ,GAMT;IACC,MAAM,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IACpD,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAEpC,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACnD,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC,CAAC;IAErD,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACnC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAE/B,MAAM,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC;IAChD,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAEpC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAEtC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5B,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,eAAe,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,QAAQ,CAAC,CAAC;IACpD,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEnC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAE/B,MAAM,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;IAC9C,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAEpC,yCAAyC;IACzC,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEnC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC/B,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC/B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,12 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { ensureHttps } from './utils.js';
5
+ export async function loginToDatabricks({ url, page, }) {
6
+ const spinner = ora('Navigating to Databricks login page...').start();
7
+ await page.goto(ensureHttps(url));
8
+ await page.waitForSelector('.aad-btn');
9
+ await page.click('.aad-btn');
10
+ spinner.succeed(chalk.green('Logged in to Databricks successfully'));
11
+ }
12
+ //# sourceMappingURL=databricksLogin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"databricksLogin.js","sourceRoot":"","sources":["../src/databricksLogin.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,GAAG,EACH,IAAI,GAIL;IACC,MAAM,OAAO,GAAG,GAAG,CAAC,wCAAwC,CAAC,CAAC,KAAK,EAAE,CAAC;IAEtE,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAElC,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAEvC,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;AACvE,CAAC"}
package/dist/index.cjs CHANGED
@@ -92869,27 +92869,45 @@ async function loginToSnowflake({
92869
92869
  }) {
92870
92870
  log("Navigating to Snowflake login page...");
92871
92871
  await page.goto(ensureHttps(url));
92872
- await page.waitForSelector('input[name="username"]');
92873
- await setInput({
92874
- page,
92875
- querySelector: 'input[name="username"]',
92876
- value: username
92877
- });
92878
- await page.waitForSelector('input[name="password"]');
92879
- await setInput({
92880
- page,
92881
- querySelector: 'input[name="password"]',
92882
- value: password
92883
- });
92884
- const loginButton = 'div[data-test-id="loginButton"][aria-disabled="false"]';
92885
- await page.waitForSelector(loginButton);
92886
- await page.click(loginButton);
92872
+ await page.waitForSelector('input[autocomplete="username"]');
92873
+ const usernameField = await page.$('input[autocomplete="username"]');
92874
+ if (!usernameField) {
92875
+ throw new Error("Username field not found");
92876
+ }
92877
+ await usernameField.click({ clickCount: 3 });
92878
+ await page.keyboard.press("Backspace");
92879
+ await page.type('input[autocomplete="username"]', username);
92880
+ await page.waitForSelector('input[autocomplete="current-password"]');
92881
+ const passwordField = await page.$('input[autocomplete="current-password"]');
92882
+ if (!passwordField) {
92883
+ throw new Error("Password field not found");
92884
+ }
92885
+ await passwordField.click({ clickCount: 3 });
92886
+ await page.keyboard.press("Backspace");
92887
+ await page.type('input[autocomplete="current-password"]', password);
92888
+ await page.waitForSelector("button:not([disabled])");
92889
+ const buttons = await page.$$("button:not([disabled])");
92890
+ let signInButtonHandle;
92891
+ for (const btn of buttons) {
92892
+ const textContent = await page.evaluate(
92893
+ (el) => el.textContent?.trim(),
92894
+ btn
92895
+ );
92896
+ if (textContent === "Sign in") {
92897
+ signInButtonHandle = btn;
92898
+ break;
92899
+ }
92900
+ }
92901
+ if (!signInButtonHandle) {
92902
+ throw new Error("Could not find an enabled Sign in button on the page.");
92903
+ }
92904
+ await signInButtonHandle.click();
92887
92905
  log("Logged in to Snowflake!");
92888
92906
  log("Skipping optional parts of login");
92889
92907
  await page.waitForSelector('[data-testid="Dialog Footer"]');
92890
92908
  log("Dialog Footer found");
92891
- const buttons = await page.$$('div[role="button"]');
92892
- const notNowButton = await findAsync(buttons, async (button) => {
92909
+ const dialogButtons = await page.$$('div[role="button"]');
92910
+ const notNowButton = await findAsync(dialogButtons, async (button) => {
92893
92911
  const innerText = await page.evaluate((el) => el.innerText, button);
92894
92912
  return innerText === "Not now";
92895
92913
  });
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ import chalk from 'chalk';
2
+ import yargs from 'yargs';
3
+ import { loginToAWS } from './awsLogin.js';
4
+ import { loginToAzure } from './azureLogin.js';
5
+ import { loginToDatabricks } from './databricksLogin.js';
6
+ import { setupBrowser } from './setup.js';
7
+ const SUPPORTED_CLOUD_PROVIDERS = ['aws', 'azure', 'databricks'];
8
+ const argv = yargs(process.argv.slice(2))
9
+ .options({
10
+ cloudProvider: {
11
+ demandOption: true,
12
+ choices: SUPPORTED_CLOUD_PROVIDERS,
13
+ type: 'string',
14
+ },
15
+ password: { demandOption: true, type: 'string' },
16
+ url: { demandOption: false, type: 'string' },
17
+ username: { demandOption: true, type: 'string' },
18
+ })
19
+ .parseSync();
20
+ (async () => {
21
+ const { url, password, username, cloudProvider } = argv;
22
+ try {
23
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
+ const { browser, page } = await setupBrowser();
25
+ switch (cloudProvider) {
26
+ case 'azure':
27
+ await loginToAzure({ url, username, page, password });
28
+ break;
29
+ case 'aws':
30
+ if (!url) {
31
+ console.error(chalk.red('AWS URL is required'));
32
+ process.exit(1);
33
+ }
34
+ await loginToAWS({ url, username, page, password });
35
+ break;
36
+ case 'databricks':
37
+ if (!url) {
38
+ console.error(chalk.red('Databricks URL is required'));
39
+ process.exit(1);
40
+ }
41
+ await loginToAzure({
42
+ url: undefined,
43
+ username,
44
+ page,
45
+ password,
46
+ });
47
+ await loginToDatabricks({ url, page });
48
+ break;
49
+ default:
50
+ console.error(chalk.red('Unsupported cloud provider'));
51
+ }
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ }
54
+ catch (error) {
55
+ console.error(chalk.red(`Error: ${error.message}`));
56
+ }
57
+ await new Promise(() => { });
58
+ })();
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,yBAAyB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAU,CAAC;AAE1E,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACtC,OAAO,CAAC;IACP,aAAa,EAAE;QACb,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,yBAAyB;QAClC,IAAI,EAAE,QAAQ;KACf;IACD,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE;IAChD,GAAG,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC5C,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE;CACjD,CAAC;KACD,SAAS,EAAE,CAAC;AAEf,CAAC,KAAK,IAAI,EAAE;IACV,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAExD,IAAI,CAAC;QACH,6DAA6D;QAC7D,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;QAE/C,QAAQ,aAAa,EAAE,CAAC;YACtB,KAAK,OAAO;gBACV,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACtD,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;oBAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBACD,MAAM,UAAU,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACpD,MAAM;YACR,KAAK,YAAY;gBACf,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;oBACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;gBACD,MAAM,YAAY,CAAC;oBACjB,GAAG,EAAE,SAAS;oBACd,QAAQ;oBACR,IAAI;oBACJ,QAAQ;iBACT,CAAC,CAAC;gBACH,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvC,MAAM;YACR;gBACE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,8DAA8D;IAChE,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC,EAAE,CAAC"}
package/dist/setup.js ADDED
@@ -0,0 +1,21 @@
1
+ import dotenv from 'dotenv';
2
+ import puppeteer from 'puppeteer-core';
3
+ const envFile = process.env.NODE_ENV === 'production' ? '.env' : '.env.development';
4
+ dotenv.config({ path: envFile });
5
+ export async function setupBrowser() {
6
+ const browser = await puppeteer.launch({
7
+ args: ['--start-maximized', '--enable-save-password-bubble'],
8
+ executablePath: process.env.EXECUTABLE_PATH,
9
+ headless: false,
10
+ defaultViewport: null,
11
+ ignoreDefaultArgs: ['--enable-automation'],
12
+ userDataDir: process.env.USER_DATA_DIR,
13
+ });
14
+ const pages = await browser.pages();
15
+ if (pages[0] === undefined) {
16
+ const page = await browser.newPage();
17
+ return { browser, page };
18
+ }
19
+ return { browser, page: pages[0] };
20
+ }
21
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAEvC,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC;AACtE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC;QACrC,IAAI,EAAE,CAAC,mBAAmB,EAAE,+BAA+B,CAAC;QAC5D,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3C,QAAQ,EAAE,KAAK;QACf,eAAe,EAAE,IAAI;QACrB,iBAAiB,EAAE,CAAC,qBAAqB,CAAC;QAC1C,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;KACvC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IAEpC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACrC,CAAC"}
package/dist/utils.js ADDED
@@ -0,0 +1,9 @@
1
+ export const AZURE_LOGIN_URL = 'https://portal.azure.com/';
2
+ export function ensureHttps(url) {
3
+ const hasProtocol = /^(http|https):\/\//i.test(url);
4
+ if (!hasProtocol) {
5
+ return `https://${url}`;
6
+ }
7
+ return url;
8
+ }
9
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,2BAA2B,CAAC;AAE3D,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,WAAW,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datacamp/learn-vm-scripts",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
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",