What does kind undefined mean here? I cannot find any solution for this error - api

I am trying to split up my schema of GraphQL API into separate ones.
Having familiarized with a huge number of them I decided on this one below using "extend"
( I also wanted to use .graphql file extension for them but as I've got there is only one way to do that - it is with the use of webpack. I am not really good at it so I tried to make it work at first with .js files)
BUT: I cannot cope with this simple task because I either have TypeError: Cannot read property 'kind' of undefined or Invalid schema passed, or something else pops up...
What am I doing wrong here and what is the best practice/approach to split up and stitch the Schema?
Thanks in advance!
server.js
import express from "express";
import { ApolloServer, gql } from "apollo-server-express";
import { makeExecutableSchema } from 'graphql-tools';
import * as mongoClient from "./config";
import * as _ from 'lodash';
import { UserSchema, UserResolvers } from "./graphql.partials/user.api";
const port = process.env.PORT || 8080;
const RootSchema = gql`
type Query {
_empty: String
}
type Mutation {
_empty: String
}
`
const RootResolvers = {
};
const app = express();
const schema = makeExecutableSchema({
typeDefs: [RootSchema, UserSchema],
resolvers: _.merge(RootResolvers, UserResolvers)
});
const apolloServer = new ApolloServer({ schema });
apolloServer.applyMiddleware({ app });
app.listen({ port }, () => {
console.log(
`Server ready at http://localhost:${port}${apolloServer.graphqlPath}`
);
});
user schema
const { gql } = require("apollo-server-express");
import User from '../models/User';
export const typeDefs = gql`
extend type Query {
users: [User]
user(id: String): User
}
extend type Mutation {
addUser(email: String, password: String): User
deleteUser(id: String!): User
updateUser(user: UserInput): User
}
type User {
id: ID!
firstName: String
lastName: String
email: String!
password: String!
confirmed: Boolean
role: String
}
input UserInput {
id: ID!
firstName: String
lastName: String
email: String
password: String
confirmed: Boolean
role: String
}
`
export const UserResolvers = {
Query: {
users: async (obj, args, context, info) => {
try {
const res = await User.find();
return res;
} catch (err) {
return err.message;
}
},
user: async (obj, args, context, info) => {
try {
const res = User.findById(args['id']);
return res;
} catch (e) {
return e.message;
}
}
},
Mutation: {
addUser: async (obj, args, context, info) => {
try {
const res = await User.create(args);
return res;
} catch (err) {
return err.message;
}
},
deleteUser: async (obj, args, context, info) => {
try {
return User.findByIdAndDelete(args['id']);
} catch (e) {
return e.message;
}
},
updateUser: async (obj, args, context, info) => {
try {
return User.findByIdAndUpdate(args.user.id, args.user)
} catch (e) {
return e.message;
}
}
}
}

There is no export named UserSchema in your file. You have two named exports -- UserResolvers and typeDefs. As a result, when you attempt to import UserSchema, its value is undefined.

Related

Urql config with guest token for SSG on next js

So I have a project using the latest Next js 13, React 18, Urql 3, and using typescript
Currently, I have issues when trying to query the urql from the getstaticprops function. My urql request needs a guest token, and I'm storing the token on session storage(other suggestions ?).
It has no issue when the query is running on the client, but I have it when querying inside the function.
My concern is related to the token reading, so the server cannot read the session storage value.
I'm asking what is the better and simplest way to make this work.
Does use cookies to store guest tokens will make this work?
Or the configuration that doesn't work?
This is my current config for urql.ts
import {
createClient,
ssrExchange,
dedupExchange,
cacheExchange,
fetchExchange,
} from "urql";
import { GRAPH_URL } from "#lib/constant/env";
import type { TypedDocumentNode } from "#urql/core";
const isServerSide = typeof window === "undefined";
const ssrCache = ssrExchange({
isClient: !isServerSide,
});
const client = createClient({
url: GRAPH_URL,
exchanges: [dedupExchange, cacheExchange, ssrCache, fetchExchange],
fetchOptions: () => {
const token = sessionStorage.getItem("accessToken");
return {
headers: {
authorization: token ? `Bearer ${token}` : "",
},
};
},
});
const query = async (
query: TypedDocumentNode<any, object>,
variables?: Record<string, string | string[] | unknown>
) => {
try {
const response = await client.query(query, variables as any).toPromise();
return response;
} catch (error) {
if (error instanceof Error) console.error(error.message);
}
};
const mutation = async (
mutation: TypedDocumentNode<any, object>,
variables?: Record<string, string | string[] | unknown>
) => {
try {
const response = await client
.mutation(mutation, variables as any)
.toPromise();
return response;
} catch (error) {
if (error instanceof Error) console.error(error.message);
}
};
export { client, query, mutation, ssrCache };
And this some of the code for the blog index page
export const getStaticProps = async () => {
await fetchArticlesSummary();
return {
props: {
urqlState: ssrCache.extractData(),
},
revalidate: 600,
};
};
export default withUrqlClient(() => ({
url: GRAPH_URL,
}))(BlogPage);
This is for the fetchArticlesSummary
export const fetchArticlesSummary = async () => {
try {
const {
data: { listArticles },
}: any = await query(getListArticle);
return listArticles.items;
} catch (error) {
return {
notFound: true,
};
}
};
I also doing a setup on _app.tsx
export default function App({ Component, pageProps }: AppProps) {
if (pageProps.urqlState) {
ssrCache.restoreData(pageProps.urqlState);
}
return (
<Provider value={client}>
<Component {...pageProps} />
</Provider>
);
}
Thank you
I have followed urql documentation about server-side configuration and many others but still don't have any solutions.

Cannot verify JWT token

I am using NestJS and its JWT package based on jsonwebtoken. The generated token is always being invalid, and I am getting a 500 - Internal Server Error.
What might be the problem?
My login function in the AuthService:
async login(email: string, password: string, isAdmin?: boolean, isVIP?: boolean){
let user = await this.usersService.findByEmail(email);
if(!user){
throw new NotFoundException('No user with this email could be found.');
}
const isEqual = await bcrypt.compare(password, user.password);
if(!isEqual){
throw new BadRequestException('Email and password do not match');
}
const secret = 'secretkey';
const payload = {email: user.email, userId: user._id.toString()}
const token = this.jwtService.sign(payload, {secret, expiresIn: '1h'});
return [email, isAdmin, isVIP, token];
}
My verification logic in the AuthGuard
`
import { BadRequestException, CanActivate, ExecutionContext, Inject } from "#nestjs/common";
import { JwtService } from "#nestjs/jwt/dist";
import { JwtConfigService } from "src/config/jwtconfig.service";
export class JwtAuthGuard implements CanActivate {
constructor(#Inject(JwtService) private jwtService: JwtService){}
canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
const authHeader = request.get('Authorization');
if (!authHeader) {
throw new BadRequestException('Not authorized');
}
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = this.jwtService.verify(token, {secret: 'secretkey'});
} catch (err) {
throw new Error('Cannot verify token.')
}
if(!decodedToken){
throw new BadRequestException('Not authenticated')
}
request.userId = decodedToken.userId;
console.log({decodedToken, token});
return request.userId;
};
}
My current JWT setup in the UsersModule imports (I have no AuthModule); I tried all the other configurations in the official docs, too.
JwtModule.register({
secret: 'secretkey',
publicKey: '...',
privateKey: '...',
secretOrKeyProvider: (
requestType: JwtSecretRequestType,
tokenOrPayload: string | Object | Buffer,
verifyOrSignOrOptions?: jwt.VerifyOptions | jwt.SignOptions
) => {
switch (requestType) {
case JwtSecretRequestType.SIGN:
return 'privateKey';
case JwtSecretRequestType.VERIFY:
return 'publicKey';
default:
return 'secretkey';
}
},
})
`
My jwtconfig.ts, which I don't think is being used:
`
import { JwtOptionsFactory, JwtModuleOptions } from '#nestjs/jwt'
export class JwtConfigService implements JwtOptionsFactory {
createJwtOptions(): JwtModuleOptions {
return {
secret: 'secretkey'
};
}
}
`
I solved the problem by switching my guard to a middleware.

(redis-om & fastify) this.writeEntity is not a function

I'm learning to use the Redis for my backend database and I would like to try using redis-om for fastify not sure whether they are compatible or not, but I got error.
I use service of app.redislabs.com
I don't know what I just messed up? And how can I fix the problem?
server.js
const { createCar, createIndex } = require("./redis");
app.post("/add", async (req, res) => {
await createIndex();
const { make, model, image, description } = req.body;
const data = { make, model, image, description };
await createCar(data);
res.code(200).send('ok');
});
const PORT = 5000;
app.listen(PORT, function (err) {
if (err) {
app.log.error(err);
process.exit(1);
}
});
redis.js
const { Client, Entity, Schema, Repository } = require("redis-om");
const client = new Client();
const connect = async () => {
if (!client.isOpen()) {
await client.open("redis://default:password#localhost:6379");
} else {
console.log("CONNECTED");
}
};
class Car extends Entity {}
let schema = new Schema(
Car,
{
make: { type: "string" },
model: { type: "string" },
image: { type: "string" },
description: { type: "string" },
},
{ dataStructure: "JSON" }
);
const createCar = async (data) => {
await connect();
const repository = new Repository(schema, client);
const car = repository.createEntity(data);
const id = await repository.save(car);
return id;
};
const createIndex = async () => {
await connect();
const repository = new Repository(schema, client);
await repository.createIndex();
};
module.exports = {
createCar,
createIndex,
};
My JSON Body
You cannot call new on Repository. This is a breaking change I introduced in version 0.2.0 of Redis OM. There are a couple of others that are documented in the CHANGELOG.
Call const repository = client.fetchRepository(schema) instead, as shown here. Unfortunately, there are some videos and blogs that have the older syntax and so this crops up from time to time.
Thanks for using my library!

I can't send a parameter through graphql query

i'm reciving the error Variable "$id" of required type "String!" was not provided. Someone knows why?
In my backend (node-mongo-graphql)
Mutation:
type Mutation {
deleteAmbiente(_id: String!): Ambiente
}
Resolver:
async deleteAmbiente(_,_id, context) {
console.log("hi there!", _id)
}
In my front-end (vue + apollo)
async deleteAmbiente() {
try {
let id = this.item._id
const res = await apolloClient.mutate({
mutation: ELIMINAR_AMBIENTE,
variables: id, // id has a value, if i send "hello" from here, it doesn't work either
});
console.log(res)
} catch (err) {
err;
}
},
export const ELIMINAR_AMBIENTE = gql`
mutation deleteAmbiente(
$id: String!
){
deleteAmbiente(_id:$id){
nombre
}
}
`

Can not run multiple tests in a file

I'm building a GraphQL API and I want to test some resolvers and the database with jest.
Here is my helper file, where I set up the context and the Prisma Client for testing.
import { PrismaClient } from "#prisma/client";
import { ServerInfo } from "apollo-server";
import { execSync } from "child_process";
import getPort, { makeRange } from "get-port";
import { GraphQLClient } from "graphql-request";
import { nanoid } from "nanoid";
import { join } from "path";
import { Client } from "pg";
import { server } from "../api/server";
type TestContext = {
client: GraphQLClient;
db: PrismaClient;
};
export function createTestContext(): TestContext {
let ctx = {} as TestContext;
const graphqlCtx = graphqlTestContext();
const prismaCtx = prismaTestContext();
beforeEach(async () => {
const client = await graphqlCtx.before();
const db = await prismaCtx.before();
Object.assign(ctx, {
client,
db,
});
});
afterEach(async () => {
await graphqlCtx.after();
await prismaCtx.after();
});
return ctx;
}
function graphqlTestContext() {
let serverInstance: ServerInfo | null = null;
return {
async before() {
const port = await getPort({ port: makeRange(4000, 6000) });
serverInstance = await server.listen({ port });
return new GraphQLClient(`http://localhost:${port}`);
},
async after() {
serverInstance?.server.close();
},
};
}
function prismaTestContext() {
const prismaBinary = join(__dirname, "..", "node_modules", ".bin", "prisma");
let schema = "";
let databaseUrl = "";
let prismaClient: null | PrismaClient = null;
return {
async before() {
schema = `test_${nanoid()}`;
databaseUrl = `postgresql://user:123#localhost:5432/testing?schema=${schema}`;
process.env.DATABASE_URL = databaseUrl;
execSync(`${prismaBinary} migrate up --create-db --experimental`, {
env: {
...process.env,
DATABASE_URL: databaseUrl,
},
});
prismaClient = new PrismaClient();
return prismaClient;
},
async after() {
const client = new Client({
connectionString: databaseUrl,
});
await client.connect();
await client.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
await client.end();
await prismaClient?.$disconnect();
},
};
}
My test file looks like this:
import { createTestContext } from "./__helpers";
const ctx = createTestContext();
it("register user", async () => {
const testUser = {
username: "Test",
email: "test#test.com",
password: "password",
};
const registerResult = await ctx.client.request(
`
mutation registerNewUser($username: String!, $email: String!, $password: String!) {
register(username: $username, email: $email, password: $password) {
user {
user_id
username
email
}
}
}
`,
{
username: testUser.username,
email: testUser.email,
password: testUser.password,
}
);
const resultUsername = registerResult.register.user.username;
const resultEmail = registerResult.register.user.email;
const resultUserID = registerResult.register.user.user_id;
expect(resultUsername).toBe(testUser.username);
expect(resultEmail).toBe(testUser.email);
expect(resultUserID).not.toBeNull;
const users = await ctx.db.user.findMany();
const savedUser = users[0];
expect(savedUser.username).toBe(testUser.username);
expect(savedUser.email).toBe(testUser.email);
expect(savedUser.user_id).toBe(resultUserID);
expect(savedUser.first_name).toBeNull;
expect(savedUser.last_name).toBeNull;
expect(savedUser.role).toBe("USER");
expect(savedUser.password).not.toBe(testUser.password);
});
it("all events", async () => {
const eventsResult = await ctx.client.request(
`
query {
allEvents {
event_id
title
description
}
}
`
);
expect(eventsResult.allEvents.length).toBe(0)
});
When I just run one file with one test in it, everything works. But when I run multiple tests in one file, the first one runs normal, but the ones after not. I receive this error:
The table `test_LjrcmbMjI4vLaDYM9-lvw.Event` does not exist in the current database.: {"response":{"errors":[{"message":"\nInvalid `prisma.event.findMany()` invocation:\n\n\n The table `test_LjrcmbMjI4vLaDYM9-lvw.Event` does not exist in the current database.","locations":[{"line":3,"column":7}],"path":["allEvents"],"extensions":{"code":"INTERNAL_SERVER_ERROR","exception":{"code":"P2021","clientVersion":"2.11.0","meta":{"table":"test_LjrcmbMjI4vLaDYM9-lvw.Event"}}}}],"data":null,"status":200},"request":{"query":"\n query {\n allEvents {\n event_id\n title\n description\n }\n }\n "}}
Also when I run two tests in separated files, on every second test run I get this error:
listen EADDRINUSE: address already in use :::4200
I did the nexus tutorial (Step 4, and 5), where they explained how to test, but somehow it doesn't work. So please help me.
https://nexusjs.org/docs/getting-started/tutorial
I have created a repo with parallel tests for the same here. The test environment setup is in the prisma folder and a similar helper is created in the tests folder.