How to integrate custom pathfinding algorithm into PathFinding.js library?

I forked the PathFinding.js project and implemented a custom IDDFS (Iterative Deepening Depth-First Search) algorithm. I want to make it work with the visual demo but I keep getting an error.

When I click the Start Search button, I get this error:

Uncaught TypeError: PF.CustomIDDFSFinder is not a constructor

I already made these changes:

Step 1 - Updated the main module exports in src/PathFinding.js:

module.exports = {
    'Heap': require('heap'),
    'Node': require('./core/Node'),
    'Grid': require('./core/Grid'),
    'Util': require('./core/Util'),
    'DiagonalMovement': require('./core/DiagonalMovement'),
    'Heuristic': require('./core/Heuristic'),
    'AStarFinder': require('./finders/AStarFinder'),
    'BestFirstFinder': require('./finders/BestFirstFinder'),
    'BreadthFirstFinder': require('./finders/BreadthFirstFinder'),
    'DijkstraFinder': require('./finders/DijkstraFinder'),
    'BiAStarFinder': require('./finders/BiAStarFinder'),
    'BiBestFirstFinder': require('./finders/BiBestFirstFinder'),
    'BiBreadthFirstFinder': require('./finders/BiBreadthFirstFinder'),
    'BiDijkstraFinder': require('./finders/BiDijkstraFinder'),
    'IDAStarFinder': require('./finders/IDAStarFinder'),
    'JumpPointFinder': require('./finders/JumpPointFinder'),
    'CustomIDDFSFinder': require('./finders/CustomIDDFSFinder')
};

Step 2 - Added switch case in visual/js/panel.js:

case 'custom_iddfs_header':
    allowDiagonal = typeof $('#custom_iddfs_section .allow_diagonal:checked').val() !== 'undefined';
    biDirectional = typeof $('#custom_iddfs_section .bi-directional:checked').val() !== 'undefined';
    dontCrossCorners = typeof $('#custom_iddfs_section .dont_cross_corners:checked').val() !== 'undefined';
    
    finder = new PF.CustomIDDFSFinder({
        allowDiagonal: allowDiagonal,
        dontCrossCorners: dontCrossCorners
    });
    
    break;

Step 3 - Added HTML section in visual/index.html:

<h3 id="custom_iddfs_header"><a href="#">Custom IDDFS Algorithm</a></h3>
<div id="custom_iddfs_section" class="finder_section">
    <header class="option_header">
        <h3>Settings</h3>
    </header>
    <div class="optional sub_options">
        <input type="checkbox" class="allow_diagonal" checked>
        <label class="option_label">Allow Diagonal</label><br>
        <input type="checkbox" class="bi-directional">
        <label class="option_label">Bi-directional</label><br>
        <input type="checkbox" class="dont_cross_corners">
        <label class="option_label">Don't Cross Corners</label><br>
    </div>
</div>

My custom finder implementation:

var Util = require('../core/Util');
var DiagonalMovement = require('../core/DiagonalMovement');

function CustomIDDFSFinder(options) {
    options = options || {};
    this.allowDiagonal = options.allowDiagonal;
    this.dontCrossCorners = options.dontCrossCorners;
    this.diagonalMovement = options.diagonalMovement;

    if (!this.diagonalMovement) {
        if (!this.allowDiagonal) {
            this.diagonalMovement = DiagonalMovement.Never;
        } else {
            if (this.dontCrossCorners) {
                this.diagonalMovement = DiagonalMovement.OnlyWhenNoObstacles;
            } else {
                this.diagonalMovement = DiagonalMovement.IfAtMostOneObstacle;
            }
        }
    }
}

