From d16558261e3153233f2992de6c094c250e14fbf9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:35:12 +0000 Subject: [PATCH 1/5] Initial plan From f5a77fb1cd25845ca3a3740c7e0ad963935591d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:42:47 +0000 Subject: [PATCH 2/5] Optimize queries to use _id instead of @id for root object lookups Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> --- controllers/delete.js | 11 ++++++++--- controllers/utils.js | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/controllers/delete.js b/controllers/delete.js index 403319cc..604ea16d 100644 --- a/controllers/delete.js +++ b/controllers/delete.js @@ -221,9 +221,14 @@ async function newTreePrime(obj) { async function getAllVersions(obj) { let ls_versions let primeID = obj?.__rerum.history.prime - let rootObj = ( primeID === "root") - ? JSON.parse(JSON.stringify(obj)) - : await db.findOne({ "@id": primeID }) + let rootObj + if (primeID === "root") { + rootObj = JSON.parse(JSON.stringify(obj)) + } else { + //Use _id for indexed query performance instead of @id + const primeHexId = parseDocumentID(primeID) + rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) + } ls_versions = await db.find({ "__rerum.history.prime": rootObj['@id'] }).toArray() ls_versions.unshift(rootObj) return ls_versions diff --git a/controllers/utils.js b/controllers/utils.js index 9de0c011..6ab1e0f9 100644 --- a/controllers/utils.js +++ b/controllers/utils.js @@ -198,16 +198,16 @@ async function alterHistoryNext(objToUpdate, newNextID) { async function getAllVersions(obj) { let ls_versions let primeID = obj?.__rerum.history.prime - let rootObj = ( primeID === "root") - ? //The obj passed in is root. So it is the rootObj we need. - JSON.parse(JSON.stringify(obj)) - : //The obj passed in knows the ID of root, grab it from Mongo - await db.findOne({ "@id": primeID }) - /** - * Note that if you attempt the following code, it will cause Cannot convert undefined or null to object in getAllVersions. - * rootObj = await db.findOne({"$or":[{"_id": primeID}, {"__rerum.slug": primeID}]}) - * This is the because some of the @ids have different RERUM URL patterns on them. - **/ + let rootObj + if (primeID === "root") { + //The obj passed in is root. So it is the rootObj we need. + rootObj = JSON.parse(JSON.stringify(obj)) + } else { + //The obj passed in knows the ID of root, grab it from Mongo + //Use _id for indexed query performance instead of @id + const primeHexId = parseDocumentID(primeID) + rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) + } //All the children of this object will have its @id in __rerum.history.prime ls_versions = await db.find({ "__rerum.history.prime": rootObj['@id'] }).toArray() //The root object is a version, prepend it in From f64e5d6c44cf67abead568a2641e156d793ec6e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:46:57 +0000 Subject: [PATCH 3/5] Add null check validation for primeID before parsing Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> --- controllers/delete.js | 5 ++++- controllers/utils.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/controllers/delete.js b/controllers/delete.js index 604ea16d..1a74121e 100644 --- a/controllers/delete.js +++ b/controllers/delete.js @@ -224,10 +224,13 @@ async function getAllVersions(obj) { let rootObj if (primeID === "root") { rootObj = JSON.parse(JSON.stringify(obj)) - } else { + } else if (primeID) { //Use _id for indexed query performance instead of @id const primeHexId = parseDocumentID(primeID) rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) + } else { + //primeID is undefined or null, cannot proceed + throw new Error("Object has no valid history.prime value") } ls_versions = await db.find({ "__rerum.history.prime": rootObj['@id'] }).toArray() ls_versions.unshift(rootObj) diff --git a/controllers/utils.js b/controllers/utils.js index 6ab1e0f9..0822d3d1 100644 --- a/controllers/utils.js +++ b/controllers/utils.js @@ -202,11 +202,14 @@ async function getAllVersions(obj) { if (primeID === "root") { //The obj passed in is root. So it is the rootObj we need. rootObj = JSON.parse(JSON.stringify(obj)) - } else { + } else if (primeID) { //The obj passed in knows the ID of root, grab it from Mongo //Use _id for indexed query performance instead of @id const primeHexId = parseDocumentID(primeID) rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) + } else { + //primeID is undefined or null, cannot proceed + throw new Error("Object has no valid history.prime value") } //All the children of this object will have its @id in __rerum.history.prime ls_versions = await db.find({ "__rerum.history.prime": rootObj['@id'] }).toArray() From 513721c660678af66b3e57c8685dce93f15f8bb0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:50:23 +0000 Subject: [PATCH 4/5] Add null check for rootObj after database query Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> --- controllers/delete.js | 3 +++ controllers/utils.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/controllers/delete.js b/controllers/delete.js index 1a74121e..5123ed4d 100644 --- a/controllers/delete.js +++ b/controllers/delete.js @@ -228,6 +228,9 @@ async function getAllVersions(obj) { //Use _id for indexed query performance instead of @id const primeHexId = parseDocumentID(primeID) rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) + if (!rootObj) { + throw new Error(`Root object with id '${primeID}' not found in database`) + } } else { //primeID is undefined or null, cannot proceed throw new Error("Object has no valid history.prime value") diff --git a/controllers/utils.js b/controllers/utils.js index 0822d3d1..b45e97fa 100644 --- a/controllers/utils.js +++ b/controllers/utils.js @@ -207,6 +207,9 @@ async function getAllVersions(obj) { //Use _id for indexed query performance instead of @id const primeHexId = parseDocumentID(primeID) rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) + if (!rootObj) { + throw new Error(`Root object with id '${primeID}' not found in database`) + } } else { //primeID is undefined or null, cannot proceed throw new Error("Object has no valid history.prime value") From 6758171d4e5a8f7623e2cb9a01389e5063cbccfd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:54:53 +0000 Subject: [PATCH 5/5] Remove duplicate getAllVersions function and improve error handling Co-authored-by: cubap <1119165+cubap@users.noreply.github.com> --- controllers/delete.js | 44 +------------------------------------------ controllers/utils.js | 7 ++++++- 2 files changed, 7 insertions(+), 44 deletions(-) diff --git a/controllers/delete.js b/controllers/delete.js index 5123ed4d..12aec2ac 100644 --- a/controllers/delete.js +++ b/controllers/delete.js @@ -6,7 +6,7 @@ */ import { newID, isValidID, db } from '../database/index.js' import utils from '../utils.js' -import { createExpressError, getAgentClaim, parseDocumentID } from './utils.js' +import { createExpressError, getAgentClaim, parseDocumentID, getAllVersions, getAllDescendants } from './utils.js' /** * Mark an object as deleted in the database. @@ -218,48 +218,6 @@ async function newTreePrime(obj) { return true } -async function getAllVersions(obj) { - let ls_versions - let primeID = obj?.__rerum.history.prime - let rootObj - if (primeID === "root") { - rootObj = JSON.parse(JSON.stringify(obj)) - } else if (primeID) { - //Use _id for indexed query performance instead of @id - const primeHexId = parseDocumentID(primeID) - rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) - if (!rootObj) { - throw new Error(`Root object with id '${primeID}' not found in database`) - } - } else { - //primeID is undefined or null, cannot proceed - throw new Error("Object has no valid history.prime value") - } - ls_versions = await db.find({ "__rerum.history.prime": rootObj['@id'] }).toArray() - ls_versions.unshift(rootObj) - return ls_versions -} - -function getAllDescendants(ls_versions, keyObj, discoveredDescendants) { - let nextIDarr = [] - if (keyObj.__rerum.history.next.length === 0) { - //essentially, do nothing. This branch is done. - } - else { - nextIDarr = keyObj.__rerum.history.next - } - for (let nextID of nextIDarr) { - for (let v of ls_versions) { - if (v["@id"] === nextID) { - discoveredDescendants.push(v) - getAllDescendants(ls_versions, v, discoveredDescendants) - break - } - } - } - return discoveredDescendants -} - export { deleteObj } diff --git a/controllers/utils.js b/controllers/utils.js index b45e97fa..9da47cea 100644 --- a/controllers/utils.js +++ b/controllers/utils.js @@ -205,7 +205,12 @@ async function getAllVersions(obj) { } else if (primeID) { //The obj passed in knows the ID of root, grab it from Mongo //Use _id for indexed query performance instead of @id - const primeHexId = parseDocumentID(primeID) + let primeHexId + try { + primeHexId = parseDocumentID(primeID) + } catch (error) { + throw new Error(`Invalid history.prime value '${primeID}': ${error.message}`) + } rootObj = await db.findOne({"$or":[{"_id": primeHexId}, {"__rerum.slug": primeHexId}]}) if (!rootObj) { throw new Error(`Root object with id '${primeID}' not found in database`)