npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

elm-tigershark

v0.0.11

Published

conversations between a tree and a fish

Downloads

18

Readme

Elm Tigershark

Enjoy type-safe interop between Elm and TypeScript with automatically typed flags and ports.

This tool is meant as a mostly drop-in replacement for elm-typescript-interop, so if you don't know what's up start there. While elm-typescript-interop supports Elm 0.18 well but has known bugs with Elm 0.19, elm-tigershark only supports Elm 0.19.

Installation

Tigershark is an npm package and can be installed via npm i elm-tigershark or similar commands.

Usage

Unlike elm-typescript-interop, tigershark uses CLI arguments similar to the Elm compiler in order to specify the Elm input files and generated output file. This level of control allows tigershark to support some interop use cases that are not possible with elm-typescript-interop.

A single Elm program

For a project with one Elm program, we might compile our Elm code and generate type declarations like this:

elm make src/Main.elm --output=src/elm-main.js
tigershark src/Main.elm --output=src/elm-main.d.ts

Importantly, the compiled javascript file and type declaration file have the same name so when we use an import directive, such as import {Elm} from 'elm-main', TypeScript is able to match up the generated types to the compiled Elm code. We could instead use an index file, in this case meaning --output=src/elm-main/index.d.ts

Multiple Elm programs

For a project with multiple Elm programs, we may choose to compile each program separately, like above, or compile multiple Elm programs together into one javascript output. In this later case we need to specify the same files when calling elm make and tigershark so that the output includes types for each Elm program:

elm make src/*.elm --output=src/elm-programs.js
tigershark src/*.elm --output=src/elm-programs.d.ts

Once again, the .d.ts type declaration file name should match the file name of the compiled javascript asset. Like elm make, tigershark will identify which of the provided Elm input files contains a program main function and produces a type for each program.

Webpack and other asset loaders

If we're using Elm with elm-webpack-loader or some other asset management system, then we will have to take advantage of TypeScript's wildcard module declarations feature to associate types with imported Elm files. This use case has some unfortunate nuance, so we'll step through it carefully.

When using elm-webpack-loader the build system identifies which Elm files to find and compile based off of javascript imports with the .elm extension. Given two Elm programs, Foo.elm and Bar.elm, we might import and use the programs like this:

import { Elm as ElmFooApp } from "Foo.elm";
import { Elm as ElmBarApp } from "Bar.elm";

...

ElmFooApp.Foo.init(fooNode, fooFlags)
ElmFooApp.Bar.init(barNode, barFlags)

In previous examples we noted that Typescript pairs untyped javascript files to type declaration files based on file name. How do we accomplish this pairing when the file name has an extension? Unfortunately we can't. The only way to associate types to our Elm imports is by wrapping the type declarations in a wildcard module, specifically declare module '*.elm'. This directive tells TypeScript that every file imported with a .elm extension will use the module's type, regardless of file name.

Here's how we might generate types for our Elm and Typescript project that uses webpack to manage Elm compilation:

tigershark src/Foo.elm src/Bar.elm --output=src/elm.d.ts --tsModule='*.elm'

The name of the output file is no longer relevant, since it's superseded by the wildcard module declaration. The tsModule argument can be changed to support different asset loaders which might use a different import syntax.

Finally, elm-tigershark comes with a webpack plugin to automatically regenerate type declarations when Elm files are changed. The plugin API has not yet been finalized.

Roadmap to 1.0.0

  • [ ] Fix detection of indirect port use
  • [ ] Basic error messages
  • [ ] Basic CLI help output
  • [ ] Improve ElmTigersharkWebpackPlugin API

Known issues

  • The current method of finding ports associated to an Elm program is flawed and needs to be rewritten. If you declare a port in a file, but then wrap the port in a different function and export the wrapping function, the indirect use of the port will not be detected.
  • In Elm 0.19 the --optimize flag removes unused ports from the compiled javascript output. These unused ports are still included in the generated type definition, but calling the port functions from javascript produces a runtime error.

Future enhancements

  • Auto generate TS types, encoders, and decoders for message passing ports.
  • On init, preemptively read files that we know will be needed.
  • Make read file requests for multiple files at once.
  • Write custom "isPortModule" parser so that we don't have to fully parse a file with elm-syntax to find out if it's declared as a port module.
  • Cache ASTs in the Project so that files don't have to be repeatedly re-parsed.

The name

This isn't a useful tool yet so it doesn't have a useful tool name. TypeScript and Tigershark sound a bit similar. That's all I've got.