Giter Site home page Giter Site logo

lydell / elm-watch Goto Github PK

View Code? Open in Web Editor NEW
150.0 9.0 8.0 2.28 MB

`elm make` in watch mode. Fast and reliable.

Home Page: https://lydell.github.io/elm-watch/

License: MIT License

JavaScript 2.16% TypeScript 96.16% Elm 0.96% HTML 0.60% Shell 0.12%
elm watcher

elm-watch's Introduction

elm-watch

elm make in watch mode. Fast and reliable.

elm-watch recompiles whenever your Elm files change and reloads the compiled JS in the browser.

Installation

npm install --save-dev elm-watch

ℹ️ You need to install Elm itself separately, in whatever way you prefer (installer, npm, unofficial npm, elm-tooling).

ℹ️ Node.js 16 or newer is required.

npx elm-watch --help

ℹ️ The rest of the documentation has moved!

πŸ‘‰ https://lydell.github.io/elm-watch/

There are a bunch of links elsewhere that go straight to headings in this readme, so I’ve kept them around.


Getting started

πŸ‘‰ https://lydell.github.io/elm-watch/getting-started/

What elm-watch is

πŸ‘‰ https://lydell.github.io/elm-watch/what-elm-watch-is/

What elm-watch is not

πŸ‘‰ https://lydell.github.io/elm-watch/what-elm-watch-is-not/

Ideas for the future

πŸ‘‰ https://lydell.github.io/elm-watch/what-elm-watch-is/#ideas-for-the-future

Browser UI

πŸ‘‰ https://lydell.github.io/elm-watch/browser-ui/

Clickable error locations

πŸ‘‰ https://lydell.github.io/elm-watch/browser-ui/#clickable-error-locations

elm-watch.json

πŸ‘‰ https://lydell.github.io/elm-watch/elm-watch.json/

targets

πŸ‘‰ https://lydell.github.io/elm-watch/elm-watch.json/#targets

postprocess

πŸ‘‰ https://lydell.github.io/elm-watch/postprocess/

Warning: β€œBricked” setup

πŸ‘‰ https://lydell.github.io/elm-watch/postprocess/#warning-bricked-setup

External process

πŸ‘‰ https://lydell.github.io/elm-watch/postprocess/#external-process

elm-watch-node

πŸ‘‰ https://lydell.github.io/elm-watch/postprocess/#elm-watch-node

Postprocess notes

πŸ‘‰ https://lydell.github.io/elm-watch/postprocess/#postprocess-notes

Hot reloading

πŸ‘‰ https://lydell.github.io/elm-watch/hot-reloading/

HTTPS

πŸ‘‰ https://lydell.github.io/elm-watch/https/

Comparison to other tools

πŸ‘‰ https://lydell.github.io/elm-watch/comparison-to-other-tools/

elm-watch vs generic watcher tools

πŸ‘‰ https://lydell.github.io/elm-watch/comparison-to-other-tools/#elm-watch-vs-generic-watcher-tools

elm-watch vs build tools with Elm support

πŸ‘‰ https://lydell.github.io/elm-watch/comparison-to-other-tools/#elm-watch-vs-build-tools-with-elm-support

elm-watch's People

Contributors

brianhicks avatar chazsconi avatar janiczek avatar kantuni avatar lydell avatar nidico avatar sebsheep avatar sylbru avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elm-watch's Issues

Allow building a file with the hot-reload code inserted

Hi, and thanks for the great work you're doing on elm-watch. We're using it happily in our Django application at work. There are a few features that would make life much easier for us, especially as we would like to integrate our build more directly into Django.

Together with #68, it would be very useful for us to be able to elm-watch make a js file, but still insert the hot-reload code.
The way I would imagine this working is that we could, on a request to our website, generate the js file as a oneshot, which would have the hot-reload code attached so if a developer has elm-watch hot running, the hot-reload connects and they can develop efficiently.

Runtime error after build with --optimize

First of all, Amazing tool !
Works perfect for me in development, but tried to build a production version just now and got this error:
image
( Seems to be a elm-ui text input )

I am using the postprocess.js file from the example here with no modifications.
Any idea what can cause this?

Also, the editor shows an error here. (But no errors when building)
image

dependency versions:
image

Support HTTPS with external SSL handoff

Love the project - it's really improved the productivity in our team!

