Why is Koa-Pug returning Not Found in included code? - koa

I have the following code...
// File 1
import {Application2} from "./Application2.mjs";
const app = new Application2();
app.start(()=>{
console.log("Application has been started")
});
// File 2
import Koa from "koa";
import Router from "koa-router";
import Pug from "koa-pug";
import path from 'path';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
const PORT = process.env.PORT || 3001;
export class Application2{
constructor(){
console.log(`This thing ${__dirname}/views`)
this.app = new Koa();
this.pug = new Pug({
app: this.app,
viewPath: `${__dirname}/views`
});
const router = new Router();
router.get("/", function(ctx){
ctx.render('index');
})
this.app.use(router.routes());
}
start(callback){
this.app.listen(PORT, callback);
}
}
When I run this code I see the correct path in the console. However, when I try to go to the site I just see...
I can't figure out why this is happening, can someone help? It seems to match the examples provided here

Ugghhh missed this...
router.get("/", async (ctx) => {
await ctx.render('index');
})

Instead of doing this:
router.get('/', function(ctx){
ctx.render('index')
})
Try This
my_route.get('/', async (body) => {
await body.render('index')
})

Related

API Routes on Next.JS with Apollo-Server : why does using a basePath cause error?

I'm using API Routes on a Next.JS app with Apollo-Server, to create a GraphQL API wrapper around a REST endpoint. But I'm running into an issue if the project has a bathPath.
I've been following this example, and a video tutorial on youtube.
I've replicated my issue by using the repo from that tutorial. Upon running that code $ yarn dev, and navigating to http://localhost:3000/api/graphql the GraphQl playground shows up, and works as expected.
However if I add a basepath to the project then the graphQl playground still shows up fine at http://localhost:300/basepath/api/graphql but it gives me the error of "Server cannot be reached" and shows a 404 error in the network tab on the dev tools.
To add the base path I created a next.config.js and added
module.exports = {
basePath: '/basepath'
}
In pages/api/graphql.ts I updated the path from /api/graphql to /basepath/api/graphql
import { ApolloServer } from "apollo-server-micro";
import { schema } from "src/schema";
const server = new ApolloServer({ schema });
const handler = server.createHandler({ path: "/somewhere/api/graphql" });
export const config = {
api: {
bodyParser: false,
},
};
export default handler;
In src/apollo.ts I updated the HttpLink uri from /api/graphql to /basepath/api/graphql
import {
ApolloClient,
InMemoryCache,
NormalizedCacheObject,
} from "#apollo/client";
import { useMemo } from "react";
let apolloClient: ApolloClient<NormalizedCacheObject>;
function createIsomorphicLink() {
if (typeof window === "undefined") {
// server
const { SchemaLink } = require("#apollo/client/link/schema");
const { schema } = require("./schema");
return new SchemaLink({ schema });
} else {
// client
const { HttpLink } = require("#apollo/client/link/http");
return new HttpLink({ uri: "/bathpath/api/graphql" });
}
}
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: createIsomorphicLink(),
cache: new InMemoryCache(),
});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
if (initialState) {
_apolloClient.cache.restore(initialState);
}
if (typeof window === "undefined") return _apolloClient;
apolloClient = apolloClient ?? _apolloClient;
return apolloClient;
}
export function useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
Any ideas why adding a basepath would break this setup? and what I'd need to do to fix it?
This is my first time posting on stack overflow, so I hope my description is good enough, please do ask if I've missed anything and thanks for your help in advance!

Nest could not find GraphQLModule element

I'm trying to write the e2e test for my backend app (nestjs, grpahql, mongodb).
This is my test:
import { INestApplication } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { Test, TestingModule } from '#nestjs/testing';
import {
ApolloServerTestClient,
createTestClient,
} from 'apollo-server-testing';
import gql from 'graphql-tag';
import { UserModule } from '../src/user/user.module';
import { MongooseModule } from '#nestjs/mongoose';
import config from '../src/environments/environment';
describe('User', () => {
let app: INestApplication;
let apolloClient: ApolloServerTestClient;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [UserModule, MongooseModule.forRoot(config.mongoURI)],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
const module: GraphQLModule = moduleFixture.get<GraphQLModule>(
GraphQLModule,
);
apolloClient = createTestClient((module as any).apolloServer);
});
it('should get users', async () => {
const { query } = apolloClient;
const result: any = await query({
query: gql`
query {
getUsers {
_id
name
}
}
`,
variables: {},
});
console.log(result);
});
});
I face this error:
Nest could not find GraphQLModule element (this provider does not exist in the current context)
Could someone share a working example or point me what is wrong?
It looks like GraphQLModule is not imported in the scope of your TestModule. If so, the context will never be able to provide it using get().
Also, this might not help you but this is what we do in our projects:
beforeAll(async () => {
const TCP_PORT = 4242;
const testingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
gqlClient = new ApolloClient({
uri: `http://localhost:${TCP_PORT}/graphql`,
fetch: fetch as any,
cache: new InMemoryCache({
addTypename: false,
}),
});
app = testingModule.createNestApplication();
await app.listen(TCP_PORT);
});
I did not add all the imports but here are the most relevant:
import ApolloClient, { gql, InMemoryCache } from 'apollo-boost';
import fetch from 'node-fetch';
I assume you know the other ones and/or don't need them

Can't access req from context

I'm using Koa.js with Apollo Server's apollo-server-koa.
I've debug the { req } and the value is undefined.
I've followed the documentation, but still got no clue.
Even if I access the req.headers.authorization and put this on HTTP Header of graphql gui:
{
"authorization": "bla"
}
the value is still undefined.
app.ts:
import cors from "#koa/cors";
import Koa from "koa";
import config from "./config/environtment";
import server from "./server";
const PORT: number = config.port;
async function bootstrap() {
try {
const app: Koa = new Koa();
server.applyMiddleware({ app });
app
.use(cors())
.listen(PORT, () =>
console.log(
`Server running on http://localhost:${PORT}${server.graphqlPath}`,
),
);
} catch (error) {
console.error(error);
}
}
bootstrap();
server.ts:
import { ApolloServer } from "apollo-server-koa";
import typeDefs from "./graphql/schema";
import resolvers from "./graphql/resolvers";
import context from "./graphql/context";
export default new ApolloServer({
typeDefs,
resolvers,
context,
});
context.ts
export default ({ req }) => {
console.log(req) // return undefined.
return {
test: "test",
};
};
The docs are specific to apollo-server, which uses apollo-server-express under the hood. I believe for apollo-server-koa, the options are passed in an object with a ctx field that holds the Koa Context. So the following should work:
export default ({ ctx }) => {
console.log(ctx.request)
console.log(ctx.response)
return {};
};

Handling apollo graphql errors globally and render custom ErrorHandler component on error

Need to handle Apollo graphql errors globally in client side and render custom ErrorHandler component on error . So I used Apollo's afterware and apollo-link-error
import ApolloClient from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { onError } from 'apollo-link-error'
const httpLink = new HttpLink({ uri: '/graphql' });
const logoutLink = onError(({ networkError }) => {
if (networkError.statusCode === 401) {
//need to dispatch a redux action so that ErrorHandler component renders
}
})
const client = new ApolloClient({
link: logoutLink.concat(httpLink),
});
My solution for this (which I guess, is not the correct approach)
import ApolloClient from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { onError } from 'apollo-link-error';
import { render } from 'react-dom';
import ErrorHandler from '../utils/ErrorHandler';
const httpLink = new HttpLink({ uri: '/graphql' });
const logoutLink = onError(({ networkError }) => {
if (networkError.statusCode === 401) {
const targetDiv = document.getElementById('serviceErrorHandler');
render(
<ErrorHandler message={networkError.message}/>,
targetDiv
);
}
})
const client = new ApolloClient({
link: logoutLink.concat(httpLink),
});
Please suggest an approach for my scenario. Thanks in advance
Had this same problem, one solution we went with was making a function that returns onError and take a parameter (the store):
const errorHandler = store => onError((errors) => {
if (errors.networkError) {
store.dispatch(createApolloErrorAction({
message: GENERIC_ERROR_FETCHING_STRING,
}));
}
});
And use it in a wrapper functions to pass in the store:
let apolloClient = null;
export const createApolloClient = (reduxStore) => {
const cache = new InMemoryCache();
const link = errorHandler(reduxStore).concat(otherLink);
apolloClient = new ApolloClient({ link });
return apolloClient;
};
export const getApolloClient = () => apolloClient;

What is the recommended way to pass Apollo Client around in a React app?

Right now I am using the HOC withApollo like:
export default connect(mapStateToProps, mapDispatchToProps)(withApollo(withData(Browse)));
then in that component:
render() {
const { client } = this.props;
<Button onPress={() => searchInterestsTab(client)} />
then outside that component:
export const searchInterestsTab = (client) => {
^ but am finding this gets very messy having to pass it into every outside function from my component.
Couldn't I just use:
const apolloClient = new ApolloClient({...})
export default apolloClient;
then:
import apolloClient from './apolloClient';
everywhere?
It should be possible to use it with kind of:
import apolloClient from './apolloClient'
If you look at the usage documantation you see that you can use it. So somewhere most possible in your index.js you should already have
const apolloClient = new ApolloClient({...})
My apollo client is instantiated like this:
import ApolloClient, { addTypename } from 'apollo-client';
const createApolloClient = options => {
return new ApolloClient(Object.assign({}, {
queryTransformer: addTypename,
dataIdFromObject: (result) => {
if (result.id && result.__typename) {
return result.__typename + result.id;
}
return null;
},
}, options))
};
export default createApolloClient;
and in the index.js it is used like this:
...
const client = createApolloClient({
networkInterface: networkInterface,
initialState: window.__APOLLO_STATE__,
ssrForceFetchDelay: 100,
});
....
export {
client,
...
};

Resources