next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

Type issue in 4.24.8 Adapter

Open tacomanator opened this issue 1 year ago • 13 comments

Environment

  System:
    OS: macOS 14.6.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 259.67 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.16.0 - ~/.nvm/versions/node/v20.16.0/bin/node
    npm: 10.8.1 - ~/.nvm/versions/node/v20.16.0/bin/npm
    pnpm: 9.11.0 - ~/Library/pnpm/pnpm
    bun: 1.0.2 - ~/.bun/bin/bun
  Browsers:
    Chrome: 129.0.6668.70
    Safari: 17.6
  npmPackages:
    next: 14.2.13 => 14.2.13 
    next-auth: ^4.24.8 => 4.24.8 
    react: ^18 => 18.3.1 

Reproduction URL

https://github.com/tacomanator/next-auth-adapter-4.24.8

Describe the issue

In upgrading from 4.24.7 to 4.24.8, the parameter types for the following Adapter methods are missing (i.e. becoming implicit any):

  • createUser
  • linkAccount
  • unlinkAccount

How to reproduce

try to build typescript project with custom Adapter. For example, the reproduction repository uses the following:

import { Adapter, AdapterSession, AdapterUser } from "next-auth/adapters";

const data: { user: AdapterUser; session: AdapterSession } = {
  user: { id: "test", name: "test", email: "test", emailVerified: new Date() },
  session: { sessionToken: "test", userId: "test", expires: new Date() },
};

export default function MyAdapter(): Adapter {
  return {
    async createUser(user) {
      console.log(user);
      return;
    },
    async getUser(id) {
      console.log(id);
      return null;
    },
    async getUserByEmail(email) {
      console.log(email);
      return null;
    },
    async getUserByAccount({ providerAccountId, provider }) {
      console.log(providerAccountId, provider);
      return null;
    },
    async updateUser(user) {
      console.log(user);
      return data.user;
    },
    async deleteUser(userId) {
      console.log(userId);
      return;
    },
    async linkAccount(account) {
      console.log(account);
      return null;
    },
    async unlinkAccount({ providerAccountId, provider }) {
      console.log(providerAccountId, provider);
      return null;
    },
    async createSession({ sessionToken, userId, expires }) {
      console.log(sessionToken, userId, expires);
      return data.session;
    },
    async getSessionAndUser(sessionToken) {
      console.log(sessionToken);
      return null;
    },
    async updateSession({ sessionToken }) {
      console.log(sessionToken);
      return null;
    },
    async deleteSession(sessionToken) {
      console.log(sessionToken);
      return null;
    },
    async createVerificationToken({ identifier, expires, token }) {
      console.log(identifier, expires, token);
      return null;
    },
    async useVerificationToken({ identifier, token }) {
      console.log(identifier, token);
      return null;
    },
  };
}

Expected behavior

Types are present for parameters and can build.

tacomanator avatar Sep 26 '24 23:09 tacomanator

Looks related to https://github.com/nextauthjs/next-auth/pull/11562

Based on https://github.com/nextauthjs/next-auth/issues/9493#issuecomment-2282731857 and my own local testing, I thought it fixed the issue...

But it introduced a new one in case of custom adapters. 🙁

I will try to look into this.

balazsorban44 avatar Sep 26 '24 23:09 balazsorban44

Looks related to #11562

Based on #9493 (comment) and my own local testing, I thought it fixed the issue...

But it introduced a new one in case of custom adapters. 🙁

I will try to look into this.

Hi. The issue seems to be present (and/or breaking CI/CD) when one do not install @auth/core or smth like that (e.g. upgrading to the 5th version[?]). So I assume you just imported types from that package and here we are.

Maybe this information will be helpful

image

kiruushaaa avatar Sep 27 '24 08:09 kiruushaaa

Yes I have a same issue. Using Prisma adapter.

huksley avatar Oct 06 '24 07:10 huksley

I have the same issue.

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

maxdeichmann avatar Oct 06 '24 23:10 maxdeichmann

Anyone saying same issue, add a reproduction. Would help to see how this regressed.

balazsorban44 avatar Oct 06 '24 23:10 balazsorban44

We have a branch to upgrade next-auth here: https://github.com/langfuse/langfuse/pull/3602 If fails with:

