From 12f80bd28dbcb2f8b5fcab3946625b9e404a4108 Mon Sep 17 00:00:00 2001 From: Carson Full Date: Fri, 17 Nov 2023 17:25:50 -0600 Subject: [PATCH 1/2] Update edgedb query builder generation to allow referencing a default module type or module with the same name Essentially `e.User` or `e.User.Status` This is more consistent with what EdgeQL allows --- src/core/edgedb/generator/query-builder.ts | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/core/edgedb/generator/query-builder.ts b/src/core/edgedb/generator/query-builder.ts index 0ed62338c0..623b61f53f 100644 --- a/src/core/edgedb/generator/query-builder.ts +++ b/src/core/edgedb/generator/query-builder.ts @@ -24,6 +24,7 @@ export async function generateQueryBuilder({ changeCustomScalars(qbDir); changeImplicitIDType(qbDir); allowOrderingByEnums(qbDir); + mergeDefaultTypesWithModuleNames(qbDir); } function addJsExtensionDeepPathsOfEdgedbLibrary(qbDir: Directory) { @@ -72,3 +73,29 @@ function allowOrderingByEnums(qbDir: Directory) { .setType('TypeSet'); file.fixMissingImports(); } + +function mergeDefaultTypesWithModuleNames(qbDir: Directory) { + const file = qbDir.getSourceFileOrThrow('index.ts'); + const st = file.getVariableDeclarationOrThrow('ExportDefault'); + const typeText = st.getTypeNodeOrThrow().getFullText(); + const value = st.getInitializerIfKindOrThrow( + SyntaxKind.ObjectLiteralExpression, + ); + // Regex is faster here than ts-morph type parsing + const conflicting = ( + typeText.match(/Omit/)?.[1].split(/ \| /g) ?? [] + ).map((s) => s.slice(1, -1)); + let newTypeText = typeText; + for (const name of conflicting) { + newTypeText = newTypeText.replace( + `typeof _${name}`, + `typeof _${name} & typeof _default.${name}`, + ); + value + .getPropertyOrThrow(`"${name}"`) + .asKindOrThrow(SyntaxKind.PropertyAssignment) + .getInitializerOrThrow() + .replaceWithText(`{ ..._${name}, ..._default.${name} }`); + } + st.setType(newTypeText); +} From 12637e75e19f24d734bab55133fa447c61b4230c Mon Sep 17 00:00:00 2001 From: Carson Full Date: Fri, 17 Nov 2023 17:27:40 -0600 Subject: [PATCH 2/2] Drop default module reference in query builder usage now that we don't need it --- .../authentication.edgedb.repository.ts | 12 +++++------ src/components/user/user.edgedb.repository.ts | 20 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/authentication/authentication.edgedb.repository.ts b/src/components/authentication/authentication.edgedb.repository.ts index aff03c19f2..3bcf86eab1 100644 --- a/src/components/authentication/authentication.edgedb.repository.ts +++ b/src/components/authentication/authentication.edgedb.repository.ts @@ -20,7 +20,7 @@ export class AuthenticationEdgeDBRepository } async getRootUserId() { - const query = e.assert_exists(e.select(e.default.RootUser).assert_single()); + const query = e.assert_exists(e.select(e.RootUser).assert_single()); const result = await this.db.run(query); return result.id; } @@ -31,7 +31,7 @@ export class AuthenticationEdgeDBRepository } async savePasswordHashOnUser(userId: ID, passwordHash: string) { - const user = e.select(e.default.User, () => ({ + const user = e.select(e.User, () => ({ filter_single: { id: userId }, })); const query = e @@ -61,7 +61,7 @@ export class AuthenticationEdgeDBRepository async connectSessionToUser(input: LoginInput, session: Session): Promise { const user = e.assert_exists( { message: 'User not found' }, - e.select(e.default.User, () => ({ + e.select(e.User, () => ({ filter_single: { email: input.email }, })), ); @@ -101,7 +101,7 @@ export class AuthenticationEdgeDBRepository scopedRoles: withScope('global', user.roles), }), impersonatee: e.assert_single( - e.select(e.default.User, (user) => ({ + e.select(e.User, (user) => ({ scopedRoles: withScope('global', user.roles), filter: e.op(user.id, '=', impersonateeId ?? e.cast(e.uuid, e.set())), })), @@ -116,7 +116,7 @@ export class AuthenticationEdgeDBRepository } async rolesForUser(userId: ID) { - const query = e.select(e.default.User, (user) => ({ + const query = e.select(e.User, (user) => ({ scopedRoles: withScope('global', user.roles), filter_single: { id: userId }, })); @@ -145,7 +145,7 @@ export class AuthenticationEdgeDBRepository } async userByEmail(email: string) { - const query = e.select(e.default.User, () => ({ + const query = e.select(e.User, () => ({ filter_single: { email }, })); const result = await this.db.run(query); diff --git a/src/components/user/user.edgedb.repository.ts b/src/components/user/user.edgedb.repository.ts index 3a054ad3a1..a6665562d3 100644 --- a/src/components/user/user.edgedb.repository.ts +++ b/src/components/user/user.edgedb.repository.ts @@ -11,7 +11,7 @@ import { e, EdgeDB, isExclusivityViolation } from '~/core/edgedb'; import { CreatePerson, User, UserListInput } from './dto'; import { UserRepository } from './user.repository'; -const hydrate = e.shape(e.default.User, (user) => ({ +const hydrate = e.shape(e.User, (user) => ({ ...user['*'], // Other links if needed })); @@ -23,7 +23,7 @@ export class UserEdgedbRepository extends UserRepository { } async readOne(id: ID, _session: Session | ID) { - const query = e.select(e.default.User, (user) => ({ + const query = e.select(e.User, (user) => ({ ...hydrate(user), filter_single: { id }, })); @@ -36,7 +36,7 @@ export class UserEdgedbRepository extends UserRepository { async readMany(ids: readonly ID[], _session: Session | ID) { const query = e.params({ ids: e.array(e.uuid) }, ({ ids }) => - e.select(e.default.User, (user) => ({ + e.select(e.User, (user) => ({ ...hydrate(user), filter: e.op(user.id, 'in', e.array_unpack(ids)), })), @@ -46,7 +46,7 @@ export class UserEdgedbRepository extends UserRepository { } async doesEmailAddressExist(email: string) { - const query = e.select(e.default.User, () => ({ + const query = e.select(e.User, () => ({ filter_single: { email }, })); const result = await this.edgedb.run(query); @@ -54,8 +54,8 @@ export class UserEdgedbRepository extends UserRepository { } async list(input: UserListInput, _session: Session) { - const sortKey = input.sort as keyof (typeof e.default.User)['*']; - const all = e.select(e.default.User, (user) => ({ + const sortKey = input.sort as keyof (typeof e.User)['*']; + const all = e.select(e.User, (user) => ({ filter: e.all( input.filter.pinned != null ? e.op(user.pinned, '=', input.filter.pinned) @@ -83,7 +83,7 @@ export class UserEdgedbRepository extends UserRepository { } async create(input: CreatePerson) { - const query = e.insert(e.default.User, { ...input }); + const query = e.insert(e.User, { ...input }); try { const result = await this.edgedb.run(query); return result.id; @@ -103,7 +103,7 @@ export class UserEdgedbRepository extends UserRepository { user: User, email: string | null | undefined, ): Promise { - const query = e.update(e.default.User, () => ({ + const query = e.update(e.User, () => ({ filter_single: { id: user.id }, set: { email }, })); @@ -122,7 +122,7 @@ export class UserEdgedbRepository extends UserRepository { } async updateRoles(user: User, roles: Role[]): Promise { - const query = e.update(e.default.User, () => ({ + const query = e.update(e.User, () => ({ filter_single: { id: user.id }, set: { roles }, })); @@ -130,7 +130,7 @@ export class UserEdgedbRepository extends UserRepository { } async delete(id: ID, _session: Session, _object: User): Promise { - const query = e.delete(e.default.User, () => ({ + const query = e.delete(e.User, () => ({ filter_single: { id }, })); try {