I don't want to keep using [TypeScript](https://www.typescriptlang.org/) for https://github.com/brettcannon/check-for-changed-files and I want to replace it. It needs to work with [npm](https://www.npmjs.com/) or have [GHA](https://docs.github.com/en/actions)-related libraries to make up for the loss of [@actions/core](https://github.com/actions/toolkit/tree/main/packages/core) and [@actions/github](https://github.com/actions/toolkit/tree/main/packages/github). Bonus points if it can compile to a single JS file to eliminate needing [@vercel/ncc](https://www.npmjs.com/package/@vercel/ncc) or committing 3rd-parry libraries like `node_modules` to the repo.
> [!INFO]
> I [went with](https://github.com/brettcannon/check-for-changed-files/commit/8f63f9581067e96ffdaeaeadc0e0e8a4521789cf) [ReScript](https://rescript-lang.org/).
# Possibilities
## Python
Might work with the WASI preview2 build + [JCO](https://github.com/bytecodealliance/jco) + [gidgethub](https://gidgethub.readthedocs.io/en/latest/).
## Go
https://github.com/gopherjs/gopherjs
## [Clojure](https://clojure.org/)
There's [ClojureScript](https://clojurescript.org/), but every time I look at the docs it feels like a lot of work and under-documented. [Shadow-cljs](https://github.com/thheller/shadow-cljs) might simplify things enough to make ClojureScript viable (especially its [`:node-script` build target](https://shadow-cljs.github.io/docs/UsersGuide.html#target-node-script)). Since Clojure is untyped, don't have to worry about how to bring TS types into the language. There are docs on how to use [shadow-cljs with npm](https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages).
# Successes
## TypeScript
https://github.com/brettcannon/check-for-changed-files/tree/rewrite/ts
The project started with this.
## JavaScript
https://github.com/brettcannon/check-for-changed-files/tree/rewrite/mjs
https://github.com/brettcannon/check-for-changed-files/pull/95
It took:
1. Stripping out the types
2. Updating/simplifying the dependencies and configuration files
3. Renaming the files to `.mjs`
4. Moving from [Jest](https://jestjs.io/) to [Vitest](https://vitest.dev/) due to the former not supporting ECMAScript modules
5. Moving from [ncc](https://www.npmjs.com/package/@vercel/ncc) to [esbuild](https://esbuild.github.io/) and not being explicit about esmodule usage in compilation/execution
## [ReScript](https://rescript-lang.org/)
It's immutable and only has functions. [Dusty is also a fan](https://dusty.phillips.codes/rescript/). They do have a [CoC](https://rescript-lang.org/community/code-of-conduct). Can use [`genType`](https://rescript-lang.org/docs/gentype/latest/usage) to help work with Typescript.
### Steps
Following https://rescript-lang.org/docs/manual/latest/converting-from-js
- [x] `npm create rescript-app`
- [x] Port `matching.mjs`
- [x] [Copy the entire contents](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-2-copy-paste-the-entire-js-file) of `*.mjs` into `*.res`
- [x] [Pull out self-contained code into idiomatic ReScript](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-3-extract-parts-into-idiomatic-rescript)
- [x] [Add `external`s and fix types](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-4-add-externals-fix-types)
- [x] [Cleanup](https://rescript-lang.org/docs/manual/latest/converting-from-js#optional-step-5-cleanup)
- [x] Port `gh.mjs`
- [x] [Copy the entire contents](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-2-copy-paste-the-entire-js-file) of `*.mjs` into `*.res`
- [x] [Pull out self-contained code into idiomatic ReScript](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-3-extract-parts-into-idiomatic-rescript)
- [x] [Add `external`s and fix types](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-4-add-externals-fix-types)
- [x] [Cleanup](https://rescript-lang.org/docs/manual/latest/converting-from-js#optional-step-5-cleanup)
- [x] Port `index.mjs`
- [x] [Copy the entire contents](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-2-copy-paste-the-entire-js-file) of `*.mjs` into `*.res`
- [x] [Pull out self-contained code into idiomatic ReScript](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-3-extract-parts-into-idiomatic-rescript)
- [x] [Add `external`s and fix types](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-4-add-externals-fix-types)
- [x] [Cleanup](https://rescript-lang.org/docs/manual/latest/converting-from-js#optional-step-5-cleanup)
- [x] Port `main.mjs`
- [x] [Copy the entire contents](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-2-copy-paste-the-entire-js-file) of `*.mjs` into `*.res`
- [x] [Pull out self-contained code into idiomatic ReScript](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-3-extract-parts-into-idiomatic-rescript)
- [x] [Add `external`s and fix types](https://rescript-lang.org/docs/manual/latest/converting-from-js#step-4-add-externals-fix-types)
- [x] [Cleanup](https://rescript-lang.org/docs/manual/latest/converting-from-js#optional-step-5-cleanup)
- [x] Add in appropriate ReScript (i.e., non-native JS) types for `external`s in `GH.res`
- [x] Set up tasks
- [x] Building via `rescript build -w`
- [x] Testing via `pta tests/*.mjs`
- [x] Move tests over to ReScript
- [x] Move `Matching`
- [x] `action.yml`
- [x] `GH`
- [x] `Main`
- [x] Make more idiomatic for ReScript (e.g. argument order to make piping easier, more use of `option`)
- [x] `Matching.res`
- [x] `Action.res`
- [x] `GH.res`
- [x] `Main.res`
- [x] Clear out all `TODO` and `XXX` markers
- [x] Update to [rescript-zora](https://www.npmjs.com/package/@dusty-phillips/rescript-zora) 5 ([issue](https://github.com/brettcannon/check-for-changed-files/issues/98))
- [x] Decide whether to commit `res.mjs` files (to potentially make PRs easier, also make CI simpler since no build step is necessary; also another good dogfooding situation)
# Failures
## [Gleam](https://gleam.run/)
Trying to wrap code from npm was a massive pain, mostly due to esmodules stuff. After that was `gleam test` not showing enough failure detail: `TypeError: f.split is not a function` is not helpful. Basically the tooling doesn't seem oriented towards JS code calling Gleam code (which is what I was trying to do to make the migration gradual), but more about writing something entirely in Gleam and compiling to JS or Gleam code calling JS.
### Previous notes
Mostly meant for BEAM, but can compile to JS as well. I also appreciate their [community](https://gleam.run/community/) stance (from their homepage):
> As a community, we want to be friendly too. People from around the world, of all backgrounds, genders, and experience levels are welcome and respected equally. See our community code of conduct for more.
>
> Black lives matter. Trans rights are human rights. No nazi bullsh\*t.
Also, [Gleam has reached 1.0](https://gleam.run/news/gleam-version-1/).
Doesn't seem to have extensive help to facilitate working with npm or Node, though. There's support for [JS as an FFI](https://gleam.run/book/tour/external-functions.html) along with a [prelude](https://github.com/gleam-lang/gleam/blob/main/compiler-core/templates/prelude.mjs) (available as `gleam.mjs` in your project; might need to [export it](https://gleam.run/writing-gleam/command-line-reference/)). [gleam_javascript](https://hexdocs.pm/gleam_javascript/) can be used to "work with JavaScript types and values in Gleam" and as example code for how to wrap things. [Plinth](https://hexdocs.pm/plinth/) wraps some Node APIs. I should be able to compile the Gleam code first, then run `ncc build` to still end up with a single JS file.
You need to set the `target` in [`gleam.toml`](https://gleam.run/writing-gleam/gleam-toml/).