Uwe Laubender and I have recently proposed a cool and pretty fast method that retrieves and reports all DOM objects present in the active document: TextFrames, Polygons, Footnotes, Stories, Rectangles, Groups, Guides as well as Pages, Spreads, Links, Sections, Layers, Assignments, TrapPresets, XMLElements, styles, Colors, Gradients, Inks, and so on. Any persistent component—that is, having an ID—will be reported, no matter how deep it is in the object hierarchy.

Note. — This therefore excludes volatile objects that only exist as index-based ranges within a stream, such as Words, Paragraphs, Cells, Tables, etc.

Thus, the “Collect Everything” routine provides a full snapshot of the current document state. How does it work? It simply inspects all registered and valid object IDs from the internal DOM database, based on the (little known) fact that itemByID() can access any kind of element regardless of the collection from which you invoke the method. The key idea is then to loop within the exhaustive interval of possible IDs, from 1 to N, where N refers to the highest ID that the current InDesign document may address. Given a candidate i in [1,N], we just have to check whether anyCollection.itemByID(i).isValid.

Of course, the main problem is to determine N. Noting that InDesign creates unique (increasing) IDs in chronogical order, Uwe found a brilliant solution: “one could [temporarily] add a new object like a rectangle and use its ID value” as the highest number. Indeed! This allows us to initialize N as follows:

var doc = app.activeDocument,
    coll = doc.pageItems;
 
// ---
// Uwe's trick
// ---
var N = (function(_){
   return coll.itemByID(_=doc.rectangles.add().id).remove(), _;
   })();
 
// . . .
 

It only remains to loop from N-1 to 1, testing the validity of itemByID(i). Each valid ID can then be stored in a structure of your choice (associative array, sequential data, tree, etc.) for further processing. In our example, we just wanted to display the IDs and the corresponding classes in historical order (from newest to oldest). Which leads to the code:

// ==============
// Collect everything!
// ==============
 
const re = /\[object ([^\]]+)/i;
 
var doc = app.activeDocument,
    coll = doc.pageItems,
    // Uwe's trick
    // ---
    i = (function(_){
    return coll.itemByID(_=doc.rectangles.add().id).remove(),_;
    })(),
    o, t, m, a = [];
 
while( i-- )
    {
    if(! (o=coll.itemByID(i)).isValid ) continue;
    t = '' + o.getElements();
    (m=t.match(re)) && (t = m[1]);
    a[a.length] = 'ID' + i + ' => ' + t;
    }
 
alert( a.join('\r') );
 

It's up to you to adapt this pattern to your own project. It may be noted that the whole process is very effective even in complex documents, as ID-based access is generally much faster than DOM-hierarchical lookup.