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

@jvlk/rescript-remix

v1.0.1

Published

ReScript bindings, modules, and functions for Remix.

Downloads

5

Readme

@jvlk/rescript-remix

ReScript bindings, modules, and functions for Remix.

Requires ReScript v11.

This is a work in progress and is not complete

Installation

npm install @jvlk/rescript-remix

Update rescript.json to include it in your dependencies.

"bs-dependencies": [
   "@jvlk/rescript-remix"
],

If you want to have .res files directly in the app/routes directory you will need to set the file extension to .jsx in rescript.json.

Note: ReScript does not allow you to have $ in file names so you will need to create a JavaScript file for routes with params such as blog/$id.jsx and import from your generated JavaScript files.

Add ReScript extenstions to Remix's ignored files so it doesn't try and load them in as routes and uses the generated .jsx files.

// remix.config.js
export default {
    ignoredRouteFiles: ["**/.*", "**/*.res", "**/*.resi"],
}

root.js

You can add types to Remix's links and meta functions

@module("./style.css")
external styles: string = "default"

let links: Remix.Links.t = () => [Remix.Links.Href({rel: "stylesheet", href: styles})]

let meta: Remix.Meta.t = () => [
  Remix.Meta.Content({name: "viewport", content: "width=device-width, initial-scale=1"}),
  Remix.Meta.Title({title: "My site"}),
  Remix.Meta.Content({
    name: "description",
    content: "a website",
  }),
  Remix.Meta.Charset({charset: "UTF-8"}),
]

@react.component
let make = () => {
  <html lang="en">
    <head>
      <link rel="icon" href="data:image/x-icon;base64,AA" />
      <Remix.Meta />
      <Remix.Links />
    </head>
    <body>
      <main>
        <Remix.Outlet />
      </main>
      <Remix.Scripts />
      <Remix.LiveReload />
    </body>
  </html>
}

let default = make

Loader

To create a typed loader you can use Remix.MakeLoader higher order module (functor). This will create a type for a loader as well as a typed useLoaderData hook that has a typed response.

// _index.res
module Data = {
  type t = {posts: Posts.t} // type for the data returned by the loader
  type params // route params
  type context = { "NODE_ENV": string, "API_KEY": string } // context passed from the server
}

module Loader = Remix.MakeLoader(Data) // create a Loader module for this route

let loader: Loader.t /** use Loader.t to add typing to the exported loader function */= async ({context}) => {
  let secret = context["API_KEY"]
  let data = await Posts.query(secret)
  Loader.json( // this is Remix's json function typed to Data.t
    {posts: data}, // if this doesn't match Data.t you'll get a type error
    ~jsonOptions={ 
      headers: { // you can add headers to the response
        "Cache-Control": "max-age=300, s-maxage=3600",
      },
    },
  )
}

@react.component
let make = () => {
  let {posts} = Loader.useLoaderData() // the data from the hook is fully typed
  <div>
    {posts
    ->Array.map(post => <Post post />)
    ->React.array}
  </div>
}

let default = make // you have to export make as default for route files

Actions

To create an action you can use Remix.MakeAction.

module ActionData = {
  type t
  type context = Env.context
}

module Action = Remix.MakeAction(ActionData)

let action: Action.t = async ({context, request}) => {
    /** */
    Js.null // actions expect you to return a value or null
}