diff -pruN 0.14.31/autopkgtest/runner 0.14.32/autopkgtest/runner
--- 0.14.31/autopkgtest/runner	2022-06-15 04:28:38.000000000 +0000
+++ 0.14.32/autopkgtest/runner	2022-07-22 12:17:02.000000000 +0000
@@ -13,7 +13,7 @@ function dolink() {
 	done
 }
 
-MAKEFILES='^(?:(?:(?:(?:rollup[\.\-].*|ava\.)config|karma\.conf|.mocharc)\.j|g(?:ulpfile\.(?:babel\.m?j|(?:t|m?j))|runt(?:file)?\.j))s|j(?:est\.config\.js|sl\.node\.conf|asmine\.json)|(?:tsconfig.*|lerna)\.json|babel\.config\.js(?:on)?|(?:[cm]ake|Docker)file|\.babelrc(?:.js)?)$'
+MAKEFILES='^(?:(?:g(?:ulpfile\.(?:babel\.m?j|(?:t|m?j))|runt(?:file)?\.j)|(?:(?:rollup[\.\-].*|ava\.)config|karma\.conf)\.j)s|j(?:est\.config\.js|sl\.node\.conf|asmine\.json)|\.(?:mocharc\.js(?:on)?|babelrc(?:.js)?)|(?:tsconfig.*|lerna)\.json|babel\.config\.js(?:on)?|(?:[cm]ake|Docker)file)$'
 
 pack="."
 if [ -e debian/nodejs/main ]; then
