Library / SDK
graphql-hive/graphql-scalars avatar
graphql-hive/graphql-scalars

graphql-scalars: the scalars GraphQL leaves to you, and the v2 packaging split

A library of custom GraphQL Scalars for creating precise type-safe GraphQL schemas.

1,931 stars142 forksTypeScriptMIT

At a glance

What is it?
graphql-scalars collects scalar types not included in base GraphQL, and at version 2 it ships as a dual CommonJS and ESM package with separate type declaration files, built by bob. Its README is deliberately thin and points every question at a separate documentation site.
Who is it for?
Adopt graphql-scalars if your schema has dates, big integers, JSON payloads or durations and you would rather not write the serialize and parseValue pair for each, because the library is a curated set of those implementations with named exports rather than a framework you adopt. Do not adopt it expecting a scalar for your domain: the inventory is what it is, and anything bespoke still needs writing.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • graphql-hive/graphql-scalars1,931 ★ · +0
Star history
Repository2026-10-162026-10-23
graphql-hive/graphql-scalars1.9k1.9k

0 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What the package claims and what it actually contains

The README states the purpose in one sentence: a library of custom GraphQL scalar types for creating precise type-safe GraphQL schemas, with a link to the GraphQL specification's scalar types documentation.

Then it stops. The README has no install section, no usage example and no list of scalars. Everything is delegated to a separate documentation site, graphql-scalars.dev, and the repository's homepage points to the-guild.dev/graphql/scalars.

The `package.json` description is more informative than the README: a collection of scalar types not included in base GraphQL. That is the whole scope, and it is a narrower and more useful framing than a general GraphQL utility library.

What a scalar is, for the uninitiated, is why this package exists at all. GraphQL's built-in type system covers String, Int, Float, Boolean and ID. Formats such as dates, times, big integers, arbitrary JSON, durations, URLs and non-empty strings can require custom scalar serialization and coercion code.

The credits at the bottom of the README explain where the implementations came from, which is a good indicator of quality. The library was originally published as `@okgrow/graphql-scalars`, created and maintained by the company ok-grow, and The Guild took over maintenance later. Individual scalars are credited to their authors: `graphql-iso-date` to excitement-engineer, `graphql-bigint` to stems, `graphql-type-json` to taion, `GraphQLTimestamp.js` to langpavel, the Duration scalar to vespertilian, and `NonEmptyString` to maxwellsmart84.

There is also a note about the `graphql-scalars` name on npm, which was previously owned by adriano-di-giovanni's own library and was donated. So the package name you install was acquired rather than invented, and the maintainers credit it.

Version 2 is a packaging change, and the exports map is where it lives

The v2.0.0 release on 2026-08-20 was the significant one, and it is worth reading `package.json` rather than the README to understand why.

The package declares `"type": "module"` and then ships two build outputs anyway. `main` is `./dist/cjs/index.js`, `module` is `./dist/esm/index.js`, and `typings` is `./dist/typings/index.d.ts`.

The `exports` map is more detailed than that legacy triple:

json
"exports": {
    ".": {
      "require": {
        "types": "./dist/typings/index.d.cts",
        "default": "./dist/cjs/index.js"
      },
      "import": {
        "types": "./dist/typings/index.d.ts",
        "default": "./dist/esm/index.js"
      },
      "default": {
        "types": "./dist/typings/index.d.ts",
        "default": "./dist/esm/index.js"
      }
    },
    "./package.json": "./package.json"
}

Two things follow. First, the `require` condition points at a `.d.cts` declaration file while `import` points at `.d.ts`, which means a consumer using `require()` from TypeScript needs the `.cts` declarations to resolve correctly. That is the kind of detail that breaks in a project using `moduleResolution: node16` or later, and it is exactly the kind of thing a major version bump exists to fix.

Second, `./package.json` is explicitly exported. Some tools read a dependency's `package.json`, and without that entry the `exports` map would block it. Its presence means a package manager or a build tool can introspect the dependency.

The declared engine is `node >=10`, which is almost certainly a stale floor inherited from the package's long history rather than a real constraint of the v2 build.

One inconsistency to note: the `repository` field points at a different organisation's path than the repository this README lives in. If you are debugging a dependency chain, that field will send you to the wrong place.

The peer dependency is `graphql`, which means the GraphQL implementation is yours to provide rather than a nested copy the package resolves on its own.

Bob builds it, Vitest tests it, and a bundle test guards the output

The scripts tell you the whole toolchain.

The build is `bob build --single`, and bob is The Guild's TypeScript project builder. The generated package entry points are `dist/cjs/index.js` and `dist/esm/index.js`. `bob.config.js` at the root configures it, and `prebuild` runs `yarn clean` which removes `dist`, so a build always starts from empty.

Tests are Vitest, with the config in `vitest.config.ts`. The test script is `vitest run && yarn bundlesize`, which is the detail worth pausing on. The test command is not only unit tests; it also runs a bundle-size check, and that check is a separate nested package in `bundle-test/` that installs its own dependencies and runs its own test.

