From ac07e3cbe6895170fbbd6f2783f9a5de864c7de6 Mon Sep 17 00:00:00 2001
From: Alex Yang <himself65@outlook.com>
Date: Mon, 16 Sep 2024 12:46:40 -0700
Subject: [PATCH] fix: replace instanceof check with `.type` check (#1214)

---
 .changeset/moody-feet-sit.md         |  6 ++++
 .changeset/witty-windows-lick.md     |  6 ++++
 packages/core/src/schema/node.ts     | 49 ++++++++++++++++++----------
 packages/env/src/global-check.ts     | 31 ++++++++++++++++++
 packages/env/src/index.browser.ts    | 10 +++++-
 packages/env/src/index.edge-light.ts |  1 +
 packages/env/src/index.ts            |  1 +
 packages/env/src/utils/index.web.ts  |  7 ----
 8 files changed, 86 insertions(+), 25 deletions(-)
 create mode 100644 .changeset/moody-feet-sit.md
 create mode 100644 .changeset/witty-windows-lick.md
 create mode 100644 packages/env/src/global-check.ts

diff --git a/.changeset/moody-feet-sit.md b/.changeset/moody-feet-sit.md
new file mode 100644
index 000000000..3792dee2b
--- /dev/null
+++ b/.changeset/moody-feet-sit.md
@@ -0,0 +1,6 @@
+---
+"@llamaindex/core": patch
+"@llamaindex/env": patch
+---
+
+fix: replace instanceof check with `.type` check
diff --git a/.changeset/witty-windows-lick.md b/.changeset/witty-windows-lick.md
new file mode 100644
index 000000000..556e827db
--- /dev/null
+++ b/.changeset/witty-windows-lick.md
@@ -0,0 +1,6 @@
+---
+"@llamaindex/core": patch
+"@llamaindex/env": patch
+---
+
+fix: add `console.warn` when import dual module
diff --git a/packages/core/src/schema/node.ts b/packages/core/src/schema/node.ts
index cf43dd184..a3a0f39df 100644
--- a/packages/core/src/schema/node.ts
+++ b/packages/core/src/schema/node.ts
@@ -437,9 +437,16 @@ export function splitNodesByType(nodes: BaseNode[]): NodesByType {
 
   for (const node of nodes) {
     let type: ModalityType;
-    if (node instanceof ImageNode) {
+    if (
+      node.type === ObjectType.IMAGE ||
+      node.type === ObjectType.IMAGE_DOCUMENT
+    ) {
       type = ModalityType.IMAGE;
-    } else if (node instanceof TextNode) {
+    } else if (
+      node.type === ObjectType.TEXT ||
+      node.type === ObjectType.DOCUMENT ||
+      node.type === ObjectType.INDEX
+    ) {
       type = ModalityType.TEXT;
     } else {
       throw new Error(`Unknown node type: ${node.type}`);
@@ -465,28 +472,36 @@ export function buildNodeFromSplits(
   };
 
   textSplits.forEach((textChunk, i) => {
-    if (doc instanceof ImageDocument) {
+    if (
+      doc.type === ObjectType.IMAGE ||
+      doc.type === ObjectType.IMAGE_DOCUMENT
+    ) {
+      const imageDoc = doc as ImageNode;
       const imageNode = new ImageNode({
-        id_: idGenerator(i, doc),
+        id_: idGenerator(i, imageDoc),
         text: textChunk,
-        image: doc.image,
-        embedding: doc.embedding,
-        excludedEmbedMetadataKeys: [...doc.excludedEmbedMetadataKeys],
-        excludedLlmMetadataKeys: [...doc.excludedLlmMetadataKeys],
-        metadataSeparator: doc.metadataSeparator,
-        textTemplate: doc.textTemplate,
+        image: imageDoc.image,
+        embedding: imageDoc.embedding,
+        excludedEmbedMetadataKeys: [...imageDoc.excludedEmbedMetadataKeys],
+        excludedLlmMetadataKeys: [...imageDoc.excludedLlmMetadataKeys],
+        metadataSeparator: imageDoc.metadataSeparator,
+        textTemplate: imageDoc.textTemplate,
         relationships: { ...relationships },
       });
       nodes.push(imageNode);
-    } else if (doc instanceof Document || doc instanceof TextNode) {
+    } else if (
+      doc.type === ObjectType.DOCUMENT ||
+      doc.type === ObjectType.TEXT
+    ) {
+      const textDoc = doc as TextNode;
       const node = new TextNode({
-        id_: idGenerator(i, doc),
+        id_: idGenerator(i, textDoc),
         text: textChunk,
-        embedding: doc.embedding,
-        excludedEmbedMetadataKeys: [...doc.excludedEmbedMetadataKeys],
-        excludedLlmMetadataKeys: [...doc.excludedLlmMetadataKeys],
-        metadataSeparator: doc.metadataSeparator,
-        textTemplate: doc.textTemplate,
+        embedding: textDoc.embedding,
+        excludedEmbedMetadataKeys: [...textDoc.excludedEmbedMetadataKeys],
+        excludedLlmMetadataKeys: [...textDoc.excludedLlmMetadataKeys],
+        metadataSeparator: textDoc.metadataSeparator,
+        textTemplate: textDoc.textTemplate,
         relationships: { ...relationships },
       });
       nodes.push(node);
diff --git a/packages/env/src/global-check.ts b/packages/env/src/global-check.ts
new file mode 100644
index 000000000..cb6bafc19
--- /dev/null
+++ b/packages/env/src/global-check.ts
@@ -0,0 +1,31 @@
+const glo: any =
+  typeof globalThis !== "undefined"
+    ? globalThis
+    : // @ts-expect-error
+      typeof window !== "undefined"
+      ? // @ts-expect-error
+        window
+      : typeof global !== "undefined"
+        ? global
+        : {};
+
+const importIdentifier = "__ $@llamaindex/env$ __";
+
+if (glo[importIdentifier] === true) {
+  /**
+   * Dear reader of this message. Please take this seriously.
+   *
+   * If you see this message, make sure that you only import one version of llamaindex. In many cases,
+   * your package manager installs two versions of llamaindex that are used by different packages within your project.
+   * Another reason for this message is that some parts of your project use the CJS version of llamaindex
+   * and others use the ESM version of llamaindex.
+   *
+   * This often leads to issues that are hard to debug. We often need to perform constructor checks,
+   * e.g. `node instanceof TextNode`. If you imported different versions of llamaindex, it is impossible for us to
+   * do the constructor checks anymore - which might break the functionality of your application.
+   */
+  console.error(
+    "llamaindex was already imported. This breaks constructor checks and will lead to issues!",
+  );
+}
+glo[importIdentifier] = true;
diff --git a/packages/env/src/index.browser.ts b/packages/env/src/index.browser.ts
index 762e24ea1..3ab85b486 100644
--- a/packages/env/src/index.browser.ts
+++ b/packages/env/src/index.browser.ts
@@ -1,8 +1,16 @@
 /**
- * Edge light environment polyfill.
+ * Web environment polyfill.
  *
  * @module
  */
+import "./global-check.js";
 export * from "./web-polyfill.js";
 
 export { Tokenizers, tokenizers, type Tokenizer } from "./tokenizers/js.js";
+
+// @ts-expect-error
+if (typeof window === "undefined") {
+  console.warn(
+    "You are not in a browser environment. This module is not supposed to be used in a non-browser environment.",
+  );
+}
diff --git a/packages/env/src/index.edge-light.ts b/packages/env/src/index.edge-light.ts
index 667f00bfe..08d2a53d8 100644
--- a/packages/env/src/index.edge-light.ts
+++ b/packages/env/src/index.edge-light.ts
@@ -3,6 +3,7 @@
  *
  * @module
  */
+import "./global-check.js";
 export * from "./node-polyfill.js";
 
 export { Tokenizers, tokenizers, type Tokenizer } from "./tokenizers/js.js";
diff --git a/packages/env/src/index.ts b/packages/env/src/index.ts
index c11fdca1f..32d470080 100644
--- a/packages/env/src/index.ts
+++ b/packages/env/src/index.ts
@@ -18,6 +18,7 @@ import path from "node:path";
 import { Readable } from "node:stream";
 import { fileURLToPath } from "node:url";
 import { createWriteStream, fs } from "./fs/node.js";
+import "./global-check.js";
 import type { SHA256 } from "./node-polyfill.js";
 
 export function createSHA256(): SHA256 {
diff --git a/packages/env/src/utils/index.web.ts b/packages/env/src/utils/index.web.ts
index f8fdfbab5..d2bf3d6b7 100644
--- a/packages/env/src/utils/index.web.ts
+++ b/packages/env/src/utils/index.web.ts
@@ -42,11 +42,4 @@ export class AsyncLocalStorage<T> {
 
 const defaultCustomEvent = (globalThis as any).CustomEvent;
 
-// @ts-expect-error
-if (typeof window === "undefined") {
-  console.warn(
-    "You are not running in a browser environment, which might not as expected",
-  );
-}
-
 export { defaultCustomEvent as CustomEvent };
-- 
GitLab