Your problem is that you don't have a controlled environment.
For example, I get the impression you routinely upgrade your packages without thinking about it.
All my applications, in any language, constantly have a fixed version number for each dependency. I do upgrade fairly often, but then we run a battery of tests, and this corresponds to a specific commit, which we can revert if needed.
That said, NPM is a nightmare, mainly because the granularity of packages is too small, and there are too many of them.