ext::auth::ClientTokenIdentity has wrong cardinality type and type does not exist error
Code
The code causing the error.
const query =
e.insert(e.User, {
name: "user",
identity: e.ext.auth.ClientTokenIdentity,
})
Schema
Your application schema.
using extension auth;
module default {
type User {
required name: str;
identity: ext::auth::Identity {
constraint exclusive;
};
}
}
Error or desired behavior
For identity in the e.insert() statement, Typescript complains about:
Type 'Cardinality.Many' is not assignable to type 'Cardinality.AtMostOne | Cardinality.One | Cardinality.Empty
Expected behavior: According to its definition, I think ClientTokenIdentity should have Cardinality.AtMostOne instead of Many:
<project>/dbschema/edgeql-js/modules/ext/auth.ts
const ClientTokenIdentity: $.$expr_PathNode<$.TypeSet<$ClientTokenIdentity, $.Cardinality.Many>, null> = _.syntax.$PathNode($.$toSet($ClientTokenIdentity, $.Cardinality.Many), null);
<gel-source>/edb/lib/ext/auth.edgeql
create single global ext::auth::ClientTokenIdentity := (
with
...
select
ext::auth::Identity
filter
.id = <uuid>json_get(jwt.claims, "sub")
);
Versions:
- OS: Linux
- EdgeDB version (e.g.
2.0): "6.2+e1a80a5" edgedb-jsversion (e.g.0.20.10;): [email protected]@edgedb/generateversion (e.g.0.0.7;): @gel/[email protected]- TypeScript version: [email protected]
- Node/Deno version: node v22.11.0
query.toEdgeQL() returns:
INSERT default::User {
name := "user",
identity := DETACHED ext::auth::ClientTokenIdentity
}
and running the query throws error:
object type or alias 'ext::auth::ClientTokenIdentity' does not exist
identity := DETACHED ext::auth::ClientTokenIdentity
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Hint: did you mean 'ext::auth::ClientTokenIdentity'?
I run the query after a successful OpenIDConnect login flow: A corresponding entry ext::auth::Identity is created.
A few things are off here, including a misleading error message on our part that I'll work in getting fixed with the compiler team:
Unless you are setting the ext::auth::client_token global, you will not have an ext::auth::ClientTokenIdentity, and depending on how you're working with this code, you're probably wanting to set it like this:
const query =
e.insert(e.User, {
name: "user",
identity: e.select(e.ext.auth.Identity, (i) => ({
filter_single: e.op(i.id, "=", identityId),
})),
});
// or better yet with UUID -> object casting which will throw an error if the Identity does not exists
const query =
e.insert(e.User, {
name: "user",
identity: e.cast(e.ext.auth.Identity, e.uuid(identityId)),
});
Where the identityId came from the token data you got when creating the identity.
The actual path to the ClientTokenIdentity global is: e.ext.auth.global.ClientTokenIdentity. This explains the query error, too: you were trying to address it as an object type, but it's a global. Two bugs there:
- we shouldn't expose module globals on the module namespace, only on the
module_name.globalnamespace - we should give you a better error message that implies that the syntax error is that you are missing
global. The query should read:
INSERT default::User {
name := "user",
identity := global ext::auth::ClientTokenIdentity
}
Thanks for the fast reply! Yes, I confirm that using e.ext.auth.global.ClientTokenIdentity fixes the insert query.
For anyone who stumbles across this, here are the docs for globals.