Code Monkey home page Code Monkey logo

edgedb-js's Introduction

EdgeDB

Stars license discord

Quickstart   •   Website   •   Docs   •   Playground   •   Blog   •   Discord   •   Twitter



What is EdgeDB?

EdgeDB is a new kind of database
that takes the best parts of
relational databases, graph
databases, and ORMs. We call it
a graph-relational database.



🧩 Types, not tables 🧩


Schema is the foundation of your application. It should be something you can read, write, and understand.

Forget foreign keys; tabular data modeling is a relic of an older age, and it isn't compatible with modern languages. Instead, EdgeDB thinks about schema the same way you do: as object types containing properties connected by links.

type Person {
  required name: str;
}

type Movie {
  required title: str;
  multi actors: Person;
}

This example is intentionally simple, but EdgeDB supports everything you'd expect from your database: a strict type system, indexes, constraints, computed properties, stored procedures...the list goes on. Plus it gives you some shiny new features too: link properties, schema mixins, and best-in-class JSON support. Read the schema docs for details.


🌳 Objects, not rows 🌳


EdgeDB's super-powered query language EdgeQL is designed as a ground-up redesign of SQL. EdgeQL queries produce rich, structured objects, not flat lists of rows. Deeply fetching related objects is painless...bye, bye, JOINs.

select Movie {
  title,
  actors: {
    name
  }
}
filter .title = "The Matrix"

EdgeQL queries are also composable; you can use one EdgeQL query as an expression inside another. This property makes things like subqueries and nested mutations a breeze.

insert Movie {
  title := "The Matrix Resurrections",
  actors := (
    select Person
    filter .name in {
      'Keanu Reeves',
      'Carrie-Anne Moss',
      'Laurence Fishburne'
    }
  )
}

There's a lot more to EdgeQL: a comprehensive standard library, computed properties, polymorphic queries, with blocks, transactions, and much more. Read the EdgeQL docs for the full picture.


🦋 More than a mapper 🦋


While EdgeDB solves the same problems as ORM libraries, it's so much more. It's a full-fledged database with a powerful and elegant query language, a migrations system, a suite of client libraries in different languages, a command line tool, and—coming soon—a cloud hosting platform. The goal is to rethink every aspect of how developers model, migrate, manage, and query their database.

Here's a taste-test of EdgeDB's next-level developer experience: you can install our CLI, spin up an instance, and open an interactive EdgeQL shell with just three commands.

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
$ edgedb project init
$ edgedb
edgedb> select "Hello world!"

Windows users: use this Powershell command to install the CLI.

PS> iwr https://ps1.edgedb.com -useb | iex

Get started

To start learning about EdgeDB, check out the following resources:

  • The quickstart. If you're just starting out, the 10-minute quickstart guide is the fastest way to get up and running.
  • EdgeDB Cloud 🌤️. The best most effortless way to host your EdgeDB database in the cloud.
  • The interactive tutorial. For a structured deep-dive into the EdgeQL query language, try the web-based tutorial— no need to install anything.
  • The e-book. For the most comprehensive walkthrough of EdgeDB concepts, check out our illustrated e-book Easy EdgeDB. It's designed to walk a total beginner through EdgeDB in its entirety, from the basics through advanced concepts.
  • The docs. Jump straight into the docs for schema modeling or EdgeQL!

Contributing

PRs are always welcome! To get started, follow this guide to build EdgeDB from source on your local machine.

File an issue 👉
Start a Discussion 👉
Join the discord 👉


License

The code in this repository is developed and distributed under the Apache 2.0 license. See LICENSE for details.

edgedb-js's People

Contributors

1st1 avatar aarongeorge avatar ambv avatar andreasthoelke avatar beerose avatar carsonf avatar colinhacks avatar dhghomon avatar diksipav avatar dlee avatar drewradcliff avatar ediskandarov avatar elprans avatar escwxyz avatar fmoor avatar freeatnet avatar ggallon avatar jaclarke avatar kfrp avatar miroslavpetrik avatar nicu-chiciuc avatar nurbekgithub avatar pastelstoic avatar progrestian avatar raddevon avatar robertoprevato avatar scotttrinh avatar sikarii avatar tailhook avatar vpetrovykh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

