gel-js: the official TypeScript client for Gel, with a generated query builder
The official TypeScript/JS client library and query builder for EdgeDB
At a glance
- What is it?
- gel-js is the official JavaScript and TypeScript client for the Gel database, published on npm as `gel`. Beyond a connection pool and typed query methods, it ships a code generator that turns .edgeql files into typed functions and a schema-aware query builder, and the workspace is still organised around the older `edgedb` package name.
- Who is it for?
- gel-js fits a TypeScript team building on Gel that wants the query builder and generated query functions rather than hand-written string queries, and that wants a connection configuration that works in local development and in production without code changes.
- Can I use it commercially?
- Yes. Apache-2.0 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 40 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 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The client is a connection pool with typed query methods
A client is an instance of the `Client` class, which maintains a pool of connections to your database and provides methods for executing queries. Creating one takes no arguments in the common case:
import * as gel from "gel";
const client = gel.createClient();The library resolves where to connect from the environment in two ways. For local development, you initialize a project with the `gel project init` command, and as long as the file is within a project directory, `createClient` will auto-discover the connection information of the project's associated instance. In production, you configure the connection using environment variables, and the easiest way is to set the `GEL_DSN` variable, where a DSN, also known as a connection string, is a string of the form `gel://USERNAME:PASSWORD@HOSTNAME:PORT/DATABASE`. The same environment variable route also works during local development if you prefer it. For anything more involved the README points at the DSN specification and the connection parameters reference.
Query methods are typed, and the return type depends on which one you pick
The query API is where the typing earns its keep, and the README is precise about a distinction that is easy to get wrong. The `.query()` method always returns an array, regardless of the result cardinality of your query. If your query returns zero or one elements, use `.querySingle()` instead, and if your query is guaranteed to return exactly one element, use `.queryRequiredSingle()`:
const client = gel.createClient();
await client.query("select 2 + 2"); // => [4]The difference shows up in the inferred types. A `querySingle<string>` on an empty set gives `string | null`, while `queryRequiredSingle<number>` gives plain `number`, and the compiler points that out. This is a small design decision with real consequences. A project that uses `.query()` everywhere loses the cardinality information in its types, so a `queryRequiredSingle` call is a genuine upgrade over the default, and the README gives the worked examples with a `select <str>{}` empty set and a `select 2 + 2` single element.
The @gel/generate package turns .edgeql files into typed functions
The generators are a separate dev dependency, and the README says so directly. You install `@gel/generate` with `npm install @gel/generate --save-dev`, and then run a generator with `npx @gel/generate <generator> [FLAGS]`. Three generators are currently supported. `queries` generates typed functions from `*.edgeql` files. `interfaces` generates interfaces for your schema types. And `edgeql-js` generates the query builder. The `queries` generator is the one that changes how a codebase is written. Given a file such as `getUser.edgeql` containing a select over User with name and email filtered on the email parameter, it generates a `getUser.query.ts` file alongside it exporting a function called `getUser`, where the first argument is a `Client` and the second is the set of parameters, with both the parameters and the returned value fully typed.
The edgeql-js builder is code first and infers its own return type
The query builder is the other half of the story, and it takes the opposite approach to the generator for .edgeql files. The README describes it as letting you write queries in a code-first way, and it automatically infers the return type of your queries. To generate it you install the `gel` package, initialize a project if you have not already, and run `npx @gel/generate edgeql-js`, which writes the builder into the `./dbschema/edgeql-js` directory as defined relative to your project root. The generated builder is then used as a default export:
import { createClient } from "gel";
import e from "./dbschema/edgeql-js";A select over the Movie type lists the fields it wants, including a nested shape for actors and a computed count, and the filter is expressed as an operation on the movie's title rather than as a string. The result of running the query is then typed, so `result.actors[0].name` is a string the compiler knows about. The two generators are complementary rather than competing, since one wraps hand-written EdgeQL files and the other generates a builder from the schema.
The workspace still carries the edgedb package name
A detail worth flagging for anyone migrating: the repository is a Yarn workspace whose members are `packages/*`, `edgedb/*`, and `integration-tests/*`, so the older product name is still baked into the directory layout even though the package published to npm is now `gel`. The root package is private and names itself `root`, with the package manager pinned to yarn 1.22.19 and Turbo as the task runner, since every script is a `turbo run` of typecheck, build, test, or lint. The dev dependencies are TypeScript 5.8.2, ESLint 9 with typescript-eslint, Prettier 3, and Turbo 2. There is also a `docs/` directory, an `eslint.config.mjs` for flat config, a `.prettierignore`, and a `turbo.json`. The npm package is published under the `gel` name, and the README's badges point at the `gel` npm page and the `gel` GitHub repository, so the rename is complete on the publishing side and only lingering in the paths.
Requirements are modest, and the type generators are the reason to use TypeScript
The Requirements section is short. Node.js 18+ is needed, and for TypeScript users, TypeScript 4.4+ is required. That second line is the tell. The library itself would work from plain JavaScript, since the runtime side is just a connection pool and query methods, and the README's basic usage examples are written in a way that a JavaScript developer could follow. What TypeScript buys is the generator output, because the `queries` generator produces typed functions and the `edgeql-js` builder infers return types from your schema, and both of those are TypeScript features. So the honest framing is that gel-js is a JavaScript and TypeScript library, but the argument for it over a hand-written client is strongest when you are working in TypeScript. The README also points new users at the Gel Quickstart first, which walks through installing Gel, creating a simple schema, and writing some simple queries.
Where this client is the wrong choice
Two boundaries are worth stating plainly. The first is that this is a client for one database. It speaks the Gel protocol and it consumes the Gel schema model, so if your application talks to more than one datastore you will be running a second driver alongside it, and the query builder is useless for the other one. The second is the code generation dependency, which pulls a build step into your project. A generated query builder means the schema and the client types can drift unless the generation runs as part of your build, and the README's own repository layout shows how much machinery that involves, with a Turborepo pipeline, an integration-tests workspace, and separate typecheck, build, test, and lint tasks per package. If your team wants a thin wrapper over a SQL database with no code generation step, this is more machinery than the problem needs.
Editorial conclusion
gel-js fits a TypeScript team building on Gel that wants the query builder and generated query functions rather than hand-written string queries, and that wants a connection configuration that works in local development and in production without code changes. It is the wrong choice for a JavaScript project without TypeScript, since the typed generators are the main argument for it and the README requires TypeScript 4.4 or newer for that path, and it is the wrong choice if you need a driver for another database. Before you adopt it, read the query builder documentation, since the generated builder depends on the project layout and a schema, and note that the package name moved from edgedb to gel, so any existing imports need updating.
Frequently asked questions
How do I create a client with gel-js?
Import the package and call `gel.createClient()`, which takes no arguments in the common case. The library discovers the connection from a local project initialised with `gel project init`, or from the `GEL_DSN` environment variable, which has the form `gel://USERNAME:PASSWORD@HOSTNAME:PORT/DATABASE`.
What is the difference between query, querySingle, and queryRequiredSingle in gel-js?
The `.query()` method always returns an array regardless of the result cardinality. Use `.querySingle()` when the query returns zero or one elements, and `.queryRequiredSingle()` when it is guaranteed to return exactly one, since the inferred types differ and the compiler reports the difference.
How do I use the code generators in gel-js?
Install `@gel/generate` as a dev dependency with `npm install @gel/generate --save-dev`, then run `npx @gel/generate <generator> [FLAGS]`. The supported generators are `queries` for typed functions from `*.edgeql` files, `interfaces` for schema type interfaces, and `edgeql-js` for the query builder.
Where does the gel-js query builder get generated to?
Running `npx @gel/generate edgeql-js` writes the builder into the `./dbschema/edgeql-js` directory, as defined relative to your project root. The builder is then imported as a default export from that path and used to build a query whose return type is inferred.
What are the requirements for using gel-js?
Node.js 18 or newer, and TypeScript 4.4 or newer if you are a TypeScript user, which the README lists as required for TypeScript. The published npm package is named `gel`, and the repository workspace still uses `edgedb/*` directory paths for some packages.
Official sources
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.
[](https://hysenlabs.com/projects/geldata-gel-js)Was this useful?