FetchURL failing with “URL from user-controlled data”

I am using the below code which is properly sanitizing the url.

But still I keep getting Sonar Exception “Change this code to not construct the URL from user-controlled data.”

The line await fetch(sanitizedURL, options) is throwing Sonar exception.

What modification is needed in the below code to resolve the issue?

function sanitizeURL(inputURL) {
    try {
        const parsedURL = new URL(inputURL);
        const domainsList = [inputURL];

        if (!schemesList.includes(parsedURL.protocol)) {
            throw new Error('Invalid URL scheme');
        }

        if (!domainsList.some(domain => domain.includes(parsedURL))) {
            throw new Error("URL not in allowed list");
        }

        return parsedURL.toString();
    } catch (error) {
        console.log("Caught error: ", error);
        throw error;
    }
}

async function fetchWithCheck(url, options = {}, responseType = "json", errorMessage = null) {
    let data;

    try {
        const sanitizedURL = sanitizeURL(url);
        const response = await fetch(sanitizedURL, options);
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }
        switch (responseType) {
            case "json":
                data = await response.json();
                break;
            default:
                throw new Error(`Unsupported response type: ${responseType}`);
        }
        return data;
    } catch (error) {
        console.log(logMessage, error);

        const newError = new Error("problem fetching data");
        newError.cause = error;
        throw newError;
    }
}

How do I solve this 401 error whenever I run my firebase functions?

I dont have any software experience, I just started using ai to build something for myself in late November. I’m working with a react web app and I’m trying to deploy in production. I’m trying to run my firebase functions, but im getting this error:

Failed to load resource: the server responded with a status of 401 ()
LGChat.js:78 Full error object: FirebaseError: The function must be called while authenticated.

it is telling me i need to be authenticated to do it. however, i am fully authenticated. ive logged in, and firebase storage is pulling the documents associated with the account. so i know that other firebase services are working. ive deleted the account and remade it, so i know auth isnt broken. and the way callable functions work from my understanding is firebase does the token work on their end. so nothing i add to my code has influenced the the token being sent.

Every time i try to use the function, the token is sent, and then firebase denies it. I can’t imagine that the token is incorrect. Its the one firebase is generating and pulling itself from its own auth.

The llms have suggested mostly environment issues. I’ve checked every one they’ve suggested. I’ve also confirmed that I am fully signed into the google cloud sdk.

Does anyone have any experience that could point me in a new direction to solve this? it seems like such a dumb problem lol.

The error message is being called from in my functions/index.js and in a file called LGChat. Please let me know what else I can send to be helpful. I’m new to this so feel free to assume I don’t know what you are talking about. Also, sorry if I’ve structured this stackoverflow post incorrectly.

I’ve carefully gone through all of the potential environment issues.

I confirmed I’m logged into google cloud.

I’ve gone through the callables documentation to confirm everything is set up correctly.

I’ve confirmed my gcloud secret, etc it all correct.

I’ve confirmed the other firebase services are working.

I’ve given all users have invoker access.

I clear my cache on every redeployment attempt.

What am I missing?

Thank you in advance for any help.

Screenshot of error messages

LGChat file:


  const processDocument = async () => {
    if (!selectedFile || isProcessing || isProcessed || !currentUser) return;

    setIsProcessing(true);
    setError(null);
    setProcessingStatus('Starting processing...');

    try {
      // Use the already initialized functions instance from above
      const processPdfDocument = httpsCallable(functions, 'processPdfDocument', {
        timeout: 540000
      });

      console.log('Processing document with auth:', {
        uid: currentUser?.uid,
        email: currentUser?.email
      });

      console.log('Document details being sent:', {
        fileId: selectedFile.id,
        fileName: selectedFile.name,
        fileUrl: selectedFile.url,
        userId: currentUser.uid
      });

      setProcessingStatus('Processing PDF...');
      console.log('Processing PDF...');
      const result = await processPdfDocument({
        fileId: selectedFile.id,
        fileName: selectedFile.name,
        fileUrl: selectedFile.url,
        userId: currentUser.uid
      });
      console.log('Processing PDF result:', result);

      if (result.data?.success) {
        setIsProcessed(true);
        setProcessingStatus(
          `Successfully processed ${result.data.pagesProcessed} pages`
        );
      } else {
        throw new Error(
          'Processing failed: ' + (result.data?.error || 'Unknown error')
        );
      }
    } catch (error) {
      console.error('Error processing document:', error);
      setError(error.message || 'Failed to process document.');
      setIsProcessed(false);
      setProcessingStatus('Processing failed');
    }
  };

functions/index.js:

// Process PDF
exports.processPdfDocument = onCall(
  {
    memory: "2GiB",
    timeoutSeconds: 540,
    cors: true,
    enforceAppCheck: false,
    secrets: [
      "OPENAI_API_KEY",
      "PINECONE_API_KEY",
      "PINECONE_INDEX_NAME",
      "PINECONE_HOST"
    ]
  }, 
  async (request, context) => {
    // Log the full context and request for debugging
    console.log("[processPdfDocument] Request data:", {
      auth: request.auth,
      rawRequest: request.rawRequest,
      data: request.data
    });

    console.log("[processPdfDocument] Context:", {
      auth: context.auth,
      rawRequest: context.rawRequest
    });

    // Check auth
    if (!request.auth) {
      console.error("[processPdfDocument] No auth context");
      throw new HttpsError(
        "unauthenticated",
        "The function must be called while authenticated."
      );
    }

    // Verify UID
    if (!request.auth.uid) {
      console.error("[processPdfDocument] No UID in auth context");
      throw new HttpsError(
        "unauthenticated",
        "Invalid authentication. Please sign in again."
      );
    }

    try {
      // Verify the token
      const decodedToken = await admin.auth().verifyIdToken(context.auth.token);
      console.log("[processPdfDocument] Token verified:", decodedToken.uid);

      console.log("[processPdfDocument] Auth context:", {
        hasAuth: Boolean(context.auth),
        uid: context.auth ? context.auth.uid : null,
        token: context.auth ? Boolean(context.auth.token) : false,
        app: Boolean(context.app)
      });

      if (!request.auth || !request.auth.uid) {
        console.error("[processPdfDocument] Authentication error: No valid auth context");
        throw new HttpsError(
          "unauthenticated",
          "The function must be called while authenticated."
        );
      }

      try {
        console.log("[processPdfDocument] Request data:", {
          ...request.data,
          auth: {uid: context.auth.uid}
        });

        const {fileId, fileName, path} = request.data;
        const uid = context.auth.uid;

        // Validate parameters with detailed logging
        const missingParams = [];
        if (!fileId) missingParams.push("fileId");
        if (!fileName) missingParams.push("fileName");
        if (!path) missingParams.push("path");

        if (missingParams.length > 0) {
          const errorMsg = `Missing required parameters: ${missingParams.join(", ")}`;
          console.error("[processPdfDocument] Parameter validation failed:", {
            received: {fileId, fileName, path},
            missing: missingParams
          });
          throw new HttpsError("invalid-argument", errorMsg);
        }

        // Validate config with error handling
        let config;
        try {
          config = getConfig();
          console.log("[processPdfDocument] Configuration validated successfully");
        } catch (configError) {
          console.error("[processPdfDocument] Configuration error:", configError);
          throw new HttpsError(
            "failed-precondition",
            `Configuration error: ${configError.message}`
          );
        }

        // Initialize storage and get file
        const storage = getStorage();
        const bucket = storage.bucket();
        const tempFilePath = `/tmp/${fileId}-${Date.now()}.pdf`;

        // Download file with detailed error handling
        try {
          console.log("[processPdfDocument] Attempting to download file:", {path, tempFilePath});
          await bucket.file(path).download({destination: tempFilePath});
          console.log("[processPdfDocument] File downloaded successfully");
        } catch (downloadError) {
          console.error("[processPdfDocument] Download error:", {
            error: downloadError,
            path,
            tempFilePath
          });
          throw new HttpsError(
            "internal",
            `Failed to download file: ${downloadError.message}`
          );
        }

        // Process PDF with error handling
        let pdfContent;
        try {
          const dataBuffer = await fs.readFile(tempFilePath);
          console.log("[processPdfDocument] File read successfully, size:", dataBuffer.length);
          
          pdfContent = await pdf(dataBuffer, {
            pageNumbers: true,
            normalizeWhitespace: true,
            disableCombineTextItems: false
          });
          console.log("[processPdfDocument] PDF parsed successfully, pages:", pdfContent.numpages);
        } catch (pdfError) {
          console.error("[processPdfDocument] PDF processing error:", pdfError);
          throw new HttpsError(
            "internal",
            `Failed to process PDF: ${pdfError.message}`
          );
        }

        // Create text chunks
        const splitter = new RecursiveCharacterTextSplitter({
          chunkSize: 1000,
          chunkOverlap: 200
        });

        let allDocs = [];
        try {
          const docs = await splitter.createDocuments(
            [pdfContent.text],
            [{
              pageNumber: 1,
              fileId,
              fileName,
              userId: uid
            }]
          );
          allDocs = docs;
          console.log("[processPdfDocument] Created chunks:", allDocs.length);
        } catch (splitError) {
          console.error("[processPdfDocument] Text splitting error:", splitError);
          throw new HttpsError(
            "internal",
            `Failed to split text: ${splitError.message}`
          );
        }

        // Initialize Pinecone with error handling
        let pineconeIndex;
        try {
          const pineconeOptions = {
            apiKey: config.pineconeApiKey
          };
          if (config.pineconeHost) {
            pineconeOptions.controllerHostUrl = config.pineconeHost;
          }
          const pinecone = new Pinecone(pineconeOptions);
          pineconeIndex = pinecone.index(config.pineconeIndexName);
          console.log("[processPdfDocument] Pinecone initialized successfully");
        } catch (pineconeError) {
          console.error("[processPdfDocument] Pinecone initialization error:", pineconeError);
          throw new HttpsError(
            "internal",
            `Failed to initialize Pinecone: ${pineconeError.message}`
          );
        }

        // Create and store embeddings
        try {
          const embeddings = new OpenAIEmbeddings({
            openAIApiKey: config.openaiApiKey,
            batchSize: 100
          });

          await PineconeStore.fromDocuments(allDocs, embeddings, {
            pineconeIndex,
            namespace: uid,
            maxConcurrency: 5
          });
          console.log("[processPdfDocument] Documents stored in Pinecone successfully");
        } catch (embeddingError) {
          console.error("[processPdfDocument] Embedding/storage error:", embeddingError);
          throw new HttpsError(
            "internal",
            `Failed to create/store embeddings: ${embeddingError.message}`
          );
        }

        // Cleanup temp files
        try {
          await fs.unlink(tempFilePath);
          console.log("[processPdfDocument] Cleaned up temporary file");
        } catch (cleanupError) {
          console.warn("[processPdfDocument] Cleanup warning:", cleanupError);
          // Don't throw on cleanup errors
        }

        return {
          success: true,
          chunksProcessed: allDocs.length,
          pagesProcessed: pdfContent.numpages || 1
        };

      } catch (error) {
        console.error("[processPdfDocument] Top-level error:", {
          message: error.message,
          code: error.code,
          stack: error.stack
        });
        
        if (error instanceof HttpsError) {
          throw error;
        }
        
        throw new HttpsError(
          "internal",
          `Processing failed: ${error.message}`
        );
      }
    } catch (error) {
      console.error("[processPdfDocument] Token verification failed:", error);
      throw new HttpsError(
        "unauthenticated",
        "Invalid authentication token. Please sign in again."
      );
    }
  }
);