edgedb-js's Issues

Possible buffer allocation bug?

Shouldn't __realloc also set this.size = newSize?

edgedb-js/src/buffer.ts

Lines 59 to 71 in 99f558c

private ensureAlloced(extraLength: number): void {
const newSize: number = this.pos + extraLength;
if (newSize > this.size) {
this.__realloc(newSize);
}
}
private __realloc(newSize: number): void {
newSize += BUFFER_INC_SIZE;
const newBuffer = Buffer.allocUnsafe(newSize);
this.buffer.copy(newBuffer, 0, 0, this.pos);
this.buffer = newBuffer;
}

Otherwise subsequent reuse would reallocate and copy all over again, even though there's actually enough buffer, it's just not reflected in this.size?

edgedb-js doesn't pick up environment variable EDGEDB_DATABASE

It would be nice to be able to EDGEDB_DATABASE=test npm start and the client would use the database passed instead of the default one.

That would be aligned with the behaviour of edgedb cli and would cause no surprises since the user added the env. variable explicitly.

See discussion edgedb/edgedb#2902

That's just a nice to have, because it can actually work like this: createPool({database:process.env.EDGEDB_DATABASE}) and would default to the default db if the env. variable is undefined

Deprecate createPool() in favor of synchronous lazy createClient()

createPool already functions as an implicit pool: there are no explicit acquire and release calls anymore. Turning the pool constructor into a synchronous function call, which doesn't attempt connections right away, will make it possible to safely declare and initialize the EdgeDB connection as a global variable. There should also be an ensureConnected() method to perform a connection attempt if the client has no active connections yet.

Running test doesn't seem to work

I'm running the latest Nightly version on Ubuntu 18

Running tests doesn't seem to be working. Is there something i need to configure before running tests?

I already have edgedb installed.

Typing inference wrong on inserts

It seems that an insert is showing as a type of many. This makes it impossible to chain with a conflict else.

The error:
the query has cardinality MANY which does not match the expected cardinality ONE

https://github.com/busheezy/edgedb-upsert-type-inference-error/blob/main/src/index.ts#L9
I have made an example repo. You can run npm run rebuild:db to create everything.

https://share.busheezy.dev/wrlepR.png

Thanks to @elprans for the quick reply on discord.

Thanks for the cool new toys!

Functions with optional param decrease cardinality lowerbound

This is currently an error

  e.update(e.Movie, movie => ({
    filter: e.op(movie.title[0], '=', ' '),
    set: {
      title: e.str_trim(movie.title)
    }
  }))

Because e.str_trim(movie.title) has cardinality Cardinality.One | Cardinality.AtLeastOne even though movie.title has cardinality One. It has to do with the fact that we multiply the cardinalities of the first arg and the optional second arg.

Filtering scalars seems broken.

It seems to be the case that filtering scalars is impossible. Trying to do the equivalent to:

edgedb> select _ := Hero.name filter _ like 'The%';
{'The Wasp', 'The Falcon', 'The Hulk', 'Thena'}

Attempting something like:

  const QUERY = e.select(e.Hero.name, (el) => ({
      filter: e.like(el, e.str('The%')),
  }));

Results in:

 $ yarn play
yarn run v1.22.10
$ tsc --incremental && node dist/index.js
index.ts:40:26 - error TS2769: No overload matches this call.
  Overload 1 of 5, '(expr: ObjectTypeExpression, shape: (scope: { __element__: ObjectType<string, ObjectTypePointers, any>; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<...>) => Readonly<...>): $expr_Select<...>', gave the following error.
    Argument of type '{ __element__: $str; __cardinality__: Cardinality.Many; __kind__: ExpressionKind.PathLeaf; __parent__: { type: { __element__: $Hero; __cardinality__: Cardinality.Many; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: boolean; } & ExpressionMethods<...> & { ...; }; linkName: "name"; }; __exclusive_...' is not assignable to parameter of type 'ObjectTypeExpression'.
      Types of property '__element__' are incompatible.
        Type 'ScalarType<"std::str", string, string>' is missing the following properties from type 'ObjectType<string, ObjectTypePointers, any>': __pointers__, __shape__
  Overload 2 of 5, '(expr: ObjectTypeExpression, shape: (scope: { __element__: ObjectType<string, ObjectTypePointers, any>; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<...>) => TypeSet<...>): $expr_Select<...>', gave the following error.
    Argument of type '{ __element__: $str; __cardinality__: Cardinality.Many; __kind__: ExpressionKind.PathLeaf; __parent__: { type: { __element__: $Hero; __cardinality__: Cardinality.Many; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: boolean; } & ExpressionMethods<...> & { ...; }; linkName: "name"; }; __exclusive_...' is not assignable to parameter of type 'ObjectTypeExpression'.