However, a few weeks ago before HTTPS support was added to the project I forked the library to support our use case which is to use HTTPS, but have the SSL handoff done externally (HAProxy in our case).

We have a few microservices running in our development environment under the same domain so it simplifies things that the SSL handoff is centralised. We also use a real certificate rather than a self-signed one.

For the app we are using with elm-watch we have a backend server (running on port 4000) that serves the HTML pages and then elm-watch backend running on port 4001. HAProxy routes https://my-domain/*:443 to port 4000, and wss://my-domain/elm-watch:443to 4001.

My fork is hardcoded and hacky (main...chazsconi:elm-watch:wss) but works. However, I would like to do this properly and create a PR for a setup like this with some extra optional configuration parameters for elm-watch.json but would like some feedback first:

My idea is to have these extra parameters:

  • A ssl_handoff field which defaults to true, but I would set to false. This would cause elm-watch to run the backend with ws (not wss) on the port specified by port regardless of if the browser is using wss or not.
  • A frontend_port field which would default to the port field, but I would set to 443 in my case.
  • A path field for the websocket that overrides the default /. I would set this to /elm-watch. This would allow HAProxy (or similar) to route the traffic to elm-watch backend without having to use a different port on the frontend. (I already tried without this and having HAProxy to rewrite /elm-watch to / but it seemed to confuse the browser.)

Use pager and scroll to top in hot mode

In my experience it makes sense to work through compiler errors from top to bottom. If the errors messages don't fit, one has to scroll up after running elm make / elm-watch make / elm-watch hot in order to see the first message which is the one I want to work on typically.

Automatically scrolling up to the first error requires some sort of pager mode which makes most sense in hot mode, as it is a running process already and not just "output once".

I'd suggest to put the summary (x errors found etc) on top of the compiler errors and show the output in some sort of (less style) pager, scrolled to top by default. In addition to allowing "scroll-to-top", a pager has the advantage that it allows scrolling (page and linewise) with single keystrokes compared to built-in scrolling in many terminal emulators which require e.g. ctrl-pageup or shift-pageup.

Of course this feature could be made optional through a -P flag, but I think it makes sense to default to this behavior.

Add output to postprocess arguments

I'm migrating from webpack to elm-watch at work.

At the moment in postprocess I"m extracting some css information from the elm code and writing that to a file next to the elm output file. But since the output path is not available in postprocess I'm currently reading the elm-watch.json and looking up the output path through the targetName. This feels very clunky, but works πŸ˜….

Could the output path of the code be added to the postprocess arguments? That would help a lot with our setup.

I've tried/considered other setups for extracting the css information, but at the moment doing it in postprocess seems to be the best approach for us.

elm-watch hangs on error

