How do I get AccountJS working with Fastify and Mercurius? #1190
Replies: 2 comments 11 replies
-
Fixed by downgrading to a specific version of Mongoose I noticed in the example code. (Here's a compatibility matrix but confusingly the I pointed the React Frontend example up to my backend to test, and it seems to be working perfectly now... but I'd still like feedback on whether I've got my ducks in a row, and am understanding things properly. |
Beta Was this translation helpful? Give feedback.
-
|
What ended up fixing it was having context that resumed the session. I really think the docs should be updated to reflect that in all the examples, I didn't get a user until I did this, since it seems like it's needed, but I'm open to being corrected: async ({ raw }: FastifyRequest): Promise<Context> => {
const ctx = await accountsGraphQL.context({ req: raw });
const { authToken } = ctx;
if (authToken) {
let user;
try {
user = await accountsServer.resumeSession(authToken as string); //<=== this is the key here.
} catch (error) {
if (error instanceof AccountsJsError) {
if (error.code === 'InvalidToken') {
throw new Error('Unauthorized');
}
}
}
return {
...ctx,
user,
userId: user && user.id && user._id, //<-- not sure if this lib maps the `_id` to `id` or not.
};
}
return {
...ctx,
};
}; |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
TL;DR
I am using Accounts with Fastify and Mercurius, using
@accounts/passwordand@accounts/graphql-apiwith mongo as a db, and am having the following problems (most likely due to misconfiguration or a misunderstanding of what this library does for you):createUserreturns session and user asnulladdEmailandverifyEmailthrow "Cannot read property 'nModified' of undefined"authenticateby sendingtoken, oraccess_tokenby itself otherwise it gives me "unexpected configuration"authenticateandverifyAuthenticated(returns true) work fineBelow I included my configuration, and my
package.jsonfile. Also links to issues, examples, and library code that have informed me thus far.I really love the API of
accounts-jsand was really excited to learn it when I saw it. I started a project with:I read the documentation front to back a few times. I also downloaded and ran the React Example while running the TypeScript Backend and was instantly sold! This lib is exactly what I'm looking for—hook, line, and sinker.
I'm using Fastify, which uses Mercurius for GraphQL, and quickly ran into an issue where the
userIdwasundefinedin my resolvers—butauthenticateandverifyAuthenticationworked fine. I didn't check that this was the case in the TypeScript example code mentioned earlier, but the example worked fine.My Accounts configuration code within a Fastify plugin—imports included
I saw in so many different places code that used
accountsGraphQL.contextdirectly oncontext, being new to the library, I still don't know if that's my problem. I also didn't know if it was fundamental differences between Mercurius and Apollo Server causing it to not populate or a misunderstanding of what the library actually does for you.Gives me typescript errors, about how the
booleans (2nd and 3rd args) were incompatible withreply. Event when I did just straight return the context,userIdanduserwere always undefined:In one place there was a super vague, no imports or anything (see How to use this package? under "The last step is to add to your
ApolloServer, the accounts context.") that I thought might be something, so I used that for reference as well. But didn't understand where functions were coming from.I had been passing an
Authorizationheader with Bearer token that I got from theauthenticatemutation:Still not sure if I was implementing it right, I went to the authenticate resolver in code, and saw it called
loginWithServicewhich I found onAccountsServerhere. I noted it callsauthenticate(in my case) using password, then returns the result so thatloginWithUsercan be called. Which the documentation warns:But do not see anything about the session in that code. At my lowest, I even resorted to using the
accountsServer.onevent to listen for successful authentication, then calling theloginWithUsermethod manually, to no avail.Am I misunderstanding something fundamental about how the library works? How do I get a user from a session when they pass a token? I started to get some good information with this issue but it was vague, and thought I might have the same misunderstanding.
So I built a context function based on this issue, to do this work manually, but I'm not sure if there's a better way or not, but it feels right to me:
The code for the buildContext function
```typescript import { AccountsModuleConfig, AccountsModuleContext, AccountsRequest, } from "@accounts/graphql-api"; import AccountsServer, { AccountsJsError } from "@accounts/server"; import { GraphQLModule, ModuleContext } from "@graphql-modules/core"; import { FastifyRequest } from "fastify"; import { InvalidTokenError } from "jwt-decode"; import { MercuriusContext } from "mercurius"; import { User } from "./types";Now that I have that in place the
meresolver (as demonstrated here) and thegetUserqueries return data, butcreateUserstill returns session and user asnull. I poured through the issues and found a suggestion from @vuode to use:And now I get a proper error message when trying to create a user whose username or email already exists.
But then I try to verify an email, or add an email (so far have just tried those two before coming here) I get this error message:
{ "data": { "addEmail": null }, "errors": [ { "message": "Cannot read property 'nModified' of undefined", "locations": [ { "line": 74, "column": 3 } ], "path": [ "addEmail" ] } ] }But it successfully persists the data. It verified my email but barfed at me, and when I added an email it added it and then barfed that.
package.json
```json { "name": "user", "version": "1.0.0", "description": "", "main": "./src/server.ts", "scripts": { "test": "jest --runInBand", "clean": "rm -rf dist", "build": "npm run clean && tsc", "dev": "nodemon src/server.ts", "start": "node dist/src/server.js", "lint": "eslint \"src/**/*.ts\"", "lint:write": "eslint \"src/**/*.ts\" --fix", "ts-node": "ts-node --compiler-options \"{\\\"module\\\":\\\"commonjs\\\"}\"", "generate:prisma": "prisma generate", "generate:secret": "uuid v4" }, "devDependencies": { "@tsconfig/node14": "^1.0.1", "@types/jsonwebtoken": "^8.5.5", "@types/jwt-decode": "^3.1.0", "@types/node": "^16.11.6", "@types/supertest": "^2.0.10", "@types/uuid": "^8", "@types/ws": "^7.4.0", "@typescript-eslint/eslint-plugin": "^4.9.1", "@typescript-eslint/parser": "^4.9.1", "eslint": "^7.15.0", "eslint-config-google": "^0.14.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jest": "^24.1.3", "eslint-plugin-promise": "^4.2.1", "jest": "^26.6.3", "nodemon": "^2.0.15", "prettier-plugin-prisma": "^3.4.1", "prisma": "3.4.1", "supertest": "^6.0.1", "ts-jest": "^26.4.4", "ts-node": "^10.4.0", "ts-node-dev": "^1.1.1", "typescript": "^4.4.4" }, "dependencies": { "@accounts/database-manager": "^0.33.1", "@accounts/graphql-api": "^0.33.1", "@accounts/magic-link": "^0.1.1", "@accounts/mongo": "^0.33.5", "@accounts/password": "^0.32.1", "@accounts/rest-express": "^0.33.1", "@accounts/server": "^0.33.1", "@graphql-modules/core": "^0.7.17", "@graphql-tools/merge": "^8.2.1", "@graphql-tools/schema": "^7.1.2", "@prisma/client": "3.4.1", "argon2": "^0.28.2", "dotenv": "^10.0.0", "fastify": "^3.9.2", "fastify-express": "^0.3.3", "fastify-mongodb": "^4.1.1", "fastify-plugin": "^3.0.0", "graphql": "^15.4.0", "graphql-tag": "^2.12.6", "jsonwebtoken": "^8.5.1", "jwt-decode": "^3.1.2", "mercurius": "^8.9.1", "mercurius-codegen": "^1.2.0", "mongoose": "^6.0.13", "reflect-metadata": "^0.1.13", "tslib": "^2.3.1", "uuid": "^8.3.2", "yup": "^0.32.11", "yup-env": "^1.2.0" }, "author": "Kevin Dench ", "license": "ISC", "prisma": { "seed": "ts-node prisma/seed.ts" } } ```I could really use some help getting this set up properly, it's been a very hard and exasperating experience so far, but I don't want to give up on all the niceities and good design from this library. What am I doing/how am I thinking wrong? I have been using
graphiqlto test all this configuration, haven't built the frontend yet.Thanks for any help ahead of time. It's a great library, even with all these problems I've experienced, I'm thinking it's just me being slow.
Beta Was this translation helpful? Give feedback.
All reactions