question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RFC: `*.edgeql` workflow

See original GitHub issue

In addition to the current approach (reflecting EdgeQL and the EdgeDB typesystem into a query builder API), I propose a more GraphQL-like workflow.

*.edgeql files

Queries are written as plain EdgeQL inside *.edgeql files

// ./dbschema/queries/getUser.edgeql
select User {
  name, email
} filter .id = <uuid>$user_id

New npx command

An npx command that scans the project file tree for .edgeql files, reads the contents, and pings the database to retrieve type information about the queries’ result type and parameter types.

Candidates:

  • npx edgeql-js --generator queries: generates just queries
    • In this case npx edgeql-js --generator qb would generate the query builder and just npx edgeql-js would generate both
  • Move all generation code to a separate edbgen repo
    • For *.edgeql files: npx edbgen --generator edgeql
    • For QB: npx edbgen --generator querybuilder
    • Support community-written generators too

For each .edgeql file, a new file is generated with the following structure.

// ./dbschema/queries/getUser.ts
export type getUser = {name: string; email: string;}
export const getUser = {
  edgeql: `select User {
      name, email
    } filter .id = <uuid>$user_id`,
  run: async function(client: Client | Transaction, params: {id: string}){
    // this will be either query, querySingle, queryRequired, or queryRequiredSingle depending on the introspected result cardinality
    return client.querySingle<getUser>(this.edgeql, params);
  },
  runJSON: async function(client: Client | Transaction, params: {id: string}){
    return client.querySingleJSON(this.edgeql, params);
  }
}

The generated query can be consumed like so:

import {createClient} from "edgedb";
import {getUser} from "./dbschema/queries/getUser";

const client = createClient();
await getUser.run(client, {id: "abc..."});
// { name: "Jules", ... }

await getUser.runJSON(client, {id: "abc..."});

Watch mode

There would also be a --watch mode to re-generate whenever a .edgeql file is updated.

Target

The target (.ts vs .js vs .mjs) is still determined using the same resolution algorithm as the current npx edgeql-js command.

Output directory

The output directory can be specified with the --out-dir flag. The default is ./dbschema/queries directory, as resolved relative to the project root. If two query files share the same name, an error will be thrown.

Perhaps there should be a mode that generates the .ts/.js file alongside the corresponding *.edgeql file, wherever it may appear in the project file system. This similar to how tsc works by default; still, it’s messy and rarely used (most TS users use outDir) so it shouldn’t be our default behavior.

Index file for convenience

For convenience, an index.{j|t}s file should be generated into the dbschema/queries directory that re-exports all generated queries.

./dbschema/query/index.ts
export * from "./getUser";
export * from "./getMovies";
export * from "./searchMovies";

This makes it easier to import all queries with a single import.

import {createClient} from "edgedb";
import * from queries from "./dbschema/queries";

const client = createClient();
await queries.getUser.run(client, {id: "abc..."});

Benefits

  • Users can write plain EdgeQL, which is less verbose than the query builder, especially for shapes and operators.
  • Users don’t need to learn the equivalent query builder syntax for all EdgeQL operations
  • Many users are familiar with this workflow from GraphQL
  • Massive implementational simplification compared to the query builder: no headaches around TypeScript breakage, excessively deep, inference limitations, etc.

Cons

  • You have to run a watcher
  • No autocomplete or type checking until LSP lands
  • Your queries aren’t co-located with your code
  • No complex params types. In the query builder we allow arbitrarily complex param types ine.params. The values are automatically serialized to JSON client side, passed as a JSON param, and re-cast in the generated query. This makes it possible to pass complex, strongly-typed objects directly into .run which is a big win for mutations.
  • No select * (until it lands in EdgeQL). This isn’t implement yet in QB but will be.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:5
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
colinhackscommented, May 10, 2022

No autocomplete or type checking until LSP lands

I’m referring to the experience of writing the EdgeQL queries themselves in a *.edgeql file. Currently the IDE extensions we provide do highlighting but no autoformatting or autocompletion (they’re not schema-aware either).

But the generated client would certainly be strongly typed.

0reactions
i0bscommented, Aug 9, 2022

I’m earnestly for this, the proposed workflow here would make parsing and extrapolating the typings for schema infinitesimally easier. The only thing that concerns me, as @1st1 mentioned is flattening queries to one level

Read more comments on GitHub >

github_iconTop Results From Across the Web

Discussions · Pre Rfc - GitHub
Discuss a complex and elaborate proposals before writing an RFC. 1. You must be logged in to vote ... New dev workflow ......
Read more >
Get Started | EdgeDB Docs
It walks through EdgeDB's core workflows: how to install EdgeDB, create an instance, write a simple schema, execute a migration, write some simple...
Read more >
README.md - Create pdf from source files
There's a lot more to EdgeQL: a comprehensive standard library, compu ted properties, polymorphic queries, `with` blocks, transactions, and muc.
Read more >
lc
Net#21, this tool provides a way to create .cs files from .edgeql files. ... You can use the OAuth 2.0 client credentials grant...
Read more >
The official Node.js client library for EdgeDB - GithubHelp
JavaScript 2.44% TypeScript 97.56% edgedb edgeql database-driver high-performance ... and breaking changes, especially regarding the query builder workflow.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found