That means `yarn test` does real network-dependent work in a subdirectory, and a bundle-size regression fails the test suite rather than a separate CI job. For a library whose main deliverable is named exports consumed by many bundlers, that is a defensible choice: it catches a dependency that silently pulls in something heavy.

The remaining scripts cover the release path. `prerelease` runs the build then `bob prepack`, and `release` is `changeset publish`. There is a `.changeset/` directory, so releases are driven by Changesets rather than by editing a version by hand.

Linting has a wrinkle worth copying if you hit it: `ci:lint` and `lint` both set `ESLINT_USE_FLAT_CONFIG=false` through cross-env, with the CI variant writing an `eslint_report.json` in JSON format. So the project runs on `.eslintrc.json`, which is in the root listing, rather than a flat config, and forces the legacy resolution explicitly.

The build toolchain is pinned through `packageManager` as yarn 1.22.22 with a hash, alongside `.yarnrc`, `yarn.lock`, `.husky/`, `renovate.json`, `babel.config.cjs`, `.prettierrc.mjs` and `.editorconfig`.

There is also a `scripts/setup-scalar.js` invoked by `setup-scalar`, which reads like a generator for the boilerplate of adding one more scalar, and a `codegen-test/` directory for testing against generated code.

Where graphql-scalars is the wrong choice

The mismatches are mostly about what the library is not.

It does not cover your domain types. If your schema has a Money type with currency rules, or a semantic version, or a country code with a specific validation set, you are writing that scalar yourself. The library is a menu, and the menu is finite.

It is a collection rather than a framework. There is no schema tooling, no directive system, no middleware, and no validation layer beyond what each scalar does internally. If you want your scalars to share error handling or coercion policy, that is your code.

Version 2 is a real compatibility boundary. Anyone on a build setup that resolves through the legacy `main` and `module` fields with a resolver that does not understand conditional exports, particularly older TypeScript module resolution, is the audience for those three separate type entries. The fix is usually to upgrade the resolver rather than to stay on v1, but plan for it.

The alternative worth weighing is writing your own scalars, which is often less work than it sounds for a simple case. A scalar that parses an ISO date string and rejects invalid input still needs custom serialization and coercion logic. The case for the library is breadth, coverage of the awkward formats, and not having to be the person who decides whether a timestamp accepts an offset.

The documentation boundary is worth being honest about. The README contains no scalar list and no usage, so you cannot evaluate fit from the repository alone; you need the documentation site. That is a reasonable choice for a project with many scalars and a maintained site, and it is a real cost for anyone who works offline or who wants to see the inventory without opening a browser.

Editorial conclusion

Adopt graphql-scalars if your schema has dates, big integers, JSON payloads or durations and you would rather not write the serialize and parseValue pair for each, because the library is a curated set of those implementations with named exports rather than a framework you adopt. Do not adopt it expecting a scalar for your domain: the inventory is what it is, and anything bespoke still needs writing. Verify three things before you pin a version: whether you need the v2 module layout at all, since 2.0.0 shipped on 2026-08-20 and the `exports` map now resolves to `./dist/cjs/index.js` and `./dist/esm/index.js` with three separate type entry points, which is where breaking changes for bundlers and older resolvers live; that your GraphQL peer dependency is satisfied, because `graphql` is declared as a peer dependency rather than bundled; and that the package name resolves where you expect, because `package.json` still carries the repository URL for a different organisation path while the repository itself lives under a different name. The MIT license is at the root, the last push was on 2026-10-15, and v2.0.1 shipped the same day.

Frequently asked questions

What does the graphql-scalars package contain?

A collection of scalar types not included in base GraphQL, according to the package description, for creating precise type-safe schemas. Individual scalars are credited to their original authors, including graphql-iso-date, graphql-bigint, graphql-type-json, GraphQLTimestamp.js, a Duration scalar and NonEmptyString.

What changed in graphql-scalars version 2?

Version 2.0.0 shipped on 2026-08-20 with a dual module layout. The exports map resolves require to ./dist/cjs/index.js with a .d.cts type file, import to ./dist/esm/index.js with a .d.ts type file, and exports ./package.json explicitly. The build uses `bob build --single`.

Who maintains graphql-scalars?

The Guild. The library was originally published as @okgrow/graphql-scalars by the company ok-grow, and The Guild took over maintenance later. The `graphql-scalars` npm name was donated by adriano-di-giovanni, who is credited in the README.

How is graphql-scalars tested?

With Vitest, and the `test` script runs `vitest run && yarn bundlesize`. The bundlesize step builds the package and then installs and tests the nested `bundle-test/` project, so a bundle-size regression fails the normal test suite.

What license is graphql-scalars released under?

MIT, with the LICENSE file at the repository root and the same identifier in package.json. The current version is 2.0.1.

Official sources

  1. graphql-hive/graphql-scalars on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/graphql-hive-graphql-scalars.svg)](https://hysenlabs.com/projects/graphql-hive-graphql-scalars)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/graphql-hive-graphql-scalars.svg)](https://hysenlabs.com/projects/graphql-hive-graphql-scalars)

Was this useful?