Whenever some command like elm-watch make fails (see #91 ), the command does not exit with an error, but instead requires the user to press Ctrl+C to exit. This is fine in interactive terminals, but when calling the builder with e.g. subprocess.check_call for automation, this hangs the calling process. It would be nice to either check whether the current shell is interactive or allow overriding this behavior with a flag

dynamically specifying output location

I'm setting up elm-watch at work. We have different parts of the frontend separated into different packages so Turbo can cache the JS/HTML/CSS/images/GraphQL code/etc all independently. This helps us keep builds fast, which is nice.

The convention is that each package has to define a build and package target, which output to build and dist respectively.

Then, in order to make hot reload actually work, I have to write to a third location where all the files get coalesced and served. I can set up a rule that says "when you see a change to this file, copy it into the build" but elm-watch reloads the browser too fast and picks up the old version of the file, so that doesn't work.

At any rate, I ended up with an elm-watch.json that looks structurally similar to this:

{
  "postprocess": ["elm-watch-node", "scripts/postprocess.mjs"],
  "targets": {
    "build": {
      "inputs": [
        "src/Main.elm"
      ],
      "output": "build/js/elm.js"
    },
    "package": {
      "inputs": [
        "src/Main.elm"
      ],
      "output": "dist/js/elm.js"
    },
    "frontend": {
      "inputs": [
        "src/Main.elm"
      ],
      "output": "../../big-frontend-package/build/js/elm.js"
    }
  }
}

It feels very silly to have three basically-identical targets with elm-watch when this is basically a non-issue with elm make. Is there a way to specify the output path dynamically? If not, could that be added? It'd help make this much less of a hack!

using a known hostname but dynamic port

At work, we have to develop the frontend through a proxy. That makes webSocketUrl an absolute necessity, so we're using the beta version of elm-watch. However, sometimes the process manager tries to start a new elm-watch instance before the old one has exited, so we get port conflicts and the app fails to start. This isn't the hugest problemβ€”we can just restart the watcherβ€”but it makes me wonder if it'd make sense to specify the components of the URL separately. For example, instead of:

{
  "webSocketUrl": "ws://localhost:3002/elm-watch"
}

I wonder if we could do:

{
  "webSocketUrl": {
    "secure": false,
    "host": "localhost"
  }
}

Or even use the pseudo-syntax that you show in the examples!

{
  "webSocketUrl": "ws://localhost:${port}/elm-watch"
}

Longer-term, I hope to get rid of the process manager that's exhibiting this iffy behavior, but this would help sand down a rough edge in the mean time!

Ability to set domain for websocket server

I can tell the whole thing is intended to run on localhost, and that works well.

However I had reason to want to run the script in production, using a local development server to serve the script. To test and figure out what was wrong of course, it enabled me to add Debug.log and similar to figure out what the problems were.

However the websocket insisted on running on the public domain, the same as the page was served from. I suspect it just uses a relative url.

I could do it just by using make instead of watch, but if I could have set the full domain I would have had all the power of the tool.

Permission denied when running as root

We are running elm-watch in a docker container which, at least for now, is running as root.

When running elm-watch make for the first time, it fails with the following message:

Log
🚨 Dependencies

-- UNEXPECTED ELM OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/srv/service/elm.json

I tried to make sure all packages are installed by running the following commands:

cd /srv/service
elm make --output=/dev/null /tmp/ElmWatchDummy.elm

I expected it to either exit 0 with no output (success),
or exit 1 with an error I can recognize (using regex) on stderr.

But it exited like this:

exit 1
elm: /root/.elm/0.19.1/packages: createDirectory: permission denied (Permission denied)

-- ERROR -----------------------------------------------------------------------

I ran into something that bypassed the normal error reporting process! I
extracted whatever information I could from the internal error:

>   thread blocked indefinitely in an MVar operation

These errors are usually pretty confusing, so start by asking around on one of
forums listed at https://elm-lang.org/community to see if anyone can get you
unstuck quickly.

-- REQUEST ---------------------------------------------------------------------

If you are feeling up to it, please try to get your code down to the smallest
version that still triggers this message. Ideally in a single Main.elm and
elm.json file.

From there open a NEW issue at https://github.com/elm/compiler/issues with your
reduced example pasted in directly. (Not a link to a repo or gist!) Do not worry
about if someone else saw something similar. More examples is better!

This kind of error is usually tied up in larger architectural choices that are
hard to change, so even when we have a couple good examples, it can take some
time to resolve in a solid way.elm: thread blocked indefinitely in an MVar operation

The same happens when we set ELM_HOME to a temporary directory in /tmp

Details

  • elm make <file> works fine and creates elm-stuff, after which elm-watch also works
  • The working directory is not owned by root, but by a user mapped to the host user (this is necessary since we mount our source directory into the container)
  • chowning the temporary elm-home to the same user causes elm-watch to work

It seems to me that elm-watch has logic that depends on the owner of the working directory, or that triggers when it is run as root, and then tries to run elm with the same user?

Missing "resolved" and "integrity" from lock file

Thank you for this cool project! To make elm-watch easier to use on nix based systems, I have been trying to package this project as a nix flake. While doing that, I noticed that a lot of the dependencies listed in the packages value in package-lock.json are missing their resolved and integrity information. For example, yallist and ansi-styles. I have tried adding in these fields but it seems like there are too many missing to be able to do this by hand.

This issue of missing hashes isn't specific to elm-watch - it seems several other npm packages suffer from this issue.

The only way I could add these fields back in was to remove package-lock.json (and my local node_modules directory) and run npm install. While this does fix the missing fields, it also updates every package to the latest one, meaning my nix flake version of elm-watch isn't identical to the one you provide.

What are your thoughts about adding in the missing resolved and integrity fields, either by regenerating package-lock.json or another method?

RFC: Overhaul HTTPS support

Yesterday I got some great feedback from @dsimunic on using elm-watch behind a proxy and with HTTPS on Discord. That discussion ended up in the following plan:

  1. Add a way to configure the WebSocket URL. This could be "webSocketUrl": "wss://example.com:12345/whatever" in elm-watch.json. It means that the elm-watch client will effectively do new WebSocket("wss://example.com:12345/whatever"). Fixes #60 and #46.

  2. If "webSocketUrl" is unset:

    • On http:// pages, everything will work as before.
    • On https:// pages, elm-watch won’t even try to connect. Instead it will show a helpful message, with a link to docs about how to use elm-watch with HTTPS. Which means setting up an HTTPS server yourself, and proxying the WebSocket.
  3. Remove HTTPS support in elm-watch. This makes #47 not needed any more – you instead control all things HTTPS yourself, at the expense of having to proxy the WebSocket for elm-watch.

@chazsconi and @bdukes would this work for you?


There is just one potential downside of this I can think of. By default, elm-watch sets the WebSocket URL using window.location.hostname. On a phone you might visit http://192.168.1.123 (given that you dev server is exposed on the network and your phone is on the same wifi) and then elm-watch tries to connect to ws://192.168.1.123:45678/elm-watch. So testing on a phone just works. Now, if you for some reason use HTTPS – like https://localhost – then you would have to set "webSocketUrl": "wss://localhost/elm-watch" (since elm-watch no longer does anything on https:// pages without config). But then you wouldn’t be able to test on your phone anymore, without temporarily editing elm-watch.json to say "webSocketUrl": "wss://192.168.1.123:45678/whatever". My plan is to use my classic way of documenting this and saying β€œif you need this, please open an issue”. An idea I have already could be to also have an environment variable ELM_WATCH_WEBSOCKET_URL that overrides elm-watch.json. Then you can easily set it temporarily, or even script it to ask the computer for the IP address and put that in.

elm-watch hangs on error in dependency stage

Hey Simon! I have a weird error here: it looks like elm-watch hangs when elm make exits 1. Similar to #92, I can't seem to reproduce it outside of my projectβ€”it just won't work in a simple SSCCE. However, I was able to stick enough console.log statements in the code that gets run to know that it's hanging somewhere in/after the main then handler that sets up the ctrl-c hook. Seems like there are tasks still running indefinitely in my case. I was able to use why-is-node-running to get a list of tasks that are still running, which I can share privately with you if it'd be helpful.

Anyway, one thing that reliably resolves the issue is to modify that code to look something like this:

   elmWatchCli(process.argv.slice(2)).then((exitCode) => {
     process.exitCode = exitCode;
     if (process.stdout.isTTY) {
       process.stdout.write(
         "Exiting elm-watch. Press ctrl+c (again) to force."
       );
       process.once("exit", () => {
         process.stdout.cursorTo(0);
         process.stdout.clearLine(0);
       });
-    }
+    } else {
+      process.exit(exitCode)
+    }
   }).catch((error) => {

Would you be open to such a change or is there some important thing in the event loop that needs to be cleaned up before the process can exit?

Versions: node v20.9.0 and elm-watch 2.0.0-beta.2

Windows support

Current status: 80-90% of all tests pass. The example seems to work when playing around with it a little bit. You can definitely try it out on Windows, but I don’t dare promising there will be no problems.


elm-watch was written with Windows support from the start, and Node.js is good at Windows support.

However, there are some details that need to be sorted out. Getting the tests to pass 80% should be fairly quick, then I expect an increasing effort for every test. We’ll get there. It should be possible to release improved support without having to wait for every corner case to be fixed.

Command line is too long error

I've been trying out elm-watch and it has been working great so far.

I did encounter a curious problem. We have 99 target inputs and when running hot mode I got a 'The command line is too long.' error. This is the full error:

-- UNEXPECTED ELM OUTPUT ----------------------------------------------------------------------------------------------------------------------------
Target: Widgets

I ran the following commands:

cd 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend'
elm make --report=json --output=/dev/null 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\AuthorizeConsumer\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\ChooseAccount\List\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Embed\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\ForgotPassword\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Home\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Login\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Mix\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Mix\PublicName\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\NotVerified\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Profile\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Radio\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Settings\Account\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Settings\Profile\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Signup\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Tiles\TileName\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\UpdateUserEmail\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Administrators\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Authentication\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Contact\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Customization\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Dashboard\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Home\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Invoice\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\IpBlock\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Lti\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\NotAvailable\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Office365\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Pay\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Sis\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\SisDev\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Subscription\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\UserGroups\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Users\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Workspace\Children\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Pages\Qr\GameLayerEvent\Page.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\AchievementUnlocked\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\AddWebmix\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\AffiliateInformation\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\CookieUserLoader\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\EmbedWebmix\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\IpBlock\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\KeyboardShortcuts\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\LevelUp\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\MoveCopyTile\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\Player\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\PostCleverRegistration\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\Profile\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\PublishToWorkspace\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\PublicWebmixDetails\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\RelatedWebmixes\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\RemoveAccount\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\RemoveWebmix\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\RequestCollaboration\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\SetHomepage\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\ShareProfile\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\ShareTile\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\ShareWebmix\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\Social\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\Subscription\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\UserAffiliation\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\WebmixCollaboration\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\WorkspaceQuickSetup\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\ProfileImageUpload\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\TileImageUpload\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\WorkspaceAvatarUpload\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\WorkspaceLoginBackgroundUpload\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\WorkspaceLoginLogoUpload\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Dialogs\WorkspaceLogoUpload\Dialog.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\GridOverlays\PublicWebspaces\GridOverlay.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\GridOverlays\Webspaces\GridOverlay.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Amazon\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Annotation\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Bing\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Buienradar\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Calculator\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\CustomLogo\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Date\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Deprecated\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Dictionary\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Encyclopedia\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Google\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\GoogleTranslate\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\HeroSearch\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Horoscope\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Messages\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Notepad\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\SafeSearch\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Sigmund\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\SweetSearch\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\SymbalooGallery\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\SymbalooLogo\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\SymbalooSearch\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Tasklist\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Time\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Traffic\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Weather\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Helpers\WebFeed\WebFeedWidget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Welcome\Widget.elm' 'C:\Users\harm\Dev\Symbaloo\main\symbaloo-web\frontend\src\Widgets\Yahoo\Widget.elm'

I expected it to either exit 0 with no output (success),
or exit 1 with JSON on stderr (compile errors).

But it exited like this:

exit 1
The command line is too long.

71 errors found

server: http://localhost:62829, network: http://192.168.2.1:62829
web socket connections: 0, elm-watch-node workers: 1

I believe the max line length for command line on Windows is 8191 characters. When I reduced the number of targets at some point the error disappeared.

After some digging I found out that this only happens when running elm-watch hot inside a yarn/npm script. When you run elm-watch hot directly from the command line it is not a problem.

  • βœ… elm-watch hot
  • βœ… node myscript.js -> elmWatch(["hot"])
  • ❌ npx/yarn elm-watch hot
  • ❌ npm/yarn run my-script -> elm-watch hot
  • ❌ npm/yarn run my-script -> node myscript.js -> elmWatch(["hot"])

I'm not sure if this is actually an elm-watch issue. But it's quite inconvenient if you can not use npm/yarn to run elm-watch.

One thing that would help might be to use relative paths in the elm make command above. That would shorten the command line a lot and make it less likely that this issue occurs.

Tested on Windows command line with version 1.1.2 and 2.0.0-beta.2.

Request: avoid destroying shell scrollback

It appears elm-watch tries to destroy scrollback history:

Screenshot 2022-11-02 at 11 09 39

Other CLI tools that have a similar keep-replacing-previous-output displays (like vite) don't do this.

I found this quite surprising discovering that all my terminal history had disappeared (after initially hitting allow), and a little frustrating. I presume there's a good reason for it, but wanted to give the feedback in case it was avoidable. πŸ€—

Not urgent as I've now set my setting to "always deny", and it now seems to work as vite does.

Ability to set domain for websocket server

I can tell the whole thing is intended to run on localhost, and that works well.

However I had reason to want to run the script in production, using a local development server to serve the script. To test and figure out what was wrong of course, it enabled me to add Debug.log and similar to figure out what the problems were.

However the websocket insisted on running on the public domain, the same as the page was served from. I suspect it just uses a relative url.

I could do it just by using make instead of watch, but if I could have set the full domain I would have had all the power of the tool.

watching through symlinks

Hey! I've got a weird bug. I haven't had success making an SSCCE, but maybe this will jump out at you since you know the code.

I have a pnpm workspace with a bunch of packages, some of which generate Elm code as part of our build system. elm-watch lives in another package which produces the JS artifact. Simplifying some, you can think of our directory layout as being this:

monorepo root
β”œβ”€β”€ generated
β”‚Β Β  β”œβ”€β”€ elm-icons
β”‚Β Β  └── elm-types
└── packages
    └── frontend-elm

6 directories, 0 files

These are all packages, so the packages/frontend-elm package depends on generated/elm-icons, generated/elm-types, and some others. When you run pnpm i these get set up like this:

monorepo root
β”œβ”€β”€ generated
β”‚Β Β  β”œβ”€β”€ elm-icons
β”‚Β Β  └── elm-types
└── packages
    └── frontend-elm
        └── node_modules
            └── generated
                β”œβ”€β”€ elm-icons -> generated/elm-icons
                └── elm-types -> generated/elm-types

(This is the output of tree, where -> means a symlink.)

This has mostly worked fine in the past: when we need to get the generated Elm code from some generated directory, we put node_modules/generated/elm-icons/build/elm or whatever in elm.json, the compiler follows the symlink, compiles the code, we're good.

But recently we noticed that changes to the generated files here don't trigger the file watcher in elm-watch. We'll regenerate code, or make some egregious error on purpose, and elm-watch totally ignores the change until we restart it.

I tried to replicate this with simple symlinks with no success… a setup like below works in the watcher:

.
β”œβ”€β”€ bar -> foo
└── foo
    └── Foo.elm

So this seems to be some specific thing in how pnpm sets things up that doesn't work, but I can't figure out what it is! I thought it might be the fact that the real package names are like @project-generated/elm-icons but that seems to work fine in small samples!

For now, we can get around this by adding ../../generated/elm-icons/src/elm instead of going through node_modules, but that's brittle since it depends more on our directory layout instead of the package names.

Do you have any idea what could be happening here?

Running [email protected]

errors display below <dialog>s

Recently I've transitioned my modals to use native elements, but when I encounter errors via elm-watch the in-app error view is below the modal.

Elm's debugger can be popped out to a separate window which solves this problem, perhaps something similar could be done with elm-watch?

Allow overriding the output file for a target

Hi, and thanks for the great work you're doing on elm-watch. We're using it happily in our Django application at work. There are a few features that would make life much easier for us, especially as we would like to integrate our build more directly into Django.

One of them would be to allow either printing the build input for (single target) builds to stdout, or override the target location from the commandline. This would help us dynamically call the build for a module while rendering a Django page in development mode, so we would not have to depend on a separate process running. We would still spawn the separate process for elm-watch hot when developing, but this way if you forgot you started it you'd just get a non-hot-reload version instead of an outdated build or a missing js file.

elm-watch doesn't exit when stdin closes

In my use case I spawn elm-watch hot from my backend app which uses Phoenix. I configure Phoenix using a watcher (https://hexdocs.pm/phoenix/Phoenix.Endpoint.html#module-runtime-configuration). I am also spawning esbuild for my other assets in the same way.

When Phoenix exits it signals to the child processes (esbuild and elm-watch in my case) that they should also exit by closing stdin, however, elm-watch doesn't exit and is thus left running, so needs to be killed manually.

This is easy to reproduce by running npx elm-watch hot and then pressing ctrl-d - this closes stdin but has no effect on elm-watch which continues running.

I think this should be the standard behaviour for tools like this as both esbuild and webpack terminate from their "watch" mode when stdin is closed.

I can work around this by wrapping elm-watch in this script but it would be nice if this was handled directly by elm-watch.

I tried to fix this, but my JS/Node knowledge is quite basic and I wasn't able to find the right place in the code to listen for stdin being closed and exit so unfortunately I cannot offer a PR.

File changes made don't trigger hot reload - WSL2

Thanks so much for your work on this, it is the best.

I came across this issue (not caused by elm-watch) and thought it might be good to have a note of it in the documentation, however it might also be a bit too abstract to overly worry about.

I am on a Windows machine using vscode devcontainers for my development environment. My repository was located in my Windows User's folder (e.g. C:\Users\michael\Repos). My devcontainer Dockerfile is using ubuntu:jammy.

Essentially file changes made on the windows filesystem don't trigger file changes within the devcontainer, which meant hot reloading was not working.

Moving the repository into WSL2 is the solution. There is a warning on the vitejs website that better explains it vitejs.dev

Error Overlay's errors are output in a different order than the compiler

Thanks for elm-watch, it's been a game changer!

It seems like the errors are being output in a semi-random order, whereas the compiler appears to be consistent in how it orders the errors. It looks like it's got something to do with how elm-watch tries to cache errors maybe.

If I've got errors on lines 82, 95, and 80, both elm make and elm-test --watch'll list them in that order, whereas elm-watch lists them out of order as lines 80, 82, 95.

To reproduce:

Using https://github.com/lydell/elm-watch/tree/main/example-minimal#readme, add the following to src/Main.elm:

myName3 : Int
myName3 = "asdsd"

myName : Int
myName = "asdsd"

myName2 : Int
myName2 = "asdsd"

At first, the errors will be presented in the same order as the compiler, but if you fix what was causing the second error, save, then re-introduce the error, it'll appear at the wrong position.

Example

Here's a recording of what I mean. The left is my editor, and the elm compiler output at the bottom, and elm-watch's output on the right. Towards the end, the myName error is listed first from the compiler, but second in elm-watch.

elm_watch_error_order2.mp4

Workaround

Refresh the page, and the errors will appear in the correct order

Support different client and server ports

This is related to #39 which solved my problem for SSL hand off being done by an external server (An nginx Ingress in Kubernetes in this case).

I was able to have elm-watch listening on port 443 (but serving HTTP not HTTPS) as this port was not being used by anything else as the nginx was running elsewhere.

However, in another use case I have, I am running everything on my laptop - I use a local haproxy to do the SSL handoff. This of course must listen on port 443 thus not allowing elm-watch to also listen on this port.

Therefore I would really like to be able to configure the elm-watch client port to be 443 but set the server port to something else. In haproxy I would then rewrite /elm-watch to the server port.

I know that you are not keen on extra configuration options, so perhaps this could be done via an environment variable either to change the client port or the server port?

Support packages (was: Input file globs)

Loving this project!!

It would be really neat if it was possible to provide a folder or glob to the input array.

Context: I'm working on some library code that don't have an entry file, and listing modules out manually is a bit of a pain.

Add support for error overlays?

Hey there!

A feature I love about tools like elm-live is the ability to keep the browser and editor open at the same time, so I don't need to keep the terminal open at all.

The README was pretty clear about it being undesirable, but it was a gamechanger for me and I'd love to see something like that implemented in elm-watch.

Any chance that an optional error overlay could be enabled that would display Elm's error message in the browser?

Improve test flakiness

The tests are very comprehensive, and I’m very happy that they helped me find so many edge cases. They are written at a very high level, which gives a lot of confidence (and should make a potential rewrite in another language nice). However, the high level involves real time passing, real file system watching and real Web Sockets. While that did help me understand for example file watching better (like, how many watcher events do you get if the same file changes rapidly?), it does make the tests a bit flaky. I’ve used some pretty … clever … hacks to stabilize many tests, but not all.

Currently, the tests pass locally on Linux, Windows and macOS. In CI, jest.retryTimes(2) is needed but even with that one or two jobs usually fail and manually restarting them it’s possible to get all green checkmarks. So the tests still give a lot of confidence, they’re just a little bit annoying.

It doesn’t help that I got tired of testing and β€œfixed” some tests with arbitrary sleeps (in the tests, not in the source code). The readme says β€œelm-watch is serious about stability” – so this is a bit embarrassing.

As soon as I get some more energy I want to get back to this and clean the tests up.

Error related to debug mode?

I'm getting this error when I try to use hot reloading:

Uncaught TypeError: can't access property "$", state is undefined
    $elm$browser$Debugger$Main$getLatestModel cart-widget.elm.js:19763
    wrapSubs cart-widget.elm.js:19778
    F2 cart-widget.elm.js:2872
    _Platform_initialize cart-widget.elm.js:4776
    _Platform_worker cart-widget.elm.js:4722
    F4 cart-widget.elm.js:2881
    init cart-widget.elm.js:5402
    initApp cart-widget.coffee:136
    <anonymous> cart-widget.coffee:465
    <anonymous> cart-widget.js.js:35501
    <anonymous> cart-widget.js.js:35503

I can't figure out what this error is telling me.

The compiled files are loaded one after another in the browser, so I don't think it is an execution order issue.

<script src="/js/cart-widget.elm.js"></script>
<script src="/js/cart-widget.js.js"></script>

I had it working before, but I tried enabling the debug mode; it failed and figured I'd work on that later once I got everything else working. I'm not sure if that is related to this issue.

I cant really see a way to "turn debug mode off" though. Will restarting elm-watch do it?

Some details that may be relevant:

cart-widget.coffee and cart-widget.js.js are the same file, webpack has compiled it and the original name is read from the source map in the backtrace. cart-widget.elm.js is the compiled Elm code.

I have a "backend" worker that maintains one state for the entire page and a few "frontend" apps that are just views. They send and receive messages through ports and the cart-widget.coffee is responsible for creating the different Elm apps and connecting them to each other.

Everything is served from docker and a Ruby on Rails app, but that should be irrelevant; the actual files are essentially served by a static file server, and the app doesn't get far enough to start failing http requests.

source-directories with big ancestor directory β†’ file watcher error

With a source-directories field containing both src and a distant unpublished library

"source-directories": [
    "src",
    "../../../some-libraries/elm-midi/src"
]

elm-watch throws the following error and terminates its process

 21:14:20 Compilation finished in 2.26 s.
-- WATCHER ERROR ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

The file watcher encountered an error, which means that it cannot continue.
elm-watch is powered by its file watcher, so I have to exit at this point.

See if this is something you can solve by maybe removing some problematic files
or something!

This is the error message I got:

ENOSPC: System limit for number of file watchers reached, watch '/home/lue/Desktop/some-libraries/some-unrelated-library/.git/objects/87/05073607de7d25a6bcadb660cf7e1b8bfdd447'

My uneducated guess is that this function:

const watchRoot = longestCommonAncestorPath(paths);

watches all the library files and many more within the parent directory of some-libraries and this app's instead of only the relevant ones from only the specified directories.

Current workaround is moving the unpublished library code to the app's directory.

Anyway, much, much love for building elm-watch! πŸŒˆβƒ€πŸ¦‹

Allow custom elm-watch.json location

Thanks for the amazing package, it really is fantastic and I am using it on multiple projects now. A feature request I have is that it would be nice to be able to say something like:

npx elm-watch make --config path/to/my/elm-watch.json --optimize myTarget

It would also be nice if post processing done inside the elm-watch.json was relative to the file so that related configs like build scripts can be collocated to the elm-watch.json itself. Something like:

{
  "postprocess": ["elm-watch-node", "build.js"],
  "targets": {
    "Main": {
      "inputs": ["../../src/Main.elm"],
      "output": "../../build/main.js"
    }
  }
}

In this case build.js would be in the same directory as the elm-watch.json for example.

how would you use elm-optimize-level-2 with elm-watch?

Is there a good way to use elm-optimize-level-2 with elm-watch? It looks like they both need to start from the Elm files. Just kind of idly curious, but I am looking at these to figure stuff out, so I'd like to know if you've experimented with it!

(And happy holidays!)

Feature request: suport `*` in inputs file path.

It would be nice to be able to use * characters in inputs path like so :

{
    "targets": {
        "My target name": {
            "inputs": [
                "src/App/*/Main.elm"
            ],
            "output": "build/elm.js"
        }
    }
}

The elm compiler does support it ;)

Getting the error `Error: spawn Unknown system error -8` when using Node 18

It seems that with Node > 16 this error happens

Unexpected error:
Error: spawn Unknown system error -8
    at ChildProcess.spawn (node:internal/child_process:413:11)
    at spawn (node:child_process:757:9)
    at /Users/.../node_modules/elm-watch/index.js:3087:19
    at new Promise (<anonymous>)
    at promise (/Users/.../node_modules/elm-watch/index.js:3082:36)
    at spawn2 (/Users/.../node_modules/elm-watch/index.js:3158:99)
    at install (/Users/.../node_modules/elm-watch/index.js:3703:29)
    at continuation (/Users/.../node_modules/elm-watch/index.js:3818:33)
    at installDependencies (/Users/.../node_modules/elm-watch/index.js:3876:14)
    at /Users/.../node_modules/elm-watch/index.js:7333:35

Unexpexcted token ?

Hi, I am getting this error message:

npx: installed 24 in 1.563s
Unexpected token ?

Here is my elm-watch.json file:

{
    "targets": {
        "scripta-app": {
            "inputs": [
                "src/Main.elm"
            ],
            "output": "public/main.js"
        }
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.