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/).