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 🙏

© 2026 – Pkg Stats / Ryan Hefner

skir-gleam-gen

v0.1.2

Published

[![npm](https://img.shields.io/npm/v/skir-gleam-gen)](https://www.npmjs.com/package/skir-gleam-gen) [![build](https://github.com/gepheum/skir-gleam-gen/workflows/Build/badge.svg)](https://github.com/gepheum/skir-gleam-gen/actions)

Downloads

616

Readme

npm build

Skir's Gleam code generator

Official plugin for generating Gleam code from .skir files.

Set up

In your skir.yml file, add the following snippet under generators:

  - mod: skir-gleam-gen
    outDir: ./src/skirout
    config: {}

The generated Gleam code has a runtime dependency on skir_client. Add it to your project with:

gleam add skir_client

For more information, see this Gleam project example.

Gleam generated code guide

The examples below are for the code generated from this .skir file.

Referring to generated symbols

// Import the module generated from "user.skir"
import skirout/user

// Now you can use: user.User, user.SubscriptionStatus, user.tarzan_const, etc.

Struct types

Skir generates a plain Gleam record for every struct in the .skir file.

import skir_client
import skir_client/timestamp
import skirout/user

// Construct a User using the generated helper function.
// The helper sets the `unrecognized_` field automatically.
let john =
  user.user_new(
    "John Doe",
    [
      user.user__pet_new(1.0, "Dumbo", "🐘"),
    ],
    "Coffee is just a socially acceptable form of rage.",
    user.SubscriptionStatusFree,
    42,
  )

io.println(john.name)
// John Doe

// `user_default` holds the default value with every field at its zero value.
io.println(user.user_default.name)
// (empty string)
io.println(int.to_string(user.user_default.user_id))
// 0

// Combining the _default constant with Gleam's record update syntax allows
// you to instantiate a struct by only specifying a subset of its fields;
// the remaining fields are set to their default values.
let jane = user.User(..user.user_default, user_id: 43, name: "Jane Doe")

io.println(jane.quote)
// (empty string)
io.println(int.to_string(list.length(jane.pets)))
// 0

Creating modified copies

// Gleam records are immutable.
// To make a modified copy, use record update syntax on the original.
let evil_john =
  user.User(
    ..john,
    name: "Evil John",
    quote: "I solemnly swear I am up to no good.",
  )

io.println(evil_john.name)
// Evil John
io.println(int.to_string(evil_john.user_id))
// 42 (copied from john)

Enum types

The definition of the SubscriptionStatus enum in the .skir file is:

enum SubscriptionStatus {
  FREE;
  trial: Trial;
  PREMIUM;
}

Skir generates a Gleam custom type for every enum in the .skir file.

Constructing enum values

let _statuses = [
  // Unknown is the default and is present in all Skir enums.
  user.subscription_status_unknown,
  user.SubscriptionStatusFree,
  user.SubscriptionStatusPremium,
  // Wrapper variants carry an inner struct.
  user.SubscriptionStatusTrialX(
    user.subscription_status__trial_new(timestamp.Timestamp(
      unix_millis: 1_743_592_409_000,
    )),
  ),
]

Pattern matching on enums

let get_info_text = fn(status: user.SubscriptionStatus) -> String {
  case status {
    user.SubscriptionStatusFree -> "Free user"
    user.SubscriptionStatusPremium -> "Premium user"
    user.SubscriptionStatusTrialX(t) ->
      "On trial since " <> int.to_string(t.start_time.unix_millis)
    user.SubscriptionStatusUnknown(_) -> "Unknown subscription status"
  }
}

io.println(get_info_text(john.subscription_status))
// Free user

let trial_status =
  user.SubscriptionStatusTrialX(
    user.subscription_status__trial_new(timestamp.Timestamp(
      unix_millis: 1_743_592_409_000,
    )),
  )
io.println(get_info_text(trial_status))
// On trial since 1743592409000

Serialization

The serializer for a type is returned by calling the generated *_serializer() function. Use functions from skir_client to serialize and deserialize values.

let serializer = user.user_serializer()

// Serialize to dense JSON (field-number-based; the default mode).
// Use this when you plan to deserialize the value later. Because field
// names are not included, renaming a field remains backward-compatible.
let john_dense_json = skir_client.to_dense_json_code(serializer, john)
io.println(john_dense_json)
// [42,"John Doe",...]

// Serialize to readable (name-based, indented) JSON.
// Use this mainly for debugging.
io.println(skir_client.to_readable_json_code(serializer, john))
// {
//   "user_id": 42,
//   "name": "John Doe",
//   "quote": "Coffee is just a socially acceptable form of rage.",
//   "pets": [ ... ],
//   "subscription_status": "FREE"
// }

// Deserialize from JSON (both dense and readable formats are accepted).
let assert Ok(reserialized_john) =
  skir_client.from_json_code(serializer, john_dense_json)
let assert True = reserialized_john == john

// Serialize to binary format (more compact than JSON; useful when
// performance matters, though the difference is rarely significant).
let john_bytes = skir_client.to_bytes(serializer, john)
let assert Ok(from_bytes) = skir_client.from_bytes(serializer, john_bytes)
let assert True = from_bytes == john

Primitive serializers

io.println(skir_client.to_dense_json_code(skir_client.bool_serializer(), True))
// 1
io.println(skir_client.to_dense_json_code(skir_client.int32_serializer(), 3))
// 3
io.println(skir_client.to_dense_json_code(
  skir_client.int64_serializer(),
  9_223_372_036_854_775_807,
))
// "9223372036854775807"
io.println(skir_client.to_dense_json_code(
  skir_client.float32_serializer(),
  1.5,
))
// 1.5
io.println(skir_client.to_dense_json_code(
  skir_client.float64_serializer(),
  1.5,
))
// 1.5
io.println(skir_client.to_dense_json_code(
  skir_client.string_serializer(),
  "Foo",
))
// "Foo"
io.println(skir_client.to_dense_json_code(
  skir_client.timestamp_serializer(),
  timestamp.Timestamp(unix_millis: 1_743_682_787_000),
))
// 1743682787000

Composite serializers

// Optional serializer:
io.println(skir_client.to_dense_json_code(
  skir_client.optional_serializer(skir_client.string_serializer()),
  option.Some("foo"),
))
// "foo"

io.println(skir_client.to_dense_json_code(
  skir_client.optional_serializer(skir_client.string_serializer()),
  option.None,
))
// null

// List serializer:
io.println(
  skir_client.to_dense_json_code(
    skir_client.list_serializer(skir_client.bool_serializer()),
    [True, False],
  ),
)
// [1,0]

Constants

// Constants declared with 'const' in the .skir file are available as
// top-level constants in the generated Gleam code.
io.println(skir_client.to_readable_json_code(
  user.user_serializer(),
  user.tarzan_const,
))
// {
//   "user_id": 123,
//   "name": "Tarzan",
//   "quote": "AAAAaAaAaAyAAAAaAaAaAyAAAAaAaAaA",
//   "pets": [
//     {
//       "name": "Cheeta",
//       "height_in_meters": 1.67,
//       "picture": "🐒"
//     }
//   ],
//   "subscription_status": {
//     "kind": "trial",
//     "value": {
//       "start_time": {
//         "unix_millis": 1743592409000,
//         "formatted": "2025-04-02T11:13:29Z"
//       }
//     }
//   }
// }

SkirRPC services

Starting a SkirRPC service on an HTTP server

Full example here.

Sending RPCs to a SkirRPC service

Full example here.

Reflection

Reflection allows you to inspect a Skir type at runtime.

import gleam/dict
import gleam/list
import skir_client
import skir_client/type_descriptor

let td = skir_client.type_descriptor(user.user_serializer())

// Print the full type descriptor as JSON.
io.println(type_descriptor.type_descriptor_to_json(td))
// {
//   "type": { "kind": "record", "value": "user.skir:User" },
//   "records": [ ... ]
// }

// Pattern match on the records map to inspect the User struct's fields.
let assert Ok(type_descriptor.StructRecord(user_struct)) =
  dict.get(td.records, "user.skir:User")

let field_names = list.map(user_struct.fields, fn(f) { f.name })
io.println(string.join(field_names, ", "))
// user_id, name, quote, pets, subscription_status

io.println(int.to_string(list.length(user_struct.fields)))
// 5

// A TypeDescriptor can be serialized to JSON and parsed back.
let type_descriptor_json = type_descriptor.type_descriptor_to_json(td)
let assert Ok(reparsed_td) =
  type_descriptor.type_descriptor_from_json(type_descriptor_json)
let assert True = reparsed_td == td