8000 Upsert method not working as expected in Orchid ORM · Issue #385 · romeerez/orchid-orm · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Upsert method not working as expected in Orchid ORM #385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
KMJ-007 opened this issue Aug 27, 2024 · 2 comments
Open

Upsert method not working as expected in Orchid ORM #385

KMJ-007 opened this issue Aug 27, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@KMJ-007
Copy link
KMJ-007 commented Aug 27, 2024

Description

The upsert method is not functioning correctly when trying to upsert a user with associated auth provider data. The method is not visible or not working as expected.

Steps to Reproduce

  1. Set up a project with Orchid ORM
  2. Create the following table definitions:

User Table

```typescript
import { Queryable, Selectable, Updatable } from "orchid-orm";
import { BaseTable } from "./baseTable";
import { UserWorkspaceTable } from "./userWorkspace.table";
import { PostsTable } from "./posts.table";
import { AuthProviderTable } from "./authProvider.table";

export class UserTable extends BaseTable {
  readonly table = "user";
  
  columns = this.setColumns((t) => ({
    id: t.uuid().primaryKey().default(t.sqlgen_random_uuid()),
    name: t.string().trim().nullable(),
    email: t.string().trim().unique(),
    isVerified: t.boolean().default(false),
    profilePicture: t.string().nullable(),
    lastLoginAt: t.timestamp().nullable(),
    createdAt: t.timestamps().createdAt.nullable(),
    updatedAt: t.timestamps().updatedAt.nullable(),
  }));
  
  relations = {
    workspaces: this.hasMany(() => UserWorkspaceTable, {
      columns: ['id'],
      references: ['userId'],
    }),
    posts: this.hasMany(() => PostsTable, {
      columns: ['id'],
      references: ['authorId'],
    }),
    authProviders: this.hasMany(() => AuthProviderTable, {
      columns: ['id'],
      references: ['userId'],
    }),
  };
}

export type User = Selectable;
export type UserUpdate = Updatable;
export type UserForQuery = Queryable;

Auth Provider Table

export class AuthProviderTable extends BaseTable {
  readonly table = "auth_provider";
  
  columns = this.setColumns((t) => ({
    id: t.uuid().primaryKey().default(t.sqlgen_random_uuid()),
    userId: t.uuid().foreignKey(() => UserTable, 'id'),
    provider: t.string(),
    providerUserId: t.string(),
    accessToken: t.string(),
    refreshToken: t.string().nullable(),
    expiresAt: t.timestamp(),
    tokenType: t.string(),
    scope: t.string().nullable(),
    createdAt: t.timestamps().createdAt.nullable(),
    updatedAt: t.timestamps().updatedAt.nullable(),
  }));
  
  relations = {
    user: this.belongsTo(() => UserTable, {
      columns: ['userId'],
      references: ['id'],
    }),
  };
}

export type AuthProvider = Selectable;
export type AuthProviderUpdate = Updatable;
export type AuthProviderForQuery = Queryable;
  1. Attempt to use the upsert method in a service function:
export const upsertUserWithAuthProvider = async (
  userData: Omit<User, "id" | "createdAt" | "updatedAt" | "lastLoginAt"> & {
    providerData: Omit<AuthProvider, "id" | "userId" | "createdAt" | "updatedAt">
  }
): Promise<UserType & { authProviders: AuthProvider[] }> => {
  const user = await db.user
    .select(
      "id",
      "email",
      "isVerified",
      "name",
      "profilePicture",
      "lastLoginAt",
      "createdAt",
      "updatedAt",
      {
        authProviders: (q) => q.authProviders.select(''),
      }
    )
    .findBy({ email: userData.email })
    .upsert({
      create: {
        ...userData,
        authProviders: {
          create: [userData.providerData]
        }
      },
      update: {
        ...userData,
        authProviders: {
          upsert: {
            where: {
              provider: userData.providerData.provider,
              providerUserId: userData.providerData.providerUserId
            },
            create: userData.providerData,
            update: userData.providerData,
          }
        }
      }
    });

  return user;
};

Expected Behavior

The upsert method should be available and work correctly, allowing us to upsert a user with associated auth provider data.

Actual Behavior

The upsert method is not showing up or not working as expected.

Environment

  • Orchid ORM version: ^1.31.7
  • Node.js version: v18.19.1
@romeerez romeerez added wontfix This will not be worked on enhancement New feature or request and removed wontfix This will not be worked on labels Sep 28, 2024
@romeerez
Copy link
Owner

The reason is that upsert does only work for belongsTo and hasOne relations. (docs).

It should be possible to add support for hasMany as in your case.

@romeerez
Copy link
Owner

This is a tough one, many things to change, I hope it's no a big deal for you to workaround this by upserting an auth provider in a separate query.

I'll add support for upsert for hasMany and hasAndBelongsToMany, but I'd like to postpone it to be done after other bugfixes and changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants
0