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

girgen

v0.3.13

Published

GIR Parser and type generator.

Readme

GirGen

GIR Parser and type generator.

Install

There are pre built binaries for linux-x64 and linux-arm64 published on NPM.

npm install girgen -D
./node_modules/.bin/girgen --help

Otherwise you can install from crates.io using cargo.

cargo install girgen --root .
./bin/girgen --help

TypeScript

Generate a standalone package that contains every namespace found in the given directories.

girgen typescript --help

[!TIP]

You can use the Gnome flatpak SDK to acquire GIR files on systems that don't have them in one place, e.g NixOS or when you are targeting Flatpak.

flatpak run --command=cp --filesystem=home org.gnome.Sdk -r /usr/share/gir-1.0 gir-1.0
girgen -d gir-1.0 typescript

By default it will generate the package to .types/gi which you can then source in tsconfig.json.

{
  "compilerOptions": {
    "lib": ["es2024"], // don't forget to specify a `lib` to avoid sourcing TypeScript's `dom` lib
    "skipLibCheck": true, // it's recommended to turn this on
    "typeRoots": [".types"]
  }
}

[!TIP]

Don't forget to gitignore generated files.

echo ".types/gi/" > .gitignore

Note that when using --alias flag to generate non version imports such as gi://Gtk make sure to ignore the version you don't need so that it does not end up as a union of the two versions.

girgen typescript -i Gtk-3.0 --alias

TypeScript Annotations

GObject has a few additional concepts about class methods and properties that cannot be expressed with TypeScript alone. For these girgen generates type only fields on classes and interfaces.

We have annotations for:

  • signals
  • readable properties
  • writable properties
  • construct-only properties

When implementing a GObject subclass you might want to annotate a subset of these or all of these depending on usecase.

Every class that inherits from GObject is going to include a namespace containing type declarations where each member is written in kebab-case:

namespace MyClass {
  export interface SignalSignatures extends GObject.Object.SignalSignatures {
    // simple signal
    "my-signal"(arg: number): void
    // detailed signals are annotated with the `::{}` suffix
    "my-detailed-signal::{}"(arg: number): void
  }

  // ReadableProperties is also used for notify signal annotations
  export interface ReadableProperties
    extends GObject.Object.ReadableProperties {
    // property which has a public getter
    "my-prop": number
  }

  export interface WritableProperties
    extends GObject.Object.WritableProperties {
    // property which has a public setter
    "my-prop": number
  }

  export interface ConstructOnlyProperties
    extends GObject.Object.ConstructOnlyProperties {
    // property which can only be set at construction
    "my-ctor-prop": number
  }
}

And the Class will refer to these using special $ prefixed fields:

[!IMPORTANT]

These fields don't exist at runtime, they are used by other APIs to introspect GObjects.

class MyClass extends GObject.Object {
  declare readonly $signals: MyClass.SignalSignatures
  declare readonly $readableProperties: MyClass.ReadableProperties
  declare readonly $writableProperties: MyClass.WritableProperties
  declare readonly $constructOnlyProperties: MyClass.ConstructOnlyProperties

  static {
    GObject.registerClass(
      {
        Signals: {
          "my-signal": {
            param_types: [GObject.TYPE_DOUBLE],
          },
          "my-detailed-signal": {
            param_types: [GObject.TYPE_DOUBLE],
            flags: GObject.SignalFlags.DETAILED,
          },
        },
        Properties: {
          "my-prop": GObject.ParamSpec.double(
            "my-prop",
            null,
            null,
            GObject.ParamFlags.READWRITE,
            -GObject.Double.MAX_VALUE,
            GObject.Double.MAX_VALUE,
          ),
          "my-ctor-prop": GObject.ParamSpec.double(
            "my-ctor-prop",
            null,
            null,
            GObject.ParamFlags.CONSTRUCT_ONLY,
            -GObject.Double.MAX_VALUE,
            GObject.Double.MAX_VALUE,
          ),
        },
      },
      MyClass,
    )
  }

  // GObject.ConstructorProps can be used to infer props from the annotations
  constructor(props: Partial<GObject.ConstructorProps<MyClass>>) {
    super(props)

    // note that properties will be annotated as camelCase
    console.log(props.myProp, props.myCtorProp)
  }
}

Methods such as connect(), emit(), notify() will infer from these annotations.

const instance = new MyClass()

instance.connect("my-signal", (source, arg) => {
  console.log(arg)
})

instance.connect("my-detailed-signal::detail", (source, arg) => {
  console.log(arg)
})

instance.connect("notify::my-prop", (_, pspec) => {
  console.log(pspec.name)
})

Due to how TypeScript this type works, you need to annotate this or use a typecast to correctly infer types within the class.

class MyClass {
  myFn(this: MyClass) {
    this.emit("my-signal", 0)
  }

  myFn() {
    const self = this as MyClass
    self.emit("my-signal", 0)
  }
}

Module Augmentation

If you are using Gio._promisify you can augment namespaces.

import Gio from "gi://Gio?version=2.0"
import GLib from "gi://GLib?version=2.0"

Gio._promisify(
  Gio.InputStream.prototype,
  "read_bytes_async",
  "read_bytes_finish",
)

declare module "gi://Gio?version=2.0" {
  namespace GI {
    namespace Gio {
      interface InputStream {
        read_bytes_async(
          count: number,
          io_priority: number,
          cancellable: Gio.Cancellable | null,
        ): GLib.Bytes
      }
    }
  }
}

declare const stream: Gio.InputStream
const bytes = await stream.read_bytes_async(4096, GLib.PRIORITY_DEFAULT, null)