Generation
The query builder is auto-generated by introspecting the schema of your database.
Initialize a project
When developing locally, we recommend initializing an EdgeDB project for your application. Follow the Quickstart for detailed instructions on installing the CLI, initializing a project, writing a basic schema, and executing your first migration.
Install the JavaScript client library
Install the edgedb
package from NPM.
$
npm install edgedb # npm users
$
yarn add edgedb # yarn users
Generate the query builder
Generate the query builder with the following command.
$
npx edgeql-js # npm users
$
yarn edgeql-js # yarn users
You’ll see something similar to this. (The first line will differ depending on whether you are using TypeScript or plain JavaScript.)
$
npx edgeql-js
Detected tsconfig.json, generating TypeScript files.
To override this, use the --target flag.
Run `npx edgeql-js --help` for details.
Generating query builder into ./dbschema/edgeql-js
Connecting to EdgeDB instance...
Introspecting database schema...
Generation successful!
Important. The npx edgeql-js
establishes a connection to your database, introspects the current schema, and generates a bunch of files. It does not simply read your local .esdl
files. You must create and apply migrations to your development database before running npx edgeql-js
.
Generating the query builder requires establishing a connection to an active EdgeDB instance. Remember that object types can contain computed fields that correspond to arbitrary EdgeQL queries. It isn’t possible to determine the type and cardinality of these queries without implementing a full EdgeQL parser and static analyzer in JavaScript, which is not on our roadmap (to put it lightly!). As such, we rely on the existence of an active EdgeDB instance containing the target schema.
By default, npx edgeql-js
generated files into the ./dbschema/edgeql-js
directory, as defined relative to your project root. The project root is identified by scanning up the file system for a package.json
.
Connection issue?
This command must be able to connect to a running EdgeDB instance. If you’re using edgedb project init
, this is automatically handled for you. Otherwise, you’ll need to explicitly pass connection information, just like any other CLI command. See Client Libraries > Connection for guidance.
Targets
The generation command looks at your environment and guesses what kind of files to generate (.ts
vs .js + .d.ts
) and what module system to use (CommonJS vs ES modules). You can override this with the --target
flag.
| Generate TypeScript files (.ts) |
| Generate TypeScript files (.mts) with extensioned ESM imports |
| Generate |
| Generate JavaScript with CommonJS syntax and and |
Version control
The first time you run the command, you’ll be prompted to add the generated files to your .gitignore
. Confirm this prompt, and a line will be automatically added to your .gitignore
to exclude the generated files from Git.
$ npx edgeql-js
...
Checking the generated query builder into version control
is NOT RECOMMENDED. Would you like to update .gitignore to ignore
the query builder directory? The following line will be added:
dbschema/edgeql-js
[y/n] (leave blank for "y")
For consistency, we recommend omitting the generated files from version control and re-generating them as part of your deployment process. However, there may be circumstances where checking the generated files into version control is desirable, e.g. if you are building Docker images that must contain the full source code of your application.
Importing
Once the query builder is generated, it’s ready to use! We recommend importing the query builder as a single default import called e
.
// TypeScript
import e from "./dbschema/edgeql-js";
// TypeScript with ESM
// JavaScript (CommonJS)
const e = require("./dbschema/edgeql-js");
// JavaScript (ES modules)
import e from "./dbschema/edgeql-js/index.mjs";
If you’re using ES modules, remember that imports require a file extension. The rest of the documentation assumes you are using TypeScript-style (extensionless) import
syntax.
Here’s a full “Hello world” example.
import * as edgedb from "edgedb";
import e from "./dbschema/edgeql-js";
const client = edgedb.createClient();
async function run(){
// declare a simple query
const myQuery = e.str("Hello world!");
// execute the expression
const result = await myQuery.run(client);
// print the result
console.log(result); // "Hello world!"
}
The generation command is configurable in a number of ways.
--output-dir <path>
Sets the output directory for the generated files.
--target <ts|cjs|esm|mts>
What type of files to generate. Documented above.
--force-overwrite
To avoid accidental changes, you’ll be prompted to confirm whenever the --target
has changed from the previous run. To avoid this prompt, pass --force-overwrite
.
-h/--help
Prints full documentation.
The generator also supports all the connection flags supported by the EdgeDB CLI. These aren’t necessary when using a project or environment variables to configure a connection.
Naming conflicts
Certain link/property names will create conflicts with parts of the query builder API. Avoid using the following names in your schema.
filter
order_by
limit
offset
run
is
index
slice
destructure
Generated interfaces
While the e
object is all that’s required to build queries, npx edgeql-js
also generates TypeScript interfaces
representing your current schema. These are not needed to construct queries, but are generated as a convenience.
import e, {Person, Movie} from "./dbschema/edgeql-js";
Given this EdgeDB schema:
module default {
scalar type Genre extending enum<Horror, Comedy, Drama>;
type Person {
required property name -> str;
}
type Movie {
required property title -> str;
property genre -> Genre;
multi link actors -> Person;
}
}
The following interfaces will be generated (simplified for clarify):
enum Genre {
Horror = "Horror",
Comedy = "Comedy",
Drama = "Drama"
}
interface Person {
id: string;
name: string;
}
interface Movie {
id: string;
title: string;
genre?: Genre | null;
actors: Person[];
}
Any types declared in a non-default
module will be generated into an accordingly named namespace
.