How to detect mouse movement direction? [closed]

Currently use the following quote to detect mouse movement direction:

window.addEventListener("mousemove", function (e) {
    
    if (time > Date.now() - 100) return
    time = Date.now();
    
    var movementX = e.movementX;
    var movementY = e.movementY;
    if (movementX < 0) {
        // left
    } else if (movementX > 0) {
        // right
    } else if (movementY < 0) {
        // up
    } else if (movementY > 0) {
        // down
    }
});

But it stops working when one side of the screen is reached, in this case movementX or movementY are equal to zero and my conditions stop working. For ex., the cursor has reached the left side of the window. User tries to move cursor left, but I can not detect it – movementX is equal to 0.

I tried to cancel the default movement (e.preventDefault()) and to always keep the cursor in the center by sending another mouse movement event. But it doesn’t work.

What else should I consider?

Why does getInitialNamespaces() Returns Null or Undefined Value and How to Fix It?

I am working on my remix vite project and currently set up i18n for localization. Initially I have found out that no button component in my project works (I have even tried console.log statements but alas). I have read somewhere that it may be due to an error on somewhere else. I have tried resolving this problem for hours but nothing worked so I started to search for other errors. While I get no error on my IDE terminal, the site inspector throws this error:

entry.client.jsx:31 Error initializing i18next: TypeError: Cannot convert undefined or null to object
    at Function.values (<anonymous>)
    at getInitialNamespaces (remix-i18next_client.js?v=582c9657:5:27)
    at hydrate (entry.client.jsx:14:16)

Obviously this happens because getInitialNamespaces return a null or an undefined value. The question is how to prevent this. Nothing I did seems to work and I am on my wits end.

Here is the specific code block:

import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import i18n from "./i18n";
import i18next from "i18next";
import { I18nextProvider, initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import Backend from "i18next-http-backend";
import { getInitialNamespaces } from "remix-i18next/client";

async function hydrate() {
  try {
    const ns = getInitialNamespaces() || ['translation'];
    
    await i18next
      .use(initReactI18next)
      .use(LanguageDetector)
      .use(Backend)
      .init({
        ...i18n,
        ns,
        defaultNs: 'translation',
        backend: { loadPath: "/locales/{{lng}}/{{ns}}.json" },
        detection: {
          order: ["htmlTag"],
          caches: [],
        },
      });
  } catch (error) {
    console.error("Error initializing i18next:", error);
  }    

  startTransition(() => {
    hydrateRoot(
      document,
      <I18nextProvider i18n={i18next}>
        <StrictMode>
          <RemixBrowser />
        </StrictMode>
      </I18nextProvider>,
    );
  });
}

if (window.requestIdleCallback) {
  window.requestIdleCallback(hydrate);
} else {
  // Safari doesn't support requestIdleCallback
  // https://caniuse.com/requestidlecallback
  window.setTimeout(hydrate, 1);
}

I have tried just writing ns: "translation" but this doesn’t seem to work either. I also checked remix i18n docs but couldn’t find anything either they say to write ns: getInitialNamespaces(). The code initially wasn’t inside a try block but after throwing the error I found out that it exists the hydrate function that it is currently in thus, the try block is required.

The i18next.server.js:

import { resolve } from "node:path";
import { RemixI18Next } from "remix-i18next/server";
import i18n from "./i18n";

let i18next = new RemixI18Next({
  detection: {
    supportedLanguages: i18n.supportedLngs,
    fallbackLanguage: i18n.fallbackLng,
    order: ["path"],
  },
  i18next: {
    ...i18n,
    backend: {
      loadPath: resolve("./public/locales/{{lng}}/{{ns}}.json"),
    },
  },
});

export default i18next;

entry.server.jsx:

import { PassThrough } from "stream";
import { createReadableStreamFromReadable } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import { isbot } from "isbot";
import { renderToPipeableStream } from "react-dom/server";
import { createInstance } from "i18next";
import i18next from "./i18next.server";
import { I18nextProvider, initReactI18next } from "react-i18next";
import Backend from "i18next-fs-backend";
import i18n from "./i18n"; 
import { resolve } from "node:path";

const ABORT_DELAY = 5000;

export default async function handleRequest(
  request,
  responseStatusCode,
  responseHeaders,
  remixContext,
) {
  let callbackName = isbot(request.headers.get("user-agent"))
    ? "onAllReady"
    : "onShellReady";

  let instance = createInstance();
  let ns = i18next.getRouteNamespaces(remixContext);
  await instance
    .use(initReactI18next)
    .use(Backend)
    .init({
      ...i18n,
      lng: (() => {
        const pathSegments = new URL(request.url).pathname
          .split("/")
          .filter(Boolean);
        return pathSegments[0];
      })(),
      ns,
      backend: { loadPath: resolve("./public/locales/{{lng}}/{{ns}}.json") },
    });

  return new Promise((resolve, reject) => {
    let didError = false;

    let { pipe, abort } = renderToPipeableStream(
      <I18nextProvider i18n={instance}>
        <RemixServer context={remixContext} url={request.url} />
      </I18nextProvider>,
      {
        [callbackName]: () => {
          let body = new PassThrough();
          const stream = createReadableStreamFromReadable(body);
          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(stream, {
              headers: responseHeaders,
              status: didError ? 500 : responseStatusCode,
            }),
          );

          pipe(body);
        },
        onShellError(error) {
          reject(error);
        },
        onError(error) {
          didError = true;
          console.error(error);
        },
      },
    );

    setTimeout(abort, ABORT_DELAY);
  });
}