./src/server/auth.ts:274:20
Type error: Parameter 'profile' implicitly has an 'any' type.

  272 | const extendedPrismaAdapter: Adapter = {
  273 |   ...prismaAdapter,
> 274 |   async createUser(profile) {
      |                    ^
  275 |     if (!prismaAdapter.createUser)
  276 |       throw new Error("createUser not implemented");
  277 |     if (
 ELIFECYCLE  Command failed with exit code 1.
Error:  command finished with error: command (/home/runner/work/langfuse/langfuse/web) /home/runner/setup-pnpm/node_modules/.bin/pnpm run build exited (1)
Error: web#build: command (/home/runner/work/langfuse/langfuse/web) /home/runner/setup-pnpm/node_modules/.bin/pnpm run build exited (1)

 Tasks:    4 successful, 5 total
Cached:    0 cached, 5 total
  Time:    2m58.602s 
Failed:    web#build

 ERROR  run failed: command  exited (1)
 ELIFECYCLE  Command failed with exit code 1.
Error: Process completed with exit code 1.

Here are also docs explaining how to get up and running with the repo.

maxdeichmann avatar Oct 09 '24 19:10 maxdeichmann

Anyone saying same issue, add a reproduction. Would help to see how this regressed.

@balazsorban44 looking at https://github.com/nextauthjs/next-auth/pull/11562/files , I'll explain what I think the regression is to you.

The PR introduces an optional dependency on @auth/core, to be able to pull in import type { Adapter as FutureAdapter } from "@auth/core/adapters". Where @auth/core is present, the FutureAdapter["createUser"] successfully resolves to a real type, but if @auth/core is not present, then it causes TypeScript to resolve to the any type, causing TypeScript to break for users who both implement custom Adapters and have the noImplicitAnycompiler option.

... I'm not 100% sure of that though, I tried to pull in @auth/core as a dependency and I'm still getting the error :(

ari-becker avatar Oct 25 '24 05:10 ari-becker

balazsorban44 i do not have noImplicitAny set in my project. Any other reason why this might be failing?

maxdeichmann avatar Oct 28 '24 12:10 maxdeichmann

In order to unblock upgrade to next.js 15 I had to specify the type for unlinkAccount function arguments myself.

Before:

import type { Adapter } from "next-auth/adapters";

function MyAdapter(): Adapter {
	return {
		async unlinkAccount({
			providerAccountId,
			provider
		}) {
			
		}
	};
}

After:

import type { Adapter, AdapterAccount } from "next-auth/adapters";

function MyAdapter(): Adapter {
	return {
		async unlinkAccount({
			providerAccountId,
			provider
		}: Pick<AdapterAccount, "provider" | "providerAccountId">) {
			
		}
	};
}

MonstraG avatar Nov 06 '24 11:11 MonstraG

@balazsorban44 is there any update on this? I would really like to upgrade next-auth but I am blocked by this right now.

maxdeichmann avatar Nov 13 '24 14:11 maxdeichmann

#15 18.54 Failed to compile.
#15 18.54 
#15 18.54 ./lib/auth.ts:148:17
#15 18.54 Type error: Parameter 'account' implicitly has an 'any' type.
#15 18.54 
#15 18.54   146 | authOptions.adapter = {
#15 18.54   147 |   ...adapterOverwrite,
#15 18.54 > 148 |   linkAccount: (account) => {
#15 18.54       |                 ^
#15 18.54   149 |     delete account['not-before-policy'];
#15 18.54   150 |     delete account['refresh_expires_in'];
#15 18.54   151 |     return adapterOverwrite.linkAccount?.(account);

is this the same issue?

masterkain avatar Nov 21 '24 05:11 masterkain

@masterkain yes, the same issue. Until it's resolved you may be able to work around by explicitly typing arguments for createUser(), linkAccount(), and unlinkAccount(). For example:

function MyAdapter(): Adapter {
  return {
    async createUser(user: Omit<AdapterUser, "id">) {},
    async linkAccount(account: AdapterAccount) {} ,
    async unlinkAccount({ providerAccountId, provider }: Pick<AdapterAccount, "provider" | "providerAccountId">) {},
  }
}

the other methods don't seem to have a problem.

tacomanator avatar Dec 16 '24 08:12 tacomanator

I ran into this after setting "skipLibCheck": false in my tsconfig, and I thought I would document my journey here.

My package.json shows the latest versions

    "next": "^15.3.1",
    "next-auth": "^4.24.11",

I tried to simply add @auth/core package, but that led down a different rabbit hole so I backed up and tried to come up with a workaround that doesn't involve adding the extra package.

Create a file like /types/next-auth-fix.d.ts with this content:

declare module '@auth/core/adapters' {
    import type { AdapterUser, AdapterAccount, AdapterSession } from "next-auth/adapters";
    export interface Adapter {
      createUser?(user: Omit<AdapterUser, "id">): Promise<AdapterUser>;
      linkAccount?(account: AdapterAccount): Promise<void>;
      unlinkAccount?(providerAccountId: { provider: string; providerAccountId: string }): Promise<void>;
    }
  }

Then, additionally there seems to be another issue with next-auth package that is revealed after setting "skipLibCheck": false which I can't find any further info on, but I did come up with a second work around.

The error looks like this:

./node_modules/next-auth/react/index.d.ts:86:71
Type error: Cannot find namespace 'JSX'.

  84 |  * [Documentation](https://next-auth.js.org/getting-started/client#sessionprovider)
  85 |  */
> 86 | export declare function SessionProvider(props: SessionProviderProps): JSX.Element;
     |                                                                       ^
  87 | //# sourceMappingURL=index.d.ts.map

Create another file like /types/next-auth-fix-2.d.ts with content:

import React from "react";
declare global {
  namespace JSX {
    interface Element extends React.JSX.Element {}  // Align global JSX with React.JSX
  }
}

Then, finally, I'm able to npm run build with "skipLibCheck": false and my nextjs website seems to be working OK although these workarounds are not extensively tested in production.

ghost avatar Apr 23 '25 22:04 ghost