function limitedDepthSearch(searchState, currentNode, goalNode, visitedNodes, gridMap, maxDepth, movementType) {
    if (maxDepth === 0) {
        currentNode.opened = true;
        
        if (currentNode === goalNode) {
            searchState[0] = true;
            searchState[1].push(goalNode);
            return;
        }
    }
    
    var nodeId = "[x=" + currentNode.x + ", y=" + currentNode.y + "]";
    
    if (visitedNodes[nodeId]) {
        return;
    }
    
    visitedNodes[nodeId] = true;
    currentNode.closed = true;
    
    if (maxDepth > 0) {
        var adjacentNodes = gridMap.getNeighbors(currentNode, movementType);
        var nodeCount = adjacentNodes.length;
        var index;
        
        for (index = 0; index < nodeCount; ++index) {
            var adjacentNode = adjacentNodes[index];
            
            if (searchState[0]) {
                return;
            }
            
            var adjacentNodeId = "[x=" + adjacentNode.x + ", y=" + adjacentNode.y + "]";
            
            if (visitedNodes[adjacentNodeId]) {
                continue;
            }
            
            limitedDepthSearch(searchState, adjacentNode, goalNode, visitedNodes, gridMap, maxDepth - 1, movementType);
        }
    }
}

CustomIDDFSFinder.prototype.findPath = function(startX, startY, endX, endY, grid) {
    var startingNode = grid.getNodeAt(startX, startY);
    var targetNode = grid.getNodeAt(endX, endY);
    var movementType = this.diagonalMovement;

    startingNode.opened = true;
    
    var resultPath = [];
    var exploredNodes = {};
    var previousExploredCount = 0;
    var searchState = [false, []];
    
    for (var currentDepth = 0;; ++currentDepth) {
        limitedDepthSearch(searchState, startingNode, targetNode, exploredNodes, grid, currentDepth, movementType);
        
        if (searchState[0]) {
            return searchState[1].reverse();
        }
        
        var exploredCount = Object.keys(exploredNodes).length;
        
        if (previousExploredCount === exploredCount) {
            return [];
        }
        
        previousExploredCount = exploredCount;
        exploredNodes = {};
        searchState[1] = [];
    }
};

module.exports = CustomIDDFSFinder;

What am I missing to make this work properly?

you need to rebuild the lib after addin your custom finder. did u run npm run build or whatever build command they use? the visual demo probably pulls from the built version in dist/, not your source changes.

That constructor error means your finder isn’t being recognized. I’ve hit the same issue adding custom algorithms to PathFinding.js. Your code looks right, but something’s wrong with the file path or the build isn’t updated. Double-check your file structure first - make sure src/finders/CustomIDDFSFinder.js exists with exact capitalization. Then see if PathFinding.js builds to a dist folder. Lots of projects keep source separate from what actually gets loaded, so your changes might not be in the compiled version. Also check how the visual demo loads PathFinding.js - it could be pulling from a CDN, npm package, or pre-built file instead of your modified source. If that’s what’s happening, you’ll need to rebuild the library or point the demo at your dev version. Your export pattern matches the other finders though, so that part’s good.

I’ve hit this same integration nightmare before. You’re manually patching library code and fighting build processes - there’s a better way.

Skip forking PathFinding.js entirely. Use Latenode to automate this:

  1. Feed in your grid data
  2. Run IDDFS in a custom function node
  3. Get results in whatever format you want
  4. Connect to your frontend via webhooks or API

We had the same problem with custom routing algorithms. Instead of modifying libraries and dealing with build chains, I moved everything to Latenode scenarios. Now we test different algorithms instantly without touching any library code.

Your IDDFS code looks good. Just wrap it in a Latenode function, pass your coordinates and grid data, then call it from your demo. No more constructor errors or build headaches.

Check it out: https://latenode.com

I hit this exact same issue adding custom algorithms to PathFinding.js. Your module export is probably missing the constructor function wrapper. You’re defining the constructor right in CustomIDDFSFinder.js, but the module structure doesn’t match what the library expects. Try wrapping everything in an immediately invoked function expression or check how other finders set up their constructors. Also double-check that ./finders/CustomIDDFSFinder actually points to your file - case sensitivity and missing file extensions can make require() fail silently. I had the same TypeError until I copied the exact module export pattern from AStarFinder.