Also please note that I don’t even know if this is the reason that the buttons don’t work but this is my only lead so far.

Thank you kindy.

Rive is blocking touch events

I have tried wrapping rive with a view and adding the prop pointerEvents={"none"} still no effect.

<TouchableOpacity onPress={()=> console.log("Hello")}>
  <Rive ref={ref} {...riveProps} {...riveConfig} />
</TouchableOpacity>

How to create one clipboard script for two copy buttons?

I have two paragraphs of text, each has a “copy to clipboard” button, and each button has its own script. How can I combine these two button scripts into one?

HTML:

<p id="text1">Copy to clipboard 1</p>
<p id="text2">Copy to clipboard 2</p>

<div class="tooltip">
<button onclick="myFunction()" onmouseout="outFunc()">
  <span class="tooltiptext" id="myBtn">Copy to clipboard</span>
  Copy text
  </button>
</div>
<div class="tooltip">
<button onclick="myFunction_1()" onmouseout="outFunc()">
  <span class="tooltiptext" id="myBtn-1">Copy to clipboard</span>
  Copy text
  </button>
</div>

and JS:

<script>
function myFunction() {
  navigator.clipboard.writeText(document.querySelector("#text1").innerText);
  var tooltip = document.getElementById("myBtn");
  tooltip.innerHTML = "Copied";
}
function outFunc() {
  var tooltip = document.getElementById("myBtn");
  tooltip.innerHTML = "Copy to clipboard";
}
</script>
<script>
function myFunction_1() {
  navigator.clipboard.writeText(document.querySelector("#text2").innerText);
  var tooltip = document.getElementById("myBtn-1");
  tooltip.innerHTML = "Copied";
}
function outFunc() {
  var tooltip = document.getElementById("myBtn-1");
  tooltip.innerHTML = "Copy to clipboard";
}
</script>

Speed up Google Apps Script with slow Gmail message interactions

Gmail’s app script API call for getting a thread’s messages takes particularly long (timing captured below), so I’m looking for a way to asynchronously kick off each call in the page_count batch, and then wait for the results of all the .getMessages() calls at the end. Unfortunately, .getMessages() is not natively asynchronous, so how can I make this work?

for (var page_i = 0; page_i < unread_count; page_i += page_count) {
  Logger.log("Page count = " + page_i);
  var inbox_threads = GmailApp.getInboxThreads(page_i, page_count);
  // var inbox_threads = GmailApp.search('in:inbox', page_i, page_count);

  Logger.log("Got threads, getting messages...");
  for (var i = 0; i < inbox_threads.length; i++) {
    var message = inbox_threads[i].getMessages();
    var sender = message[0].getFrom(); 

    if (sender in cObj) {
      cObj[sender]++;
    } else {
      cObj[sender] = 1;
    }
  }
}

Execution log:

3:51:44 AM  Info    Page count = 0
3:51:45 AM  Info    Got threads, getting messages...
3:52:17 AM  Info    Page count = 250
3:52:17 AM  Info    Got threads, getting messages...
3:52:50 AM  Info    Page count = 500
3:52:51 AM  Info    Got threads, getting messages...
3:53:23 AM  Info    Page count = 750

How to Enable Safari Autofill for SMS OTP in Svelte Using BitsUI’s PinInput Component

I’m working on implementing an SMS OTP login in Svelte, similar to Auth0’s login flow. I’m using the PinInput component from BitsUI to handle the OTP input fields. My goal is to enable autofill for the OTP, particularly on iOS where autofill prompts appear after receiving an SMS with the code.

Here is my code:

<script lang="ts">
import { tick } from "svelte";
import { PinInput } from "bits-ui";

let pinInputRef: InstanceType<typeof PinInput.Root>;
let isPinVisible = $state(false);


async function handleSubmit(e: SubmitEvent) {
    e.preventDefault();
    if (!isPinVisible) {
        isPinVisible = true;
        await tick();
        // Find and focus the first PIN input after it becomes visible
        const firstInput = document.querySelector('[data-pin-input-input]') as HTMLInputElement;
        firstInput?.focus();
    }
}
</script>