40   const QUERY = e.select(e.Hero.name, (el) => ({
                            ~~~~~~~~~~~

  dbschema/edgeql/syntax/select.ts:510:17
    510 export function select(...args: any[]) {
                        ~~~~~~
    The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.

index.ts:40:40 - error TS7006: Parameter 'el' implicitly has an 'any' type.

40   const QUERY = e.select(e.Hero.name, (el) => ({
                                          ~~


Found 2 errors.

error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I think the same problem arises when applying limit or offset to scalars, too.

This appears to be related to #220

[Help-wanted] SCRAM-SHA-256 Authentication Failed.

Hi,

I am trying to connect to the edgeDB instance, but the connection fails Authentication Failed.

I have a windows system and have installed edgedb by docker. Following is the command that was used to spawn an edgedb instance.

edgedb server init test2 --port 5658 --default-user edgedb --default-database edgedb

image

Now I tried to connect to this instance using js binding but failed with an error authentication failure. The authentication method used here is SHA-SCRAM-256.

The js-binding is able to send ClientFinal message which is AuthenticationSASLResponse here. Following is the stack trace from the server.

value=Traceback (most recent call last):
  File "edb/server/protocol/binary.pyx", line 1615, in edb.server.protocol.binary.EdgeConnection.main
  File "edb/server/protocol/binary.pyx", line 387, in auth
  File "edb/server/protocol/binary.pyx", line 643, in _auth_scram
edb.errors.AuthenticationError: authentication failed

The usecase here is that I am trying to add the SCRAM-SHA-256 authentication to Java binding. Please help.

Also, I observed that even though we provide the --port parameter while initiating an instance, it does not reflect. In the given example, the port parameter passed is 5658 and the instance is spawned on 10703. It uses the next available port starting from 10700. Docker internal port is always 5656, thus could not understand the use of --port param.

Fetch api lacks a method to fetch an optional single object

The AwaitConnection from "edgedb/dist/src/client" exposes the following methods to fetch items:

  • fetchOne
  • fetchOneJSON
  • fetchAll
  • fetchAllJSON

image

The fetchOne method throws exception if a filter produces no results:

Error: query returned no data

Because internally it is configured with a flag expectOne set to true:

image

However, it often happens to desire to fetch an optional object. In simple words: "fetch the first item of the query, or nothing if none is found".

For example, in .NET System.Linq implements these two methods:

collection.First(item => item.Id == "example");    
// this throws exception if the call produces no result, because the collection 
// is expected to have at least one matching item

collection.FirstOrDefault<T>(item => item.Id == "example");   
// this returns the first matching item, or default(T), which in most circumstances 
// is `null`

As a side note, it also exposes methods that cause exception if the collection contains more than one matching item by predicate:

  • .Single(Func<TSource,Boolean> predicate) -> TSource
  • .SingleOrDefault(Func<TSource,Boolean> predicate) -> TSource or default(TSource)

A consequence of the missing API, considering that exceptions are expensive in JavaScript, is that for optional items we need to fetch a list of items, and then read the first element of the list.

For example:

    const items = await connection.fetchAll(
      `SELECT Foo {
        name
        creation_time
      }  FILTER .id = <uuid>$id;`,
      {
        id: fooId
      }
    )

    if (!items.length)
      // foo not found
      return null;
  
  return items[0];

Proposal:

  • enable overriding the parameter expectOne in the fetchOne signature,
  • or, include a function like: fetchOneOrNull,
  • or, a function like: fetchOneOrDefault, e.g:
  async fetchOneOrDefault(
    query: string, 
    args: QueryArgs = null, 
    default: any = null
  ): Promise<any> {
    this._enterOp();
    try {
       const items = await this._fetch(query, args, false, false);
       return items.length ? items[0] : default;
    } finally {
      this._leaveOp();
    }
  }

readme of edgedb-js

  • EdgeDB Version: alpha5
  • OS Version: ubuntu

Steps to Reproduce: as described in https://github.com/edgedb/edgedb-js

Here's what the readme says:
const conn = await edgedb.connect({
user: "edgedb",
host: "127.0.0.1",
});

then I get the following warning:
options as the first argument to edgedb.connect is deprecated, use edgedb.connect('instance_name_or_dsn', options)

=> example in the npm package is not updated

not a big deal, just concerns the readme, but since it's the first thing a newcomer must do, it's worthwhile to have that uptodate

see my basic example https://github.com/fimbault/test_edgedb_js

NOTE : I've seen https://edgedb.com/blog/edgedb-1-0-alpha-5-luhman#simplified-administration-with-named-instances (to pass the instance name only) but couldn't make it to work.

Ordering is broken for some basic cases

The examples use "heroes" repo.

In EdgeQL it is possible to do the following:

edgedb> select _ := {2, 0, 1} order by _;
{0, 1, 2}
edgedb> select Hero{name} order by Hero;
{
  default::Hero {name: 'The Wasp'},
  default::Hero {name: 'Captain America'},
  default::Hero {name: 'Iron Man'},
  default::Hero {name: 'The Hulk'},
  default::Hero {name: 'Hawkeye'},
  default::Hero {name: 'Spider-Man'},
  default::Hero {name: 'Black Widow'},
  default::Hero {name: 'Thor'},
  default::Hero {name: 'Ant-Man'},
  default::Hero {name: 'Doctor Strange'},
  default::Hero {name: 'Cersi'},
  default::Hero {name: 'Ikaris'},
  default::Hero {name: 'Thena'},
  default::Hero {name: 'Gilgamesh'},
  default::Hero {name: 'The Falcon'},
}

Basically it is always possible to order by the element itself, which is indispensable for scalar values, often useful for collections and sometimes useful for objects (simply to guarantee a stable ordering, even if appearing somewhat random because it's actually equivalent to order by .id).

The following don't appear to work:

  const QUERY = e.select(e.set(e.int64(2), e.int64(0), e.int64(1)), (el) => ({
      order: el
  }));
$ yarn play
yarn run v1.22.10
$ tsc --incremental && node dist/index.js
index.ts:40:26 - error TS2769: No overload matches this call.
  Overload 1 of 5, '(expr: ObjectTypeExpression, shape: (scope: { __element__: ObjectType<string, ObjectTypePointers, any>; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<...>) => Readonly<...>): $expr_Select<...>', gave the following error.
    Argument of type '{ __element__: ScalarType<"std::int64", number, 1>; __cardinality__: Cardinality.AtLeastOne; __exprs__: (getSetTypeFromExprs<[{ __element__: ScalarType<"std::int64", number, 2>; __cardinality__: Cardinality.One; __kind__: ExpressionKind.Literal; __value__: any; } & ExpressionMethods<...>, { ...; } & ExpressionMethod...' is not assignable to parameter of type 'ObjectTypeExpression'.
      Types of property '__element__' are incompatible.
        Type 'ScalarType<"std::int64", number, 1>' is missing the following properties from type 'ObjectType<string, ObjectTypePointers, any>': __pointers__, __shape__
  Overload 2 of 5, '(expr: ObjectTypeExpression, shape: (scope: { __element__: ObjectType<string, ObjectTypePointers, any>; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<...>) => TypeSet<...>): $expr_Select<...>', gave the following error.
    Argument of type '{ __element__: ScalarType<"std::int64", number, 1>; __cardinality__: Cardinality.AtLeastOne; __exprs__: (getSetTypeFromExprs<[{ __element__: ScalarType<"std::int64", number, 2>; __cardinality__: Cardinality.One; __kind__: ExpressionKind.Literal; __value__: any; } & ExpressionMethods<...>, { ...; } & ExpressionMethod...' is not assignable to parameter of type 'ObjectTypeExpression'.

40   const QUERY = e.select(e.set(e.int64(2), e.int64(0), e.int64(1)), (el) => ({
                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  dbschema/edgeql/syntax/select.ts:510:17
    510 export function select(...args: any[]) {
                        ~~~~~~
    The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.

index.ts:40:70 - error TS7006: Parameter 'el' implicitly has an 'any' type.

40   const QUERY = e.select(e.set(e.int64(2), e.int64(0), e.int64(1)), (el) => ({
                                                                        ~~


Found 2 errors.

error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Now for the object:

  const QUERY = e.select(e.Hero, (el) => ({
      order: el
  }));
$ yarn play

yarn run v1.22.10
$ tsc --incremental && node dist/index.js
^[[Aindex.ts:40:17 - error TS2769: No overload matches this call.
  Overload 1 of 5, '(expr: { __element__: $Hero; __cardinality__: Cardinality.Many; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<{ __element__: $Hero; __cardinality__: Cardinality.Many; }> & { ...; }, shape: (scope: { ...; } & ... 1 more ... & { ...; }) => Readonly<...>): $expr_Select<...>', gave the following error.
    Type '{ __element__: $Hero; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<{ __element__: $Hero; __cardinality__: Cardinality.One; }> & { ...; }' is not assignable to type 'OrderByExpression | undefined'.
      Type '{ __element__: $Hero; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<{ __element__: $Hero; __cardinality__: Cardinality.One; }> & { ...; }' is not assignable to type 'OrderByExpr'.
        Types of property '__element__' are incompatible.
          Type 'ObjectType<"default::Hero", { id: PropertyDesc<$uuid, Cardinality.One, true, false>; __type__: LinkDesc<$Type, Cardinality.One, {}, false, false>; ... 7 more ...; "<nemesis": LinkDesc<...>; }, null>' is missing the following properties from type 'ScalarType<string, any, any>': __tstype__, __tsconsttype__
  Overload 2 of 5, '(expr: { __element__: $Hero; __cardinality__: Cardinality.Many; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<{ __element__: $Hero; __cardinality__: Cardinality.Many; }> & { ...; }, shape: (scope: { ...; } & ... 1 more ... & { ...; }) => TypeSet<...>): $expr_Select<...>', gave the following error.
    Type '{ order: { __element__: $Hero; __cardinality__: Cardinality.One; __parent__: null; __kind__: ExpressionKind.PathNode; __exclusive__: true; } & ExpressionMethods<{ __element__: $Hero; __cardinality__: Cardinality.One; }> & { ...; }; }' is missing the following properties from type 'TypeSet<BaseType, Cardinality>': __element__, __cardinality__

40   const QUERY = e.select(e.Hero, (el) => ({
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
41       order: el
   ~~~~~~~~~~~~~~~
42   }));
   ~~~~~

  dbschema/edgeql/syntax/select.ts:74:3
    74   order?: OrderByExpression;
         ~~~~~
    The expected type comes from property 'order' which is declared here on type 'Readonly<pointersToSelectShape<{ id: PropertyDesc<$uuid, Cardinality.One, true, false>; __type__: LinkDesc<$Type, Cardinality.One, {}, false, false>; ... 7 more ...; "<nemesis": LinkDesc<...>; }>>'
  dbschema/edgeql/syntax/select.ts:490:10
    490   shape: (scope: $scopify<Expr["__element__"]>) => Set
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The expected type comes from the return type of this signature.
  dbschema/edgeql/syntax/select.ts:510:17
    510 export function select(...args: any[]) {
                        ~~~~~~
    The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.


Found 1 error.

error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Update the warning on Deno in the context of using edgedb-cli to start and stop EdgeDB instances

https://github.com/edgedb/edgedb-deno#tls

I really don't understand what value should the environment variable have (is true? is yes? a truthy value will do the trick?)

There is nothing about --allow-insecure-binary-clients in edgedb instance start --help

❯ edgedb instance start --help
edgedb-instance-start

Start an instance

USAGE:
    edgedb instance start [FLAGS] <name>

ARGS:
    <name>    Name of the instance to start

FLAGS:
        --foreground    Start the server in the foreground rather than using systemd to
                        manage the process (note: you might need to stop non-foreground
                        instance first)
    -h, --help          Prints help information

the documentation on environment variables is lacking in general (regarding where to set them, what will they affect in the context of edgedb-cli, what values they must have, etc)

Set db to use

Hello, according to this documention we should use the following command to change the current db:

\c tutorial

However I cannot find how to change the current db with the JS client without create a new connection.

I came up with this but it complains that \ is not expected:

const EdgeClient = require('./EdgeClient');
let c = new EdgeClient({
  user: 'edgedb',
  host: '127.0.0.1',
});
c.getConnection().then((c) => {
  const r = c.execute(`\\c tutorial`).then((r) => {
    console.log(r);
  });
});
```

Thanks

Are arrays valid values in query arguments?

I'm trying to run a query that contains a set as an argument, for example:

await conn.fetchAll(`
  # This query works
  SELECT schema::ObjectType { id, name }
  FILTER .id IN <uuid>{
    '00000000-0000-0000-0000-000000000001',
    '00000000-0000-0000-0000-000000000002'
  };
  # Replacing the filter expression to use a query argument (as either below) doesn't work
  # FILTER .id IN <uuid>$tids
  # FILTER .id IN <uuid>{$tids}
`, {
    tids: ['00000000-0000-0000-0000-000000000001',
           '00000000-0000-0000-0000-000000000002']
  }
)

Are arrays not accepted as query argument values (the examples in the docs only show scalar types), or this not the correct syntax?

Connecting to a starting EdgeDB server will stop without throwing

Steps to reproduce:

  1. Create a js script that connects to EdgeDB:
const edgedb = require('edgedb');

async function main() {
  try {
    let c = await edgedb.connect({
      user: 'edgedb',
      host: '127.0.0.1',
    });
    console.log('connected');
  } catch (e) {
    console.error('caught', e);
  }
}

main();
  1. Launch edgedb server (I used docker version).
  2. Run the js script above before the server is fully launched

Actual result

Script stops

Expected result

An error should be caught

"unexpected message" error when queries run concurrently

const edgedb = require("edgedb")

async function main() {
  const conn = await edgedb.connect({
    // connection config
  })

  try {

    console.log( await conn.fetchAll(`SELECT sys::get_version()`) )
    // Set [ NamedTuple [ major := 1, minor := 0, stage := 'alpha', stage_no := 2, local := [ 'dev', '535', 'gbd7bd5fd' ] ] ]
    console.log( await conn.fetchAll(`SELECT sys::get_version_as_str()`) )
    // Set [ '1.0-alpha.2+dev.535.gbd7bd5fd' ]

    console.log(
      await Promise.all([
        conn.fetchOne(`SELECT sys::get_version()`),
        conn.fetchOne(`SELECT sys::get_version_as_str()`)
      ])
    )
    // Error: unexpected message type 49 ("1")
    //  at AwaitConnection._fallthrough (#################\node_modules\edgedb\dist\src\client.js:244:23)
    //  at AwaitConnection._execute (#################\node_modules\edgedb\dist\src\client.js:536:26)
    //  at process._tickCallback (internal/process/next_tick.js:68:7)

  } finally {
    await conn.close()
  }
}

main()

createClient API

To-Do (must have before rc2):

  • Introduce the new createClient() function. The function immediately returns a Client instance which is essentially a Pool but with no connection actually established.
  • The new Client class can reuse most of the implementation of the Pool class.
  • createClient should accept a concurrency option (mixed in with other connection options). By default concurrency is not set to anything. (concurrency is similar to Pool's maxSize; there's no minSize equivalent in the createClient API, the minSize for clients is 0.)
  • The underlying connection object should listen to a setting message from the server called suggested_pool_size. If a client was created without concurrency being explicitly set, the actual concurrency level will be set to what suggested_pool_size parameter says. Essentially, if the concurrency is set to N, then the Client should reserve N connection holders; if it wasn't specified, the Client implementation should sniff the value of suggested_pool_size on the first established connection and then add the required number of connection holders.
  • The underlying sockets should be unrefed.
  • There should be an ensureConnected method on the client. If there is at least one already connected connection it should immediately return. If there are 0 established internal connections the method should try establishing a connection.
  • Documentation of the new API.
  • Update .withRetryOptions and .withTransactionOptions to accept config objects with optional keys
  • withRetryOptions should accept a JS object literal

To-Do (can ship after rc2):

  • Fix the code path that handles network errors
  • Make sure retryingTransaction() API repeats on network erorrs
  • Repeat read-only statements automatically

Tuples with a single element produce incorrect EdgeQL/result.

This is using the "heroes" repo, but I don't think that matters since this is reproducible with a literal.

const QUERY = e.select(e.tuple([e.int64(0)]));

Produces the following EdgeQL (as given by QUERY.toEdgeQL()):

SELECT ((
  0
))

And the following result (as given by console.log(JSON.stringify(result, null, 2));):

0

Contrast this with a 2-tuple

const QUERY = e.select(e.tuple([e.int64(0), e.int64(1)]));

EdgeQL:

SELECT ((
  0,
  1
))

Output:

[
  0,
  1
]

... or an array with one element:

const QUERY = e.select(e.array([e.int64(0)]));

EdgeQL:

SELECT ([
  0
])

Output:

[
  0
]

Finally, using an expression gives us this:

const QUERY = e.select(e.tuple([e.Hero.name]));

EdgeQL:

SELECT ((
  DETACHED default::Hero.name
))

Output:

[
  "Spider-Man",
  "Thor",
  "Ant-Man",
  "The Wasp",
  "The Falcon",
  "Black Widow",
  "The Hulk",
  "Doctor Strange",
  "Hawkeye",
  "Iron Man",
  "Ikaris",
  "Thena",
  "Gilgamesh",
  "Captain America",
  "Cersi"
]

A generic solution to this would be to always use a trailing comma in the generated EdgeQL for tuples: (0,) or (Hero.name, Hero.secret_identity,).

This is not an issue with named tuples because they are unambiguous even without a trailing comma, e.g. (x: 0).

Nest.js import troubles

Trying import e from '../dbschema/edgeql-js/index'; causes my nest project to never build.

tsconfig.build.json

{
  "extends": "./tsconfig.json",
  "exclude": ["node_modules", "test", "dist", "**/*spec.ts", "dbschema"]
}

tsconfig.json


{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false,
    "strict": true,
    "downlevelIteration": true,
  }
}

nest-cli.json

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src"
}

I have a feeling I'm missing something simple with this...
Thoughts?

createPool options typings

Typescript complains about this when specifying connection option database in createPool even though it actually works.

Argument of type '{ database: string; }' is not assignable to parameter of type 'PoolOptions'.
  Object literal may only specify known properties, and 'database' does not exist in type 'PoolOptions'.

assert_single strips away shape

Consider the following query:

  const userQuery = e
    .select(e.User, (user) => ({
      id: true,
      username: true,
      email: true,
      firstname: true,
      lastname: true,
      nickname: true,
      filter: e.op(user.username, "=", username)
    }))
    .assert_single();

The return value for this is a single object, rather than a set. However, the shape is completely ignored when using assert_single and only the id is returned.

Expected behavior should be to keep the shape.
Is there a different way to do get a single value back?

`Failed to resolve import "edgedb.js"` when targeting esm

npx edgeql-js --target esm
svelte-kit dev
10:22:44 AM [vite] Error when evaluating SSR module /Users/mark/src/Careswitch/platform/src/routes/index.ts:
Error: Failed to resolve import "edgedb.js" from "dbschema/edgeql-js/index.mjs". Does the file exist?

If I manually go into dbschema/edgeql-js/index.mjs and do the following replace everything appears to work as expected:

// Old
export { createClient } from "edgedb.js";

// New
export { createClient } from "edgedb";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.