1StepCloser
I have a biased outlook on the matter, so I'll share that at the end if you care.
For me, this is what I have found, given my projects. I lean very heavy into abstraction every where I can and prefer modularity, rather than hardcoded solutions.
1. Using JS only has the limitations that you aren't utilizing one of constructs biggest strength amongst it's competitors; The eventsheet and the sol paradigm. I doubt anyone can match speed for speed if they only use JS, which then leads to the hybrid approach being favorable. Consider how many lines of JS it takes to emulate a simple "Is A overlapping B" condition.
The api is very verbose imo, and could be streamlined with a number of apis to emulate picking conditions. Without those, you have to recode a lot of stuff. The ghost shooter template is a good example, because it requires a lot of typing to simply do what a few events did. Not only that, it is making lazy overlap tests that would kill performance in a full scale game. At the time it was made, there wasn't a way to GetCollisionCandidates and make use of the internal collision cells.
2. Given the above, a hybrid approach is definitely a better workflow, taking advantage of ACES where can, and doing specialized stuff in JS. You can solve alot of construct's biggest weaknesses by utilizing oop through js modules and extending classes... But... But one issue here: The performance overhead of a single JS block is bad*
Every event block in an event sheet has some overhead behind the scenes. It really isn't bad, but a single blank event still has a cost. Looping a blank event duplicates its cost. A "custom Action" has a cost around 3x that of a blank event and a "function" can be around 4-7x slower than the base. A loop in construct duplicates the overhead of events, which is why they take so much longer than no loop, even if they are acomplishing the same things. A js block in an event sheet takes around 300x longer to run than a blank event, which means if you are doing something simple like computing a dot product from a math module, it's going to be slower by a lot than simply doing it in events.
So... if performance is an issue, now you CANNOT put js blocks into any sort of event sheet loop and you also have to make sure that what you are accomplishing with that Js block more than justifies its incredible overhead.
Now, js blocks can eliminate the need for loops by looping themselves, which is WAY faster than an event sheet loop, but now you are losing any potential to do things through events. Basically, you can create JS systems, and so long as you minimise the number of js blocks that are needed to interact with those systems, you are golden.
---
At the end, this is why I prefer authoring behaviors for some types of problems. they take longer to make, but if I need to constantly interact with them through the event sheet, they make sense from a performance perspective.
As an example, I do alot of vector math in my game, so I created a behavior that has alot of vector utilities, along side an arbitrary number of vectors a user can add to an object. Another example would be a property whose state I need to monitor and control how it is accessed and modified. This is painful to create with events every time you need it, so I made a behavior to handle the boilerplate.
In both cases, using a JS module and calling it from a JS block would make my game unplayable, while using behaviors I can still have 100s of entities/characters.
---
For my bias: I believe if you are doing too much scripting, then you may as well pick a different engine. I make behaviors because the initial investment pays dividends in the event sheet and in scalability, but authoring them is incredibly slow compared to the equivalent in unity. If you are straight up coding the game purely through js, I would ask why bother with construct at that point at all.
Almost every other game engine I have used has a much better workflow where coding is concerned. They have better, bigger, more elegant APIs, and offer more power and flexibility. Its also fair to note, I started with construct, so I should be biased towards it - and it was PAINFUL moving to unity, but once I learned it, it was better in a number of departments. I am choosing to make my current game in construct because I believe that given the my current projects lower complexity, construct will offer a shorter dev cycle than unity will, and I like the fast editor iteration times. I used c2 until about 2016, when I made the switch fully to unity. This is the first year back with c3, but I have always used construct as a prototyping tool.
Fingers crossed, because I am using the internal, private api, but I think I can get a game out faster here than in unity.