<div class="flex flex-col justify-start items-center w-full p-6 gap-y-6">
    <form onsubmit={handleSubmit} class="w-full max-w-72 md:max-w-96 flex flex-col relative">
            <input
                type="tel"
                id="phone"
                name="phone"
                placeholder="(123) 456-7890"
                class="bg-white autofill-white text-xl outline-none text-center mb-6"
                autocomplete="tel-national"
                enterkeyhint="next"
                autofocus
            />

            <!-- PIN Input with fade-in animation -->
            <div class="transform transition-all duration-300 ease-out overflow-hidden {isPinVisible ? 'h-24 opacity-100 mb-6' : 'h-0 opacity-0'}">
                <PinInput.Root
                    bind:this={pinInputRef}
                    enterkeyhint="go"
                    autocomplete="one-time-code"
                    class="grid grid-cols-6 gap-2 w-full max-w-lg mx-auto text-lg font-semibold text-neutral-500"
                >
                    {#each Array(6) as _}
                        <PinInput.Input
                            class="aspect-square text-center bg-neutral-50 border-0 rounded-lg focus:ring-0 placeholder:text-neutral-300"
                            inputmode="numeric"
                        />
                    {/each}
                    <PinInput.HiddenInput autocomplete="one-time-code" />
                </PinInput.Root>
            </div>

            <!-- Button with slide-down animation -->
            <button
                type="submit"
                class="bg-neutral-500 text-white px-4 py-2 rounded-full transition-all duration-300 ease-out transform"
            >
                {isPinVisible ? 'Verify' : 'Continue'}
            </button>
    </form>
</div>

I can successfully focus the PIN input element to bring up iOS’s keyboard, but the OTP autofill prompt doesn’t recognize the input fields. I suspect this might be because the PinInput.HiddenInput element is actually handling the autofill, and since it’s hidden, iOS treats this as a security precaution.

How can I modify my code so that iOS recognizes the PinInput fields for OTP autofill? If the hidden input is causing the issue, is there a workaround to make autofill work while using BitsUI’s PinInput component?

How to check if html form submit was successful

I have an html form, and already did the validation, after which the form is submitted.
I want to check if the form was submit successfully, in terms of the internet connection. Because right now, it will say success, even if there is no connection to the internet, in which case i won’t receive the form. I saw a lot of other questions regarding this topic, however they are all about validation, which i already handled.

Here’s the code, in case it matters:

                <form name="kctform" action="http://nsa-us.com:5000/kfu" target="dummy" method="post" class="kct-form-javascript-link">
                    <div class="kform-ff">* Pflichtfelder</div>
                    <label for="name" class="name form-header-element kce">Ihr Name *</label>
                    <label for="name" class="name2 form-header-element bce">Vorname, Nachname *</label>
                    <input class="kform-input empty" name="name" id="name" type="text">
                    <label for="mail" class="mail form-header-element">E-Mail Addresse *</label>
                    <input class="kform-input" name="mail" id="mail" type="email">
                    <label for="phone" class="phone form-header-element bce">Telefon</label>
                    <input class="kform-input bce" name="phone" id="phone" type="text">
                    <label for="address" class="address form-header-element bce">Straße / Nummer *</label>
                    <input class="kform-input bce" name="address" id="address" type="text">
                    <label for="cityCode" class="cityCode form-header-element bce">Postleitzahl *</label>
                    <input class="kform-input bce" name="cityCode" id="cityCode" type="text">
                    <label for="about" class="about form-header-element kce">Betreff *</label>
                    <input class="kform-input kce" name="about" id="about" type="text">
                    <label for="main" class="main form-header-element kce">Ihre Nachricht *</label>
                    <label for="main" class="main2 form-header-element bce">Bewerbung *</label>
                    <textarea class="kform-input" name="main" id="main" type="text"></textarea>
                    <div for="datc" class="dataprot-checkbox-t">Ich stimme zu, dass meine Angaben aus dem Kontaktformular zur Beantwortung meiner Anfrage erhoben und verarbeitet werden. Sie können Ihre Einwilligung jederzeit für die Zukunft per E-Mail an [email protected] widerrufen. Detaillierte Informationen zum Umgang mit Nutzerdaten finden Sie in unserer <a href="../datenschutzerklärung">Datenschutzerklärung</a>.</div>
                    <div class="kform-c-div"><input class="kform-input kform-checkbox" name="datc" id="datc" type="checkbox">
                    <div class="checkDiv"><label for="datc" class="datc kform-checkbox-text">Ja, ich stimme zu. *</label><div class='echeckbox'>Checkbox ist ein Pflichtfeld!</div></div></div>
                    <button class="submitButton" type="submit">Senden</button>
                </form>
                <iframe name="dummy" id="dummy" style="display: none;"></iframe>
            </div>
    const kctForm = document.querySelector('.kct-form-javascript-link');
    kctForm.addEventListener('submit', e => {
        e.preventDefault();
        const checkbox = document.querySelector('.kform-input#datc');
        let sent = false;
        let send = true;
        if (f === 'ktf') {
            const name = kctForm.elements[0].value;
            const mail = kctForm.elements[1].value;
            const about = kctForm.elements[5].value;
            const main = kctForm.elements[6].value;
            const nameC = document.querySelector('.name');
            const mailC = document.querySelector('.mail');
            const aboutC = document.querySelector('.about');
            const mainC = document.querySelector('.main');
            let formElement = [name, mail, about, main];
            let formElementC = [nameC,mailC,aboutC,mainC];
            const varIsEmpty = str => !str.replace(/s/g, '').length
            for (let i = 0; i < formElement.length; i++) {
                let formE = formElement[i];
                let formC = formElementC[i];
                if (varIsEmpty(formE)) {
                    formC.classList.add('empty');
                    send = false;
                }
                else {
                    formC.classList.remove('empty');
                };
            };
        }
        else if (f === 'bef') {
            const name = kctForm.elements[0].value;
            const mail = kctForm.elements[1].value;
            //const phone = kctForm.elements[2].value;
            const address = kctForm.elements[3].value;
            const cityCode = kctForm.elements[4].value;
            const main = kctForm.elements[6].value;
            const nameC = document.querySelector('.name2');
            const mailC = document.querySelector('.mail');
            //const phoneC = document.querySelector('.phone');
            const addressC = document.querySelector('.address');
            const cityCodeC = document.querySelector('.cityCode');
            const mainC = document.querySelector('.main2');
            let formElement = [name, mail, /*phone, */address, cityCode, main];
            //let formElementT = ['name', 'mail', /*'phone',*/'address', 'cityCode', 'main'];
            let formElementC = [nameC,mailC,/*phoneC,*/addressC,cityCodeC,mainC];
            const varIsEmpty = str => !str.replace(/s/g, '').length;
            for (let i = 0; i < formElement.length; i++) {
                let formE = formElement[i];
                let formC = formElementC[i];
                if (varIsEmpty(formE)) {
                    formC.classList.add('empty');
                    send = false;
                }
                else {
                    formC.classList.remove('empty');
                };
            };
        };
        function checkboxF() {
            if (!checkbox.checked || window.innerWidth <= 511 && send === false) {
                document.querySelector('.echeckbox').classList.add('active');
                document.querySelector('.kform-c-div').classList.add('active');
            }
            else if (checkbox.checked && !window.innerWidth <= 511) {
                document.querySelector('.echeckbox').classList.remove('active');
                document.querySelector('.kform-c-div').classList.remove('active');
            };
            if (!checkbox.checked) {
                send = false;
            };
        };
        function changeEmptyWarningsBasedOnWidth() {
            if (window.innerWidth <= 511) {
                document.querySelector('.echeckbox').innerHTML = 'Pflichtfelder wurden nicht ausgefüllt!';
            }
            else {
                document.querySelector('.echeckbox').innerHTML = 'Checkbox ist ein Pflichtfeld!';
            };
        };
        checkboxF();
        changeEmptyWarningsBasedOnWidth();
        window.addEventListener('resize', changeEmptyWarningsBasedOnWidth, false);
        window.addEventListener('resize', checkboxF, false);
        if (send === true && sent === false) {
            e.submit();
            const submitButton = document.querySelector('.kform-div form .submitButton');
            submitButton.classList.add('success');
            submitButton.innerHTML = 'Gesendet!';
            sent = true;
            setTimeout(() => {
                document.kctform.reset();
            },2000);
            setTimeout(() => {
                submitButton.classList.remove('success');
                submitButton.innerHTML = 'Senden';
                sent = false;
            },10000);
        };

ERROR TypeError: Cannot read properties of null (reading ‘getAttribute’)

When data is empty i get this error-> ERROR TypeError: Cannot read properties of null (reading ‘getAttribute’)

Error:

chunk-UOKKXAU3.js:7 ERROR TypeError: Cannot read properties of null (reading 'getAttribute')
    at wT (chunk-FLTRA2LT.js:2:30682)
    at VM (chunk-FLTRA2LT.js:15:65614)
    at nnt (chunk-FLTRA2LT.js:15:65536)
    **at n.drawGraph (chunk-EXIXHUOH.js:33:1018)**
    at Object.next (chunk-EXIXHUOH.js:18:15207)
    at io.next (chunk-UOKKXAU3.js:3:3101)
    at we._next (chunk-UOKKXAU3.js:3:2784)
    at we.next (chunk-UOKKXAU3.js:3:2511)
    at Object.next (chunk-JDCFQ7WB.js:26:3066)
    at io.next (chunk-UOKKXAU3.js:3:3101)

The highlighted line no takes me to this code:

 drawGraph() {
    type EChartsOption = echarts.EChartsOption;
    **var chartDom = document.getElementById('networkGraph')!;** // error
    echarts.dispose(chartDom);
    this.mychart = echarts.init(chartDom);
......
.....
}

And when there is some data, I get this error-> ERROR TypeError: Cannot set properties of undefined (setting’dataIndex’)

I get this error when there is some data.

I am not getting why these error are coming. I would highly appreciate if someone can help.

Data received from server:

{
    "headers": {
        "normalizedNames": {},
        "lazyUpdate": null,
        "lazyInit": null,
        "headers": {}
    },
    "status": 200,
    "statusText": "OK",
    "url": "http://ip:port/handler/?action=trafficVisualizationServiceData",
    "ok": true,
    "type": 4,
    "body": {
        "httpstatuscode": 200,
        "AppData": {
            "data": [],
            "link": [],
            "categories": [
                {
                    "name": "CNF"
                },
                {
                    "name": "SCPE"
                },
                {
                    "name": "SCPI"
                },
                {
                    "name": "IPENDPOINT"
                }
            ]
        },
        "opStatusCode": 2000,
        "type": "SUCCESS",
        "message": "DATA RECEIVED SUCCESSFULLY"
    }
}

app.ts:

  drawGraph() {
    type EChartsOption = echarts.EChartsOption;
    var chartDom = document.getElementById('networkGraph')!;
    echarts.dispose(chartDom);
    this.mychart = echarts.init(chartDom);

    interface GraphNode {
      symbolSize: number;
      label?: {
        show?: boolean;
      };
    }

    this.mychart.showLoading();

    (this.graph = {
      nodes: this.nodes,
      links: this.links,
      categories: this.categories,
    }),
      this.mychart.hideLoading();
    console.log('nodes : ' + JSON.stringify(this.graph.nodes));

    let scpEgressThresholdTps = this.scpEgressThresholdTps;

    // this.impactedProxyList.has("")
    let impactedProxyListTemp: Set<string> = this.impactedProxyList;

    this.graph.nodes.forEach(function (node: any) {
      if (node.category == 'IPENDPOINT') {
        node.symbol = 'roundRect';
        node.symbolSize = 17;

        console.log('endpoint_kpi : ' + node.kpi);

        if (node.kpi === undefined) {
          node.itemStyle = {
            color: 'white', // Background color
            borderColor: '#818181', // Border color
            borderWidth: 1, // Border width
          };
        } else {
          node.itemStyle = {
            color: 'white', // Background color
            borderColor: '#FD5E5E',
            borderWidth: 5, // Border width
          };
        }
      } else if (node.category == 'SCPI') {
        node.symbol = 'circle';
        node.symbolSize = 20;

        let isProxyImpacted: boolean = false;
        Object.entries(impactedProxyListTemp).forEach(([key, value]) => {
          console.log('key_value : ' + key, value);
          if (value == node.proxyId) {
            isProxyImpacted = true;
          }
        });

        console.log('isProxyImpacted : ' + isProxyImpacted);
        if (isProxyImpacted) {
          console.error('this proxy is impacted.');
          node.itemStyle = {
            color: '#7EA6FF', // Background color
            borderColor: '#FD5E5E', // Border color
            borderWidth: 5, // Border width
          };
        } else if (node.value > scpEgressThresholdTps) {
          node.itemStyle = {
            color: '#7EA6FF', // Background color
            borderColor: '#fee902', // Border color
            borderWidth: 5, // Border width
          };
        } else {
          node.itemStyle = {
            color: '#7EA6FF', // Background color
            borderWidth: 1, // Border width
          };
        }
      } else if (node.category == 'SCPE') {
        node.symbol = 'circle';
        node.symbolSize = 20;

        let isProxyImpacted: boolean = false;
        Object.entries(impactedProxyListTemp).forEach(([key, value]) => {
          console.log('key_value : ' + key, value);
          if (value == node.proxyId) {
            isProxyImpacted = true;
          }
        });

        if (isProxyImpacted) {
          console.error('this proxy is impacted.');
          node.itemStyle = {
            color: '#3188FF', // Background color
            borderColor: '#FD5E5E', // Border color
            borderWidth: 5, // Border width
          };
        } else if (node.value > scpEgressThresholdTps) {
          node.itemStyle = {
            color: '#3188FF', // Background color
            borderColor: '#fee902', // Border color
            borderWidth: 5, // Border width
          };
        } else {
          node.itemStyle = {
            color: '#3188FF', // Background color
            borderWidth: 1, // Border width
          };
        }
      } else if (node.category == 'CNF') {
        node.symbol = 'roundRect';
        node.symbolSize = 26;
        node.itemStyle = {
          color: '#00A1BE', // Background color
          borderWidth: 1, // Border width
        };
      } else {
        node.symbol = 'circle';
        node.symbolSize = 13;
        node.itemStyle = {
          borderColor: '#5E42FA', // Border color
          borderWidth: 1, // Border width
        };
      }
    });

    this.graph.links.forEach(function (link: any) {
      console.log('isLinkImpacted : ' + link.isLinkImpacted);

      if (link.isLinkImpacted === undefined) {
        link.lineStyle = {
          width: 2, // Set width of the line
          type: 'solid', // Set type of the line to solid
          color: 'green', // Set color of the line
        };
      } else {
        link.lineStyle = {
          width: 2, // Set width of the line
          type: 'solid', // Set type of the line to solid
          color: 'red', // Set color of the line
        };
      }
    });


    this.mychart.setOption(this.option);
    this.option && this.mychart.setOption(this.option);
 
  }

HTML:

<div *ngIf="showConnectedGraph && isConnectedGraphDataAvailable " id="networkGraph" style="width: 100%; border-radius: 5px; height: 550px; background-color: white;"></div>
<div class="nodata" *ngIf="(showConnectedGraph) && (!isConnectedGraphDataAvailable)" style="width: 100%; border-radius: 5px; height: 550px; background-color: white;">Data Not Available</div>

How to Execute JavaScript Line by Line While Preserving Scope?

II am building a custom JavaScript debugger that allows users to execute code line by line, maintain scope across lines, and implement debugger functionalities like stepping into/over code, breakpoints, etc.

I attempted to execute code line by line using eval, but I encountered scope issues where variables and functions declared on one line were not accessible on subsequent lines. Here’s a minimal reproducible example of the problem:

let codeString = `
  function test(param){
    return param;
  }
  console.log(test("param"));
`;

let codeLines = codeString.split("n"); // Split code into lines

function execute() {
  for (let line of codeLines) {
    if (line.trim()) {
      try {
        eval(line); // Execute each line independently
      } catch (error) {
        console.error("Error executing line:", line, error);
      }
    }
  }
}

execute();

When running this code:

  1. Scope Issue: The test function declared on the first line is not accessible to the console.log statement on the second line because eval executes each line in isolation.

  2. Expected Behavior: I want each line to be executed in a way that preserves the shared execution context (like in a real JavaScript runtime).

How can I execute JavaScript code line by line while maintaining the scope and context between lines?

I am specifically looking for:

  • A way to preserve variable/function declarations across lines.

  • A method to enable low-level control for implementing debugging features like stepping and breakpoints.

I’ve tried exploring alternatives like the Function constructor but ran into similar scope issues. Any suggestions or insights would be greatly appreciated!

Nest Error Handling not Catching Errors when AuthGuard is Imported from my Custom Package

Problem:

I have a custom NPM package comprising utilities shared across different microservices built with Nest JS. The problem is that when AuthGuard throws an error with some data from my package, the Nest application catches it but only throws the default error. I am throwing the HttpException error with some data and I want the Nest application to throw the same data as response instead of the default.

Code:

The auth guard in the package is a simple guard that verifies the token and returns a response or an error

import { CanActivate, ExecutionContext, Injectable, HttpException } from '@nestjs/common';
import { verifyToken } from '../helpers';
@Injectable()
export class AuthGuard implements CanActivate {
  constructor() {}
  async canActivate(context: ExecutionContext): Promise<any> {
    const request = context.switchToHttp().getRequest();
    try {
      const token = request.headers.authorization?.split(' ')[1];
      return await verifyToken(
        token,
      );
    } catch (error) {
      console.log('⛈️⛈️⛈️⛈️⛈️⛈️', error);
       throw new HttpException(
        {
          errorDetails: "Token Expired",  
        },
        401,
      );    
  }
}

By this logic, I should be getting the error in the format of

{
errorDetails:"Token Expired"
}

but the NEST return a default error

{
    "statusCode": 500,
    "message": "Internal server error"
}

I have tried to create a Nest Module for the AuthGuard and import it into my app.module but it didn’t work. I have created global exception filter for it but it didn’t work also.

The same code works if I place it in a file inside my application.

How to alter Javascript code from SFTP to HTTPS to transfer file

I have SFTP code using Javascript for transfering file from our local on-prem server to cloud server (in this case is from ServiceNow MID Server to AWS S3). But I am required to transfer by using HTTPS protocol (port : 443). Question, by using below information,

  1. Can I reused same script but just changing port from 22 to 443?
  2. If cant, then how I can alter the existing code from SFTP into HTTPS?

Endpoint : sn-bucket-stg.vpce-xxx-xxx.s3.us-east-1.vpce.amazonaws.com
Port : 443
Username : sn-aws-user
Password : xxxxxxxxx
Objective : Transfer file A.pdf from Folder C:/AWS to S3 Bucket sn-bucket-stg/SNFolder

SFTP code :

var SFTP_Test = Class.create();
SFTP_Test.prototype = {
    initialize: function() {
        this.Properties = Packages.java.util.Properties;
        this.StringUtil = Packages.com.glide.util.StringUtil;
        this.BufferedWriter = Packages.java.io.BufferedWriter;
        this.File = Packages.java.io.File;
        this.FileWriter = Packages.java.io.FileWriter;
        this.FileReader = Packages.java.io.FileReader;
        this.Encrypter = new Packages.com.glide.util.Encrypter();
        this.FileOutputStream = Packages.java.io.FileOutputStream;
        this.FileInputStream = Packages.java.io.FileInputStream;
        this.BufferedReader = Packages.java.io.BufferedReader;
        this.InputStreamReader = Packages.java.io.InputStreamReader;
        this.OutputStraem = Packages.java.io.OutputStream;
        this.OutputStreamWriter = Packages.java.io.OutputStreamWriter;
        this.BufferedOutputStream = Packages.java.io.BufferedOutputStream;
        this.Thread = Packages.java.lang.Thread;

        this.targetServer = "sn-bucket-stg.vpce-xxx-xxx.s3.us-east-1.vpce.amazonaws.com";
        this.targetPort = "22";
        this.targetUsername = "sn-aws-user";
        this.targetPassword = "xxxxxxxxxxx";
        this.targetPath = "SNFolder";
        this.FILE_PATH = "C:/AWS";
        this.FILE_NAME = "A.pdf";
        this.TARGETFILENAME = "SN_A.pdf";
        this.PROCESSED_PATH = "C:/SNFolder/Backup";
        this.FILE_EXTENSION = "pdf";

    },


    FileTransfer: function() {
        try {
            var localFileName = this.FILE_PATH + "/" + this.FILE_NAME;
            var processedFileName = this.PROCESSED_PATH + "/" + this.TARGETFILENAME;
            this.log("Copying from local file : " + localFileName);

            this.sftpFile(this.targetServer, this.targetUsername, this.targetPassword, localFileName, this.targetPath + this.TARGETFILENAME, processedFileName);

        } catch (e) {
            this.log("Error : " + e);
        }
    },


    sftpFile: function(hostName, userName, password, localFileName, remoteFileName, processedFileName) {
        if (!this.targetPort) {
            this.targetPort = 22;
        }
        
        var authPassword = new Packages.com.glide.util.Encrypter().decrypt(password);
        
    var jsch = new Packages.com.jcraft.jsch.JSch();
    var jschSession = jsch.getSession(userName, hostName);
    jschSession.setPassword(authPassword);
    var config = this.Properties();
    config.put("StrictHostKeyChecking", "no");
    jschSession.setConfig(config);
    jschSession.connect();
        
    var channelSftp = jschSession.openChannel("sftp");
    channelSftp.connect();
         
            try {

                var inputFile = new this.File(localFileName);

                if (this.FILE_EXTENSION == 'xlsx') {
                    
                    var inputStream = this.FileInputStream(inputFile);
                    var outputStream = this.FileOutputStream(processedFileName);
                    var byteRead;
                    while ((byteRead = inputStream.read()) != -1) {
                        outputStream.write(byteRead);
                    }
                } else {
                    var fileReader = this.FileReader(inputFile); // A stream that connects to the text file
                    var bufferedReader = this.BufferedReader(fileReader); // Connect the FileReader to the BufferedReader
                    //create new file
                    // Creates a FileOutputStream
                    var outputFile = this.FileOutputStream(processedFileName);
                    // Creates an OutputStreamWriter
                    var output = this.OutputStreamWriter(outputFile);
                    var line;
                    while ((line = bufferedReader.readLine()) != null) {
                        
                        // Writes string to the file
                        output.write(line);
                        output.write("rn");
                    }

                    // Closes the reader
                    bufferedReader.close();
                    // Closes the writer
                    output.close();
                    this.log('copied file to ' + processedFileName);
                }
                //}

                //END
                channelSftp.put(processedFileName, remoteFileName);

                this.log("File has successfully copied to target path");

            } catch (e) {
                this.log('Error: ' + e);
            }
        channelSftp.exit();
            try {
                // kill connection
                jschSession.disconnect();
            } catch (e) {
                this.log('Error: ' + e);
            }
        //}

    },

    type: 'SFTP_Test'
};

Any ways to export and import annotation in PDF as JSON using Mozilla PdfJs Viewer

I recently tried annotating in PDF Viewer provided Mozilla where I can annotate and save the annotations within the pdf.

But my use case is to annotate and export the annotation as JSON, then I want to import it back while rendering the PDF.

I have tried,

// Gets all the annotation data as a map that can be exported as JSON
annotations = pdfDocument.annotationStorage.serializable(); 

// Tried loading the Annotations by setting it after the new render
pdfjsLib.getDocument({
  data: pdfData,
  cMapUrl: CMAP_URL,
  cMapPacked: CMAP_PACKED,
  enableXfa: true,
}).promise.then((_pdfDocument) => {
  for (let [key, value] of annotations) {
    pdfDocument.annotationStorage.setValue(key,value);
   }
  })

This stores the annotation to the storage, but it is not rendered in UI. Does anyone have the same use case and tried importing and exporting PDF annotation in Mozilla PDF Js?

Is there any method in the PDFViewer class to import the serialized annotation?

Your small input will be greatly appreciated. Thanks for reading my question.