diff --git a/packages/core/src/Node.ts b/packages/core/src/Node.ts
index 386c37b44c6a67f83a11fa0b044d22d2434fa814..2e275805e29917f198f48aa4258ffca3c81284a0 100644
--- a/packages/core/src/Node.ts
+++ b/packages/core/src/Node.ts
@@ -141,11 +141,13 @@ export abstract class BaseNode<T extends Metadata = Metadata> {
   }
 
   /**
-   * Used with built in JSON.stringify
+   * Creates a deep-clone of the node as JSON
    * @returns
    */
   toJSON(): Record<string, any> {
-    return { ...this, type: this.getType() };
+    const json: Record<string, any> = structuredClone(this);
+    json.type = this.getType();
+    return json;
   }
 }
 
diff --git a/packages/core/src/storage/vectorStore/utils.ts b/packages/core/src/storage/vectorStore/utils.ts
index f7905fcaee2b8a350e05fc23ff7c0cdebc8d2119..1c69ae57ef5ed4ca334350aa574aff531dce10a3 100644
--- a/packages/core/src/storage/vectorStore/utils.ts
+++ b/packages/core/src/storage/vectorStore/utils.ts
@@ -16,15 +16,14 @@ export function nodeToMetadata(
   textField: string = DEFAULT_TEXT_KEY,
   flatMetadata: boolean = false,
 ): Metadata {
-  const nodeObj = node.toJSON();
-  const { metadata, embedding, ...rest } = nodeObj;
+  const { metadata, embedding, ...rest } = node.toJSON();
 
   if (flatMetadata) {
-    validateIsFlat(node.metadata);
+    validateIsFlat(metadata);
   }
 
   if (removeText) {
-    nodeObj[textField] = "";
+    rest[textField] = "";
   }
 
   metadata["_node_content"] = JSON.stringify(rest);
diff --git a/packages/core/src/tests/VectorStore.test.ts b/packages/core/src/tests/VectorStore.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..734a6aa56fc26f7be1d11eb8cc865d4b190035f9
--- /dev/null
+++ b/packages/core/src/tests/VectorStore.test.ts
@@ -0,0 +1,47 @@
+import { Document, MetadataMode } from "../Node";
+import {
+  metadataDictToNode,
+  nodeToMetadata,
+} from "../storage/vectorStore/utils";
+
+describe("Testing VectorStore utils", () => {
+  let node: Document;
+
+  beforeEach(() => {
+    node = new Document({
+      text: "text",
+      metadata: { meta1: "Some metadata" },
+    });
+  });
+
+  test("nodeToMetadata should not modify a node's metadata", () => {
+    nodeToMetadata(node, true);
+    expect(node.metadata).toEqual({ meta1: "Some metadata" });
+  });
+  test("metadataDictToNode should reconstructs node and remove text (except embedding)", () => {
+    const metadata = nodeToMetadata(node, true);
+    const newNode = metadataDictToNode(metadata);
+    expect(newNode.metadata).toEqual({ meta1: "Some metadata" });
+    expect(() => newNode.getEmbedding()).toThrow();
+    expect(newNode.getContent(MetadataMode.NONE)).toEqual("");
+  });
+  test("metadataDictToNode should reconstructs node (except embedding)", () => {
+    const metadata = nodeToMetadata(node, false);
+    const newNode = metadataDictToNode(metadata);
+    expect(newNode.metadata).toEqual({ meta1: "Some metadata" });
+    expect(newNode.getContent(MetadataMode.NONE)).toEqual("text");
+    expect(() => newNode.getEmbedding()).toThrow();
+  });
+  test("metadataDictToNode should not allow deep metadata if flatMetadata is true", () => {
+    node.metadata = { meta: { meta: "meta" } };
+    expect(() => nodeToMetadata(node, false, "text", true)).toThrow();
+  });
+  test("metadataDictToNode should throw an error when node content not found in metadata", () => {
+    const faultyMetadata = {
+      _node_type: "IndexNode",
+    };
+    expect(() => {
+      metadataDictToNode(faultyMetadata);
+    }).toThrow();
+  });
+});