diff -pruN 0.14.31/debian/changelog 0.14.32/debian/changelog
--- 0.14.31/debian/changelog	2022-06-29 14:59:19.000000000 +0000
+++ 0.14.32/debian/changelog	2022-08-02 16:54:30.000000000 +0000
@@ -1,3 +1,13 @@
+pkg-js-tools (0.14.32) unstable; urgency=medium
+
+  * New tool: getFromNpmCache
+  * pkgjs-install: use npm cache if available
+  * autopkgtest:
+    + add .mocharc.json and .babelrc.json in Makefile list
+  * pkgjs-depends: fix for circular dependencies (Closes: #1016483)
+
+ -- Yadd <yadd@debian.org>  Tue, 02 Aug 2022 18:54:30 +0200
+
 pkg-js-tools (0.14.31) unstable; urgency=medium
 
   * add-node-component: include main module into component tree
diff -pruN 0.14.31/debian/control 0.14.32/debian/control
--- 0.14.31/debian/control	2022-06-29 14:57:12.000000000 +0000
+++ 0.14.32/debian/control	2022-07-02 08:02:07.000000000 +0000
@@ -12,7 +12,8 @@ Build-Depends-Indep: devscripts
  , libdebian-source-perl <!nocheck>
  , libgraph-perl <!nocheck>
  , libipc-run-perl <!nocheck>
- , libjson-perl <!nocheck>
+ , libjson-perl
+ , libprogress-any-output-termprogressbarcolor-perl
  , libregexp-assemble-perl <!nocheck>
  , libtest-output-perl <!nocheck>
  , libyaml-perl <!nocheck>
@@ -72,6 +73,7 @@ Recommends: apt-file
  , libcache-cache-perl
  , libprogress-any-output-termprogressbarcolor-perl
  , node-semver
+ , nodejs:any
  , npm
 Suggests: autodep8
  , git-buildpackage
diff -pruN 0.14.31/debian/pkg-js-tools.install 0.14.32/debian/pkg-js-tools.install
--- 0.14.31/debian/pkg-js-tools.install	2022-06-11 06:00:37.000000000 +0000
+++ 0.14.32/debian/pkg-js-tools.install	2022-07-02 08:02:07.000000000 +0000
@@ -4,6 +4,7 @@ lintian/tags/*          usr/share/lintia
 pkg-js-salsa.conf	usr/share/pkg-js-tools/
 usr/bin/debcheck-node-repo
 usr/bin/dh-make-node
+usr/bin/getFromNpmCache
 usr/bin/github-debian-upstream
 usr/bin/pkgjs-audit
 usr/bin/pkgjs-depends
diff -pruN 0.14.31/dh_nodejs/dh_makefiles 0.14.32/dh_nodejs/dh_makefiles
--- 0.14.31/dh_nodejs/dh_makefiles	2022-03-16 07:41:46.000000000 +0000
+++ 0.14.32/dh_nodejs/dh_makefiles	2022-07-22 12:32:56.000000000 +0000
@@ -1,5 +1,6 @@
 \.babelrc
-\.babelrc.js
+\.babelrc\.js
+\.babelrc\.json
 ava\.config\.js
 babel\.config\.js
 babel\.config\.json
@@ -15,6 +16,7 @@ jsl\.node\.conf
 karma\.conf\.js
 lerna\.json
 makefile
-.mocharc\.js
+\.mocharc\.js
+\.mocharc\.json
 rollup[\.\-].*config\.js
 tsconfig.*\.json
diff -pruN 0.14.31/doc/man/pkg-js-tools.7 0.14.32/doc/man/pkg-js-tools.7
--- 0.14.31/doc/man/pkg-js-tools.7	2022-06-11 06:00:37.000000000 +0000
+++ 0.14.32/doc/man/pkg-js-tools.7	2022-07-02 08:02:07.000000000 +0000
@@ -551,6 +551,8 @@ a node component\. See
 JS Group Sources Tutorial \fIhttps://wiki\.debian\.org/Javascript/GroupSourcesTutorial\fR\|\.
 It can also list components or modules (real names)
 .IP \(bu 2
+\fBgetFromNpmCache\fR: export npm cache content to standard output
+.IP \(bu 2
 \fBgithub\-debian\-upstream\fR: launches it in source repo to create a
 debian/upstream/metadata \fI(works only if upstream repo is on GitHub)\fR
 .IP \(bu 2
@@ -640,6 +642,11 @@ T}|T{
 0\.9\.18
 T}
 T{
+getFromNpmCache
+T}|T{
+0\.14\.32
+T}
+T{
 mjs2cjs
 T}|T{
 0\.12\.3
diff -pruN 0.14.31/doc/tools/README.md 0.14.32/doc/tools/README.md
--- 0.14.31/doc/tools/README.md	2022-06-11 06:00:37.000000000 +0000
+++ 0.14.32/doc/tools/README.md	2022-07-02 08:02:07.000000000 +0000
@@ -350,6 +350,7 @@ See related manpages.
   a node component. See
   [JS Group Sources Tutorial](https://wiki.debian.org/Javascript/GroupSourcesTutorial).
   It can also list components or modules (real names)
+* **getFromNpmCache**: export npm cache content to standard output
 * **github-debian-upstream**: launches it in source repo to create a
   debian/upstream/metadata _(works only if upstream repo is on GitHub)_
 * **nodepath**: shows the path of a node module (npm name). You can use `-p` to
@@ -393,6 +394,7 @@ pkgjs-depends(1), pkgjs-audit(1), pkgjs-
 | dh_nodejs_autodocs auto_dispatch |      0.14.5     |
 | dh_nodejs_substvars              |      0.14.5     |
 | dh-make-node                     |      0.9.18     |
+| getFromNpmCache                  |      0.14.32    |
 | mjs2cjs                          |      0.12.3     |
 | mjs2cjs -a                       |      0.14.14    |
 | pkgjs-audit                      |      0.11.2     |
diff -pruN 0.14.31/lib/Debian/Debhelper/Buildsystem/nodejs.pm 0.14.32/lib/Debian/Debhelper/Buildsystem/nodejs.pm
--- 0.14.31/lib/Debian/Debhelper/Buildsystem/nodejs.pm	2022-04-21 07:18:22.000000000 +0000
+++ 0.14.32/lib/Debian/Debhelper/Buildsystem/nodejs.pm	2022-07-22 12:17:02.000000000 +0000
@@ -56,7 +56,7 @@ sub DESCRIPTION {
 
 # Regexp compiled from dh_nodejs/dh_root_files.excluded
 my $rootFilesIgnored =
-qr/^(?:(?:g(?:ulpfile\.(?:babel\.m?j|(?:t|m?j))|runt(?:file)?\.j)|(?:rollup[\.\-].*config|karma\.conf|.mocharc)\.j)s|b(?:abel\.config\.js(?:on)?|inding\.gyp|ench.*\.js|ower\.json)|c(?:o(?:mponent\.json|ntribute|pying)|hange(?:log|s?)|akefile)|a(?:ut(?:otest\.watchr|hors?)|va\.config\.js|ppveyor\.yml)|j(?:est\.config\.js|sl\.node\.conf|asmine\.json)|.*\.(?:m(?:arkdown|d)|pdf|txt)|t(?:sconfig.*\.json|ests?\.js)|l(?:icen[cs]e.*|erna\.json)|\.(?:babelrc(?:.js)?|.*)|(?:Docker|make)file|package-lock\.json|yarn\.lock|history)$/i;
+qr/^(?:(?:g(?:ulpfile\.(?:babel\.m?j|(?:t|m?j))|runt(?:file)?\.j)|(?:rollup[\.\-].*config|karma\.conf)\.j)s|b(?:abel\.config\.js(?:on)?|inding\.gyp|ench.*\.js|ower\.json)|c(?:o(?:mponent\.json|ntribute|pying)|hange(?:log|s?)|akefile)|a(?:ut(?:otest\.watchr|hors?)|va\.config\.js|ppveyor\.yml)|j(?:est\.config\.js|sl\.node\.conf|asmine\.json)|\.(?:mocharc\.js(?:on)?|babelrc(?:.js)?|.*)|.*\.(?:m(?:arkdown|d)|pdf|txt)|t(?:sconfig.*\.json|ests?\.js)|l(?:icen[cs]e.*|erna\.json)|(?:Docker|make)file|package-lock\.json|yarn\.lock|history)$/i;
 my $filesIgnored =
 qr/^(?:\.(?:(?:wafpickle-|eslint|_).*|npm(?:ignore|rc)|lock-wscript|gitignore)|.*\.(?:c(?:offee|\+\+|cp?)?|orig|def|mk|h)|(?:[jm]|binding.M)akefile|readme(?:\.(?:txt|md))?|tsconfig\.tsbuildinfo|package-lock\.json|npm-debug\.log|yarn\.lock)$/i;
 
diff -pruN 0.14.31/lib/Debian/PkgJs/Dependencies.pm 0.14.32/lib/Debian/PkgJs/Dependencies.pm
--- 0.14.31/lib/Debian/PkgJs/Dependencies.pm	2022-06-11 06:00:37.000000000 +0000
+++ 0.14.32/lib/Debian/PkgJs/Dependencies.pm	2022-07-02 08:02:07.000000000 +0000
@@ -65,8 +65,9 @@ sub installedModules {
 }
 
 sub downloadAndInstall {
-    my ( $dest, $url ) = @_;
+    my ( $dest, $url, $name, $nocache ) = @_;
     my $pipe = IO::Handle->new;
+    $name //= 'make-fetch-happen';
     open my $null, '>', '/dev/null';
     spawn( exec => [ 'rm', '-rf', $dest ], wait_child => 1, );
     unless ( $url =~ m#^https?://# ) {
@@ -81,11 +82,29 @@ sub downloadAndInstall {
         return;
     }
     spawn( exec => [ 'mkdir', '-p', $dest ], wait_child => 1, );
-    my $getPid = spawn(
-        exec       => [ 'GET', $url ],
-        to_pipe    => $pipe,
-        wait_child => 0,
-    );
+    my $getPid;
+    if ( $name and !$nocache and -e "$ENV{HOME}/.npm/_cacache" ) {
+        spawn(
+            exec => [ 'getFromNpmCache', '-q', "$name:request-cache:$url" ],
+            wait_child => 1,
+            nocheck    => 1,
+        );
+        unless($?) {
+            print STDERR "GET FROM CACHE\n";
+            $getPid = spawn(
+                exec       => [ 'getFromNpmCache', "$name:request-cache:$url" ],
+                to_pipe    => $pipe,
+                wait_child => 0,
+            );
+        }
+    }
+    unless ($getPid) {
+        $getPid = spawn(
+            exec       => [ 'GET', $url ],
+            to_pipe    => $pipe,
+            wait_child => 0,
+        );
+    }
     my $tarPid = spawn(
         exec            => [ qw(tar xzf - -C), $dest, qw(--strip 1) ],
         from_handle     => $pipe,
diff -pruN 0.14.31/lib/Debian/PkgJs/Version.pm 0.14.32/lib/Debian/PkgJs/Version.pm
--- 0.14.31/lib/Debian/PkgJs/Version.pm	2022-06-29 14:50:55.000000000 +0000
+++ 0.14.32/lib/Debian/PkgJs/Version.pm	2022-08-02 16:54:16.000000000 +0000
@@ -2,6 +2,6 @@ package Debian::PkgJs::Version;
 
 use Exporter 'import';
 
-our $VERSION = '0.14.31';
+our $VERSION = '0.14.32';
 our @EXPORT = qw($VERSION);
 
diff -pruN 0.14.31/tools/getFromNpmCache 0.14.32/tools/getFromNpmCache
--- 0.14.31/tools/getFromNpmCache	1970-01-01 00:00:00.000000000 +0000
+++ 0.14.32/tools/getFromNpmCache	2022-07-02 08:02:07.000000000 +0000
@@ -0,0 +1,47 @@
+#!/usr/bin/node
+
+let args = process.argv.slice(2);
+
+const system = (cmd, args) => {
+  const out = require('node:child_process').spawn(cmd, args);
+  out.stdout.on('data', data => console.log(data.toString()));
+  out.stderr.on('data', data => console.error(data.toString()));
+  out.on('close', () => process.exit(0));
+}
+
+const usage = () => {
+  console.log('Usage: getFromNpmCache <npm-cache-key>');
+}
+
+if (!args.length) {
+  console.error('A key is required');
+  usage();
+  process.exit(1);
+} else if (args[0] === '--version') {
+  system('perl', ['-MDebian::PkgJs::Version', '-e', 'print $VERSION']);
+} else if (args[0] === '--help') {
+  usage();
+  process.exit(0);
+} else {
+  let query = false;
+  if (args[0] === '-q') {
+    query = true;
+    args = args.slice(1);
+  }
+  const path = require("path");
+  const cache = path.join(process.env.HOME,".npm","_cacache");
+  const cacache = require("cacache");
+  const fs = require("fs");
+  const {Duplex} = require('stream');
+  
+  cacache.get.info(cache, args[0]).then( info => {
+    if (query) {
+      process.exit(info === null ? 1 : 0);
+    }
+    if (info === null) {
+      console.error('Key not found');
+      process.exit(1);
+    }
+    cacache.get.stream(cache, args[0]).pipe(process.stdout);
+  });
+}
diff -pruN 0.14.31/tools/pkgjs-depends 0.14.32/tools/pkgjs-depends
--- 0.14.31/tools/pkgjs-depends	2022-06-11 06:00:37.000000000 +0000
+++ 0.14.32/tools/pkgjs-depends	2022-08-02 16:52:42.000000000 +0000
@@ -14,6 +14,9 @@ use JSON;
 use Progress::Any '$progress';
 use Progress::Any::Output;
 
+use constant OFFSET                => '  ';
+use constant DEFAULTRECURSIONLIMIT => 100;
+
 Progress::Any::Output->set( 'TermProgressBarColor',
     template =>
 '<color ffff00>%p%</color> <color 808000>[</color>%B<color 808000>]</color>'
@@ -32,12 +35,13 @@ GetOptions(
       c|checkversions
       clearcache
       nocache
+      l|limit=s
     )
 );
 
 my $currentPackage = '';
 $opt{cachedelay} //= CACHEDELAY;
-my $cache        = Debian::PkgJs::Cache->new(%opt);
+my $cache = Debian::PkgJs::Cache->new(%opt);
 
 # Find name
 if ( !@ARGV and -e 'package.json' ) {
@@ -74,6 +78,7 @@ Options:
  -c, --checkversions: verify that version matches
  --nocache: don't use local cache
  --clearcache: clear local cache
+ --limit: recursion limit (default: 100)
 EOF
     exit;
 }
@@ -82,6 +87,8 @@ elsif ( $opt{v} ) {
     exit;
 }
 
+my $recursionLimit = $opt{l} || DEFAULTRECURSIONLIMIT;
+
 # nodejs paths
 my @npaths =
   ( '/usr/share/nodejs', '/usr/lib/nodejs', glob("/usr/lib/*/nodejs") );
@@ -89,20 +96,22 @@ my @npaths =
 # II - Main
 
 sub debug {
-    print STDERR $_[0] if $opt{debug};
+    print STDERR '# ' . ( OFFSET x ( $_[1] // 0 ) ) . $_[0] . "\n"
+      if $opt{debug};
 }
 
-# hashref getDeps( string: $mod, string: $offset )
+# hashref getDeps( string: $mod, int: $recursionCount )
 # Get dependencies of $mod module using the result of `npm view` and
 # launches checkMods() with it
 #
 # $mod: module name
-# $offset: prefix for debugging message ("  " added at each call)
+# $recursionCount: recursion count
 # result: dependencies tree
 sub getDeps {
-    my ( $mod, $offset ) = @_;
-    my $pb = !defined $offset;
-    debug "#$offset checking $mod:\n";
+    my ( $mod, $recursionCount ) = @_;
+    my $pb = !$recursionCount;
+    $recursionCount //= 0;
+    debug( " checking $mod:", $recursionCount );
     my $res;
 
     # $opt{local} is set to package.json#name if no arg is given
@@ -163,27 +172,44 @@ sub getDeps {
         }
         $progress->target($count);
     }
-    checkMods( $res, $offset );
+    if ( $recursionCount < $recursionLimit ) {
+        checkMods( $res, $recursionCount );
+    }
+    else {
+        print STDERR "Recursion limit reached\n";
+    }
     delete $res->{name};
     return $res;
 }
 
-my $global         = {};
-my $missing        = {};
-my $known          = {};
+# Debian packages
+my $global = {};
+
+# Missing modules
+my $missing = {};
+
+# Already checked module
+my $known = {};
+
+# Workaround for circular dependencies
+my $seen = {};
+
+# Versions of Debian modules (works only for installed packages
 my $debianVersions = {};
-my $mismatch       = {};
 
-# void checkMods( hashref: $res, string: $offset )
+# Debian module that mismatch wanted version
+my $mismatch = {};
+
+# void checkMods( hashref: $res, int: $recursionCount )
 # Parse `npm view` result and search for dependencies existing in Debian
 # using local tree and apt/dpkg-query
 # If dependency isn't found in Debian, checkMods() calls getDeps() for it.
 #
 # $res: dependencies tree
-# $offset: prefix for debugging message ("  " added at each call)
+# $recursionCount: recursion count
 sub checkMods {
-    my ( $res, $offset ) = @_;
-    my $pb = !defined($offset);
+    my ( $res, $recursionCount ) = @_;
+    my $pb = !$recursionCount;
     foreach my $f ( 'dependencies', 'peerDependencies', 'devDependencies' ) {
         next unless $res->{$f};
         foreach my $mod ( sort keys %{ $res->{$f} } ) {
@@ -192,7 +218,7 @@ sub checkMods {
             if ( $known->{$mod} ) {
                 $global->{ $known->{$mod} }->{$mod}++;
                 $res->{$f}->{$mod} = { global => $known->{$mod} };
-                debug "#$offset  => package (seen): $known->{$mod}\n";
+                debug( "  => package (seen): $known->{$mod}", $recursionCount );
                 next;
             }
             my $path;
@@ -220,16 +246,15 @@ sub checkMods {
                             $debianVersions->{$debianPackage} = $debianVersion;
                             push @{ $mismatch->{$mod} }, $want;
                         }
-                        debug "Semver result: "
-                          . semver( $debianVersion, $want ) . "\n";
+                        debug( "Semver result: "
+                              . semver( $debianVersion, $want ) );
                     }
                     $global->{$debianPackage}->{$mod}++;
                     $known->{$mod} = $debianPackage;
-                    debug "#$offset  => package: $known->{$mod}\n";
+                    debug( "  => package: $known->{$mod}", $recursionCount );
                     if ( $known->{$mod} eq $currentPackage ) {
-                        debug(
-                            "# $mod is member of current package, continue\n");
-                        getDeps( $mod . '@' . $want, "  $offset" );
+                        debug("$mod is member of current package, continue");
+                        getDeps( $mod . '@' . $want, $recursionCount + 1 );
                     }
                 }
                 else {
@@ -243,12 +268,11 @@ sub checkMods {
                     $res->{$f}->{$mod} = { global => $package };
                     $global->{$package}->{$mod}++;
                     $known->{$mod} = $package;
-                    debug
-"#$offset  => package: $known->{$mod} ($currentPackage)\n";
+                    debug( "  => package: $known->{$mod} ($currentPackage)",
+                        $recursionCount );
                     if ( $known->{$mod} eq $currentPackage ) {
-                        debug(
-                            "# $mod is member of current package, continue\n");
-                        getDeps( $mod . '@' . $want, "  $offset" );
+                        debug("$mod is member of current package, continue");
+                        getDeps( $mod . '@' . $want, $recursionCount + 1 );
                     }
 
                     # Check versions if wanted
@@ -296,10 +320,11 @@ sub checkMods {
                     elsif ( $mod eq $ARGV[0] ) {
                         $res->{$f}->{$mod} = { $want => 1 };
                     }
-                    else {
-                        debug "#$offset  => missing: $mod\n";
+                    elsif ( !$seen->{$mod} ) {
+                        $seen->{$mod}++;
+                        debug( "  => missing: $mod", $recursionCount );
                         $missing->{$mod} = $res->{$f}->{$mod} =
-                          getDeps( $mod . '@' . $want, "  $offset" );
+                          getDeps( $mod . '@' . $want, $recursionCount + 1 );
                         $missing->{$mod}->{$want}++;
                     }
                 }
@@ -314,6 +339,10 @@ sub displayMissing {
     foreach my $f ( 'dependencies', 'devDependencies' ) {
         next unless $res->{$f};
         foreach my $mod ( sort keys %{ $res->{$f} } ) {
+
+            # This is a side effect of circular dependencies,
+            # $res->{$f}->{$mod} might be '*'
+            next unless ( ref $res->{$f}->{$mod} );
             next if $res->{$f}->{$mod}->{global};
             my $reason = banned($mod);
             my $suffix = ( $reason ? " # BANNED ($reason)" : '' );
diff -pruN 0.14.31/tools/pkgjs-install 0.14.32/tools/pkgjs-install
--- 0.14.31/tools/pkgjs-install	2022-06-29 14:47:19.000000000 +0000
+++ 0.14.32/tools/pkgjs-install	2022-07-02 08:02:07.000000000 +0000
@@ -310,17 +310,34 @@ foreach my $module ( keys %toLink ) {
 
 # Step 4: download missing
 
+my %from;
 unless ( $opt{nodownload} ) {
     $progress->target( scalar %toDownload );
+    my $notCache = not( -e "$ENV{HOME}/.npm/_cacache" );
 
     if (%toDownload) {
         print "Downloading...\n";
         foreach my $modulePath ( keys %toDownload ) {
             $progress->update( message => $modulePath );
-            downloadAndInstall( $modulePath, $toDownload{$modulePath} );
+            $from{
+                downloadAndInstall( $modulePath, $toDownload{$modulePath},
+                    undef, $notCache )
+            }++;
         }
         $progress->finish();
-        print "Done\n";
+        print "Done (" . join(
+            ',',
+            map {
+                    $from{$_}
+                  ? $from{$_} . ' '
+                  . {
+                    0 => 'not found',
+                    1 => 'downloaded',
+                    2 => 'from npm cache'
+                  }->{$_}
+                  : ()
+            } ( 0 .. 2 )
+        ) . ")\n";
     }
 }
 
@@ -354,7 +371,7 @@ sub scan {
 
 sub scanAndInstall {
     my ( $path, @fields ) = @_;
-    @fields = ('dependencies', 'peerDependencies') unless @fields;
+    @fields = ( 'dependencies', 'peerDependencies' ) unless @fields;
     my @deps;
     foreach (@fields) {
         my $tmp;
