Why is my apollo-server-express instance hanging due to resolvers? - express

I've recently wanted to get back into programming, and I know that Apollo GraphQL has moved to an asynchronous way to firing up the server per their documentation.
Since switching (and following docs), I can't get my server to fire up, and I don't know why.
When the server attempts to run, it hangs on the execution of .start() on my ApolloServer instance, even though I'm giving it (what I think) are both valid type definitions and resolvers.
The current iteration of my tiny boilerplate project is located here on CodeSandbox.
When I run this code locally, I receive the following error (which isn't shown on CS?):
Argument type {typeDefs: DocumentNode, resolvers: {Query: {hello(): string}}} is not assignable to parameter type ApolloServerExpressConfig
This error is on line 9, where the instance of ApolloServer is created.
I don't know what I'm doing wrong. I was previously using babel-plugin-import-graphql but switched away from that to using a normal JS import w/ the gql tag just to be safe. The problem appears to be with the resolver map, which doesn't make sense:
const resolvers = {
Query: {
hello: () => "world!"
}
};
export default resolvers;
Anyway, thanks in advance! Would love to get this sorted out today. I think if I don't, I'll end up just switching over to using Meteor for full-stack stuff and then use React for the front-end and just not worry about it anymore.

Related

How do I troubleshoot this api call?

I have the following code...
async function GetFirstAssessment() {
try {
const response = await axios.get('http://192.168.254.10/App/GetFirstAssessment/');
return response.data;
} catch (error) {
alert('error: ' + error);
console.error(error);
}
};
It's been working fine for some time, but suddenly it no longer works and eventually times out. Or I don't even know if it "times out" since I believe the default timeout for axios is 0 but eventually it does error with the message "Error: Network Error". I've also added a picture of the stack trace but I don't think it's helpful.
I can put the url in a browser and it returns the json I'm expecting, so the problem is definitely not on the server side. I am testing from an android device connected via usb and developing with cli (not expo).
If there is any other information I can provide please let me know... not sure what to do next because this really makes no sense. I would wonder if it was a security issue except that it was working perfectly earlier. Also I have updated some other code that calls this, but even after reverting I still have the same problem... and seeing as how it is making it to the catch, I don't see how any other code could be affecting this.
I did just install the standalone react native debugger. I believe it has worked since I installed it, though I'm not 100% certain on that. Still doesn't work after closing it.
I set a break point in the server code on the first line of the api method, but it doesn't get hit. Not sure how to troubleshoot further up the chain though. I also just thought to check fiddler and it doesn't show any request coming in, though I honestly don't know if it should normally or not.

How would you redirect calls to the top object in Cypress?

In my application code, there are a lot of calls (like 100+) to the "top object" referring to window.top such as top.$("title") and so forth. Now, I've run into the problem using Cypress to perform end-to-end testing. When trying to log into the application, there are some calls to top.$(...) but the DevTools shows a Uncaught TypeError: top.$ is not a function. This resulted in my team and I discovering that the "top" our application is trying to reach is the Cypress environment itself.
The things I've tried before coming here are:
1) Trying to stub the window.top with the window object referencing our app. This resulted in us being told window.top is a read-only object.
2) Researching if Cypress has some kind of configuration that would smartly redirect calls to top in our code to be the top-most environment within our app. We figured we probably weren't the only ones coming across this issue.
If there were articles, I couldn't find any, so I came to ask if there was a way to do that, or if anyone would know of an alternate solution?
Another solution we considered: Looking into naming window objects so we can reference them by name instead of "window" or "top". If there isn't a way to do what I'm trying to do through Cypress, I think we're willing to do this as a last resort, but hopefully, we don't have to change that, since we're not sure how much of the app it will break upfront.
#Mikkel Not really sure what code I can provide to be useful, but here's the code that causes Cypress to throw the uncaught exception
if (sample_condition) {
top.$('title').text(...).find('content') // Our iframe
} else {
top.$('title').text(page_title)
}
And there are more instances in our code where we access the top object, but they are generally similar. We found out the root cause of the issue is that within Cypress calls to "top" actually interface with Cypress instead of their intended environment which is our app.
This may not be a direct answer to your question, it's just expanding on your request for more information about the technique that I used to pass info from one script to another. I tried to do it within the same script without success - basically because the async nature of .then() stopped it from working.
This snippet is where I read a couple of id's from sessionStorage, and save them to a json file.
//
// At this point the cart is set up, and in sessionStorage
// So we save the details to a fixtures file, which is read
// by another test script (e2e-purchase.js)
//
cy.window().then(window => {
const contents = {
memberId: window.sessionStorage.getItem('memberId'),
cartId: window.sessionStorage.getItem('mycart')
}
cy.writeFile(`tests/cypress/fixtures/cart.json`, contents)
})
In another script, it loads the file as a fixture (fixtures/cart.json) to pull in a couple of id's
cy.fixture(`cart`).then(cart => {
cy.visit(`/${cart.memberId}/${cart.cartId}`)
})

