Next JS connection with Apollo and MongoDB - mongodb

I am new to Next.js and using this example from Next.js https://github.com/zeit/next.js/tree/master/examples/api-routes-apollo-server-and-client.
However, the example is silent on MongoDB integration (also I could not find any other example for the same). I have been able to make database-connection but NOT able to use it in resolvers.
My Code
pages/api/graphql.js
import { ApolloServer } from 'apollo-server-micro'
import { schema } from '../../apollo/schema'
const MongoClient = require('mongodb').MongoClient;
let db
const apolloServer = new ApolloServer({
schema,
context: async () => {
if (!db) {
try {
const client = await MongoClient.connect(uri)
db = await client.db('dbName')
const post = await Posts.findOne()
console.log(post)
// It's working fine here
}
catch (e) {
// handle any errors
}
}
return { db }
},
})
export const config = {
api: {
bodyParser: false,
},
}
export default apolloServer.createHandler({ path: '/api/graphql' })
apollo/schema.js
import {makeExecutableSchema} from 'graphql-tools';
import {typeDefs} from './type-defs';
import {resolvers} from './resolvers';
export const schema = makeExecutableSchema({
typeDefs,
resolvers
});
apollo/resolvers.js
const Items = require('./connector').Items;
export const resolvers = {
Query: {
viewer(_parent, _args, _context, _info) {
//want to populate values here, using database connection
return { id: 1, name: 'John Smith', status: 'cached' }
},
...
}
}
I am stuck in the resolvers.js part. Don't know how to get the cached database connection inside resolvers.js. If I create a new database connection file, top-level await is not supported there, so how do I proceed?

If context is a function, whatever you return from the function will be available as the context parameter in your resolver. So if you're returning { db }, that's what your context parameter will be -- in other words, you can access it as context.db inside your resolver.

Related

how to use env variables in nuxt 3 outside of setup scripts

So the problem is that I would like to use Axios instance. Because:
new useFetch is only possible to use inside of components aka setup scrips. https://v3.nuxtjs.org/guide/features/data-fetching/
community axios module is only possible inside of nuxt2 https://github.com/nuxt-community/axios-module/issues/536 and are nor supported in nuxt3
I need to make calls in pinia actions(store) to my backend service.
nuxt.config.js
import { defineNuxtConfig } from "nuxt";
export default defineNuxtConfig({
runtimeConfig: {
public: {
apiBase: process.env.API_BASE_URL ?? "http://localhost:8080/api/v1",
},
},
env: {
apiBase: process.env.API_BASE_URL ?? "http://localhost:8080/api/v1",
},
buildModules: ["#pinia/nuxt"],
});
and here is instance.js
import axios, { AxiosResponse } from "axios";
const instance = axios.create({
baseURL: process.env.API_BASE_URL,
});
instance.interceptors.response.use((response: AxiosResponse) => {
return response.data;
});
export default instance;
So it does see the envs on server-side as I can console log them but on client I do receive can't read of undefined
You can access your env variables using a composable and the useRuntimeConfig method.
Something like this for instance:
// file composables/use-axios-instance.ts
import axios, { AxiosResponse } from "axios";
let instance = null;
export const useAxiosInstance = () => {
const { API_BASE_URL } = useRuntimeConfig();
if (!instance) {
instance = axios.create({
baseURL: API_BASE_URL,
});
instance.interceptors.response.use((response: AxiosResponse) => {
return response.data;
});
}
return instance;
};
Then you can access to your axios instance using const axios = useAxiosInstance();

trying to get uploads saving in MongoDB

I currently have the following code, which saves the temp file to public/files I have tried to understand the MongoDB GridFS documentation but with no success.
I am wondering how do I get the files to save inside MongoDB GridFS instead of my public/file directory
I am aware I am missing the part where I need to send the uploaded file to mongodb - this is the part I don't know how to do.
In mongodb example they say to do something like:
fs.createReadStream('./myFile').pipe(
bucket.openUploadStream('myFile', {
chunkSizeBytes: 1048576,
metadata: { field: 'myField', value: 'myValue' },
})
);
however I am not using FS or do I need to upload the file to the temp and then do the fs
import formidable from 'formidable';
import { MongoClient, ObjectId } from 'mongodb';
var Grid = require('gridfs-stream');
export const config = {
api: {
bodyParser: false,
},
};
export default async (req, res) => {
const uri = process.env.MONGODB_URI;
let client;
let clientPromise;
const options = {};
client = new MongoClient(uri, options);
clientPromise = client.connect();
const clients = await clientPromise;
const database = clients.db('AdStitchr');
var gfs = Grid(database, client);
gfs.collection('uploads');
const form = new formidable.IncomingForm();
form.uploadDir = 'public/files';
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
var file = files.file;
console.log(JSON.stringify(file));
try {
const newFile = File.create({
name: `files\${file.newFilename}.mp3`,
});
res.status(200).json({ status: 'success' });
} catch (error) {
res.send(error);
}
});
};

Integration Testing with GraphQL (Nexus, Apollo), Prisma, and PostgreSQL

I am trying to follow this tutorial to establish integration tests on our web application. Our stack currently includes Nexus, Next, Apollo, Prisma, and PostgreSQL.
I am using ApolloClient in place of GraphQLClient from graphql-request, I opted to use ApolloClient instead, especially since our web application is server less.
This is currently what I have inside the helper.ts, and the ApolloClient does work when I execute mutations. However, after executing a mutation on ApolloClient and checking if the data persists through Prisma, I get a null value.
Did I do these adjustments correctly? I am definitely missing something if Prisma is not querying correctly. Maybe there is a disconnect here between ApolloClient and Prisma or ApolloClient and the database? Any help would be much appreciated.
All of the code is below.
helper.ts
function graphqlTestContext() {
let serverInstance: ServerInfo | null = null;
return {
async before() {
const rootUrl = getRootUrl();
const httpLink = createHttpLink({
uri: rootUrl + "api/graphql",
credentials: "include",
fetch
});
const client = new ApolloClient({
// ssrMode: typeof window === "undefined",
link: httpLink,
cache: new InMemoryCache(),
});
return client;
},
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() {
// Generate a unique schema identifier for this test context
schema = `test_${nanoid()}`;
// Generate the pg connection string for the test schema
databaseUrl = `${process.env.ROOT_DB_URL}/testing?schema=${schema}`;
// Set the required environment variable to contain the connection string
// to our database test schema
process.env.DATABASE_URL = databaseUrl;
// Run the migrations to ensure our schema has the required structure
execSync(`${prismaBinary} migrate dev`, {
env: {
...process.env,
DATABASE_URL: databaseUrl,
},
});
// Construct a new Prisma Client connected to the generated Postgres schema
prismaClient = new PrismaClient();
return prismaClient;
},
async after() {
// Drop the schema after the tests have completed
const client = new Client({
connectionString: databaseUrl,
});
await client.connect();
await client.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
await client.end();
// Release the Prisma Client connection
await prismaClient?.$disconnect();
},
}
User.int.test.ts
const ctx = createTestContext();
describe("User", () => {
it("creates a new user with REGISTER_MUTATION", async () => {
const userResult = await ctx.client.mutate({
mutation: gql`
mutation Register(
$firstName: String!
$lastName: String!
$email: String!
$password: String!
) {
registerUser(
firstName: $firstName
lastName: $lastName
email: $email
password: $password
) {
user {
email
firstName
}
}
}
`,
variables: {
firstName: "FirstName",
lastName: "LastName",
email: "test#email.com",
password: "password"
}
});
expect(userResult).toMatchInlineSnapshot(`
Object {
"data": Object {
"registerUser": Object {
"__typename": "UserLoginPayload",
"user": Object {
"__typename": "User",
"email": "test#email.com",
"firstName": "FirstName",
},
},
},
}
`);
});
it("verifies that user persists", async () => {
const persistedData = await ctx.prisma.user.findMany();
expect(persistedData).toMatchInlineSnapshot(`Array []`);
});
});
The reason is because graphql server is instantiated with different prisma client with its own db. And the prismaTestContext has its own prisma client with different db url.

NestJS: This operation is not supported by Mongodb driver

I am trying to get all the elements from database but stucking with this error that says:
This operation is not supported by Mongodb driver.
I am using MongoDB along with Mongoose to interact with database.
Here is my code where the error happening:
import { GetTasksFilterDto } from './dto/get-tasks-filter.dto';
import { TaskStatus } from './task-status.enum';
import { CreateTaskDto } from './dto/create-task.dto';
import { TaskEntity } from './task.entity';
import { Repository, EntityRepository } from 'typeorm';
#EntityRepository(TaskEntity)
export class TaskRepository extends Repository<TaskEntity> {
async getTasks(filterDto: GetTasksFilterDto): Promise<TaskEntity[]> {
const { status, search } = filterDto;
const query = this.createQueryBuilder('task');
// The error happen in this line
const tasks = await query.getMany();
return tasks;
}
}
Will this TypeORM MongoDB Documentation did the job for me.
The issue was that, the way I am doing it is wrong, mongodb doesn't support that way of queries, instead I must use the proper way to do it which by using MongoRepository that allows us to create a manager for any Entity.
The code below shows how I solved the problem:
async getTasks(filterDto: GetTasksFilterDto): Promise<TaskEntity[]> {
const { status, search } = filterDto;
const manager = getMongoRepository(TaskEntity);
const tasks = await manager.find({
status: status,
where: {
$or: [
{ text: Like(`%${search.toString()}%`) },
{ title: Like(`%${search.toString()}%`) },
],
},
});
return tasks;
}

Meteorjs collection can't be accessed /w async when used with 'export const'

Okay I am getting into the basics of meteor but I still can't figure what is going on when I define my collections for both server/client using
// /lib/collections.js
import { Mongo } from 'meteor/mongo';
export const Info = new Mongo.Collection('info');
export const Name = new Mongo.Collection('name');
export const Dates = new Mongo.Collection('date');
but then I run on my server a publish
// /server/main.js
Meteor.publish('insertByName', function(query) {
AsyncAPICall.findName(nameVar, Meteor.bindEnvironment(function(err, names) {
Name.upsert(query.blob, query.set);
}));
});
I get
Exception in callback of async function: ReferenceError: Name is not defined
if I edit my collection to
// lib/collections.js
import { Mongo } from 'meteor/mongo';
Info = new Mongo.Collection('info');
Name = new Mongo.Collection('name');
Dates = new Mongo.Collection('date');
the upsert works fine. BUT there is a problem with retrieving the data on the client with subscribe
I run a
// /server/main.js
Meteor.publish('getName_publish', function () {
return Name.find();
});
and
// /client/main.js
import {
Summoners,
Champions,
SummonersByName
} from '../lib/collections.js';
import '/client/template/page.js';
// /client/template/page.js
Template.page.onCreated(function pageOnCreated() {
Meteor.subscribe('getName_publish');
});
Template.page.helpers({
byname() {
return Name.find({}, { sort: { updated_at: -1 } }); //{}, { sort: { updated_at: -1 } }
},
});
my object ends up empty.
Basically if there is export const I can't upsert to the Mongo collection, if there isn't I can't retrieve the records.
Update If I use Name.find().fetch() in the browser console it returns the object as it's supposed to, but not inside the Template.page.helpers or on Template.page.onCreated