doublemarked / loopback-console

A command-line tool for Loopback app debugging and administration
MIT License
68 stars 6 forks source link

How to display console.log ? #11

Closed kartsims closed 6 years ago

kartsims commented 7 years ago

Hi,

I would like to use loopback-console to trigger manually scripts that may take a long time. Is there a way to show progress (console.log / process.stdout.write) in the REPL ?

Or if you eventually had another suggestion as on how to do the following I'd be more than happy. What I need is :

Doesn't sound much complicated but I guess I am missing some ExpressJS basics...

Help would be much appreciated, thanks

kartsims commented 7 years ago

OK after reading your code a bit more thoroughly, I found out that I could just require the app's root path and get access to everything... Didn't think that would be that easy !

But the question of showing progress or console.log output remains.

doublemarked commented 7 years ago

Hello there! Yes, for a general command-line script that uses your app's models you can just require it, wait for boot, and then work with everything. Indeed this is exactly how the loopback-console interacts with the app.

Regarding your question about showing progress - it sounds like you have some long-running method in your API and you want some sort of visual information on the command line while it's still running. Right?

I think this may be out of scope of what I would add to the loopback-console, but I can give you some pointers on how you would do this in your own script. In general you need to start the progress or meter or spinner before your long-running call starts and then stop it in the callback once it resolves. For example, something like:

  spinner.start()
  app.models.YourWidgetModel.slowMethod()
     .then(() => spinner.stop())
     .catch(() => spinner.stop())

I would look around for a 3rd-party module that handles the actual spinning or progress meter behavior. I'm aware of the following for progress meters: https://github.com/visionmedia/node-progress

Hope this helps!

kartsims commented 7 years ago

Wow, so fast ⚡️

Thanks for the answer. I understand that this is out of scope, I was just wondering if it was possible to handle console.log calls for instance.

My problem is not to show spinners of progress information, it is that whenever a console.log (or process.stdout.write) is present in a model's method, the information is dumped in the classic loopback CLI, but it is not with your console.

That doesn't allow simple debugging or progress information.

Anyway, as far as I am concerned, I will skip loopback-console for long scripts and will use it only for short actions, where I don't need to have a status update along the way.

Thanks again for the answer and the lib

doublemarked commented 7 years ago

My problem is not to show spinners of progress information, it is that whenever a console.log (or process.stdout.write) is present in a model's method, the information is dumped in the classic loopback CLI, but it is not with your console.

Ah, that's interesting and surprising. I routinely drop console.log calls in code and see it printed when running that code in the console. It definitely should work. Can you provide me a sample project or something to demonstrate the problem?

kartsims commented 7 years ago

Hmm OK my bad, I was making a sample project and it did work.

I didn't get that I had to restart the console for the changes to be acknowledged ! Again I misunderstood basic concepts, sorry about that.

Another idea (might be irrelevant, just let me know) : could there be a dev mode ? For instance if a --watch or --dev parameter is passed, the app would be reloaded when the prompt is up. What do you think ?

doublemarked commented 7 years ago

Hmm OK my bad, I was making a sample project and it did work.

No worries!

Another idea (might be irrelevant, just let me know) : could there be a dev mode ? For instance if a --watch or --dev parameter is passed, the app would be reloaded when the prompt is up. What do you think ?

Yeah, we've discussed this some in the past. The trouble is that the console would need to reload the entire environment to avoid accidentally holding on to old versions of code or data, which means you'd lose any local variables. It would need to behave much like Browsersync, where the entire frontend reloads on change. What do you think? Would it be helpful still, even if you lost local variables on reload?

kartsims commented 7 years ago

I haven't used local variables yet so I'll have to answer that later, based on the experience I'll get.

Wouldn't it be possible to use require-reload to hot-reload the Loopback app ?

doublemarked commented 7 years ago

There are a lot of caveats to hot-reloading when dealing with a Loopback app due to the app lifecycle. For instance, code that's sitting inside the base function of your model.js file can be expected to be run at a specific phase of app boot. If you change such a file we really should reboot the entire app, not just reload that model.js file. In the end there are only a few places that a hot-reload can happen without requiring the entire app to reload. And if the app is reloading any stale model instances should be removed/invalidated.

kartsims commented 7 years ago

I meant to use require-reload in bin/loopback-console file, to replace the existing const app = require(path.resolve(appPath));

Maybe I didn't understand the scope of local variables ? Did you mean local as in inside Loopback or as in inside LB console ?

doublemarked commented 7 years ago

I meant to use require-reload in bin/loopback-console file, to replace the existing const app = require(path.resolve(appPath));

I see. Yes, that's what I was getting at, though - we cannot do a targeted reload of individual files that change, we have to reload the entire app.

Maybe I didn't understand the scope of local variables ? Did you mean local as in inside Loopback or as in inside LB console ?

Within the console. For instance, const user = User.findOne(). On reload we need to ensure that the user handle is removed. But it gets a little messier as references may be sunk into other modules, not just local variables. Probably it is best to just restart the entire environment. It might be possible to just wrap the entire console process under nodemon or something similar to just restart the process, maybe with a flag to limit the output to make it less jarring.

kartsims commented 7 years ago

Oh OK I see what you mean by "local variables" now.

I agree that hot reloading Loopback models could become tedious. How about relying on a third party tool like Webpack ?

This might come out of scope because it would impact the Loopback app itself, but just for the discussion I found this article about hot module replacement in the backend, based on Webpack. Example repo here

This is a more complex solution but I guess it would preserve local variables ?

Otherwise, if we stick with the nodemon solution that is easier, a little example in the docs could be nice. It would be enough to avoid installing nodemon as a dependency to loopback-console (given it seems to be a specific use case).