Retrieve a file before anything else happens

Iʼm creating a simple SPA that will retrieve data from an API. The page itself is served by a separate backend process which is the only entity that knows the API address. As such, it also provides an endpoint that, among other things, returns the API URL:
{
"api_url_base": "http://api.example.org/v1"
}
This is needed because the whole thing is deployed at multiple sites where we donʼt have control over DNS records and it may or may not be easy to derive the API URL from the front end appʼs.
Now i need to write my Vue app so nothing can happen until i fetch and process this file. To achieve that, i added to the appʼs beforeMount method:
this.settings = axios.get('/settings.json');
and in my componentsʼ beforeMount:
var comp = this;
app.__vue__.settings.then((response) => {comp.url = response.data.api_url;});
However,it seems the componentʼs beforeMounted often runs before the appʼs, and app. __vue__.settings is undefined when i get to the componentʼs beforeMount.
Where do i go wrong? Am I putting things at wrong places, or is my approach completely wrong?
You can fetch data before mount the vue app.
axios.get('/settings.json').then(response => {
// do something with response
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
}
One way (as suggested in the previous answer) is to make one more call, before anything else. However it brings numerous downsides.
Let me just say that it freezes the loading of your application until the response is received.
There is hope as you can cleverly use (f.e.) good ol' dependency injection to pass the required data to your app.
This article answers this question fully and completely: https://codeburst.io/passing-configuration-to-vue-js-1b96fa8f959

Relay modern caching example

I would like to enable caching in my react native application. I am using GraphQL with Relay modern. I found out that caching is not enabled by default in relay modern, but they have exposed RelayQueryResponseCache from relay-runtime, which we can add to the fetchQuery function in our API. I read discussion here and here about it, but have not seen any example to get started. Can someone help me out on this?
EDIT:
Ok I came up with a solution. I think it misses few things but so far it serves our needs.
I have noticed that passing anything into QueryRenderer into cacheConfig results passing that value into fetchQuery function inside my environment.
So I have created a Component which loads the data by some relation and resolves it into the correct json structure requested by the query. Then I return this into the state. Then I extended my Component which contains QueryRenderer with the created 'cache loader'. Now when componentWillMount() is called I ask for the cached data. During this I have set this.state.loading = true so I am able to handle loading state. Reading from DB is async.
I am using this class in other components as well. Every one handles its cache data. I just pass it to QueryRenderer.
However I was thinking that this makes some extra logic need to add for each Component which is supported by this caching. Probably passing the cache resolver as cacheConfig and resolve the cached data immediately inside the environment would be much more cleaner.

How to use hapi-swaggered without a running server

I have a working hapi service, complete with hapi-swaggered and hapi-swaggered-ui. This is useful for many cases, but I want to add a build step to my CI which will be able to get the JSON generated by hapi-swaggered (which, if changed, would get compiled that into an .Net assembly that gets stored in a local proget).
I know that if I really wanted to, on my build server, I could start an instance of my server, curl to localhost:3000/swagger, kill the server, and proceed, but that seems a little risky (i.e., what if I have two builds running at the same time?).
Has anyone developed a way to directly call the hapi-swaggered API to get the raw JSON?
Well, that didn't take too much longer, but I think I found one solution. In this case, internals is my server. It does not auto-start if its loaded (required'ed) from another file, and the compose method is exposed to use hapi's Glue.compose to assemble the service. It seems that I can then use the inject method to simulate a call.
'use strict';
var internals = require('./');
internals.compose(function(err, server) {
server.inject({ method: 'GET', url: '/swagger' }, function (response) {
console.log(JSON.stringify(response.result));
process.exit();
});
});
If there's anything that I'm missing about this technique, I'd like to hear about it.