Why won't this nuxt-socket-io emitter trigger its action? - websocket

I am trying to get nuxt-socket-io working on my NuxtJS application, but my emit functions do not seem to trigger the actions in my vuex store.
nuxt.config.js has the following code:
modules: [
'#nuxtjs/axios',
'nuxt-socket-io'
],
io: {
sockets: [
{
name: 'main',
url: process.env.WS_URL || 'http://localhost:3000',
default: true,
vuex: {
mutations: [],
actions: [ "subscribeToMirror" ],
emitBacks: []
},
},
]
},
That subscribeToMirror action is present in my vuex store (in index.js):
export const actions = {
async subscribeToMirror() {
console.log('emit worked');
try {
new TopicMessageQuery()
.setTopicId(state.topicId)
.setStartTime(0) // TODO: last 3 days
.subscribe(HederaClient, res => {
console.log("Got response from mirror...");
return res;
});
} catch (error) {
console.error(error);
}
}
};
And that action should be triggered by the emit in my index.vue script:
mounted() {
this.socket = this.$nuxtSocket({
name: 'main',
reconnection: false
})
},
methods: {
...mapMutations([
'setEnv',
'initHashgraphClient',
'setTopicId',
'createNewTopicId'
]),
...mapActions([
'createAndSetTopicId'
]),
subscribeToMirror() {
console.log("method worked");
return new Promise((res) => {
this.socket.emit('subscribeToMirror', {}, (resp) => {
console.log(resp)
resolve()
})
})
}
}
While I can see the 'method worked' console output from index.vue's subscribeToMirror method, I have never seen the 'emit worked' message. I have played around with this for hours, copying the instructions from this guide but have had no success.
Can anyone spot what I'm doing wrong?
UPDATE: I tried copying the code from this example and was unable to get a response from that heroku page. So it appears that I am completely unable to emit (even though $nuxtSocket appears to be functional and says it's connected). I am able to confirm that the socket itself is up and running, as I was able to get responses from it using the ticks from that example. I'm putting the repo for this project up here for viewing.
UPDATE2: I made a much simpler project here which is also not functioning correctly but should be easier to examine.

It turns out that while nuxt-socket-io functions as a wrapper for socket.io stuff you still need to actually create the server. This is a good template for how to do this

Related

Strapi returns 404 for custom route only when deployed to Heroku

I have created a custom route in Strapi v4 called "user-screens". Locally I hit it with my FE code and it returns some data as expected. However when I deploy it to Heroku and attempt to access the endpoint with code also deployed to Heroku it returns a 404. I've tailed the Heroku logs and can see that the endpoint is hit on the server side, but the logs don't give anymore info other than it returned a 404.
I am doing other non custom route api calls and these all work fine on Heroku. I am able to auth, save the token, and hit the api with the JWT token and all other endpoints return data. This is only happening on my custom route when deployed to Heroku. I've set up cors with the appropriate origins, and I am wondering if I need to add something to my policies and middlewares in the custom route. I have verified the permissions and verified the route is accessible to authenticated users in the Strapi admin.
Here is my route:
module.exports = {
routes: [
{
method: "GET",
path: "/user-screens",
handler: "user-screens.getUserScreens",
config: {
policies: [],
middlewares: [],
},
},
],
};
And my controller:
"use strict";
/**
* A set of functions called "actions" for `user-screens`
*/
module.exports = {
getUserScreens: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
}
strapi.entityService
.findMany("api::screen.screen", {
owner: user.id,
populate: ["image"],
})
.then((result) => {
ctx.send(result);
});
},
};
For anyone facing this, the answer was to change how I returned the ctx response from a 'send' to a 'return' from the controller method. I am not sure why this works locally and not on Heroku, but this fixes it:
New controller code:
module.exports = {
getUserScreens: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
}
return strapi.entityService
.findMany("api::screen.screen", {
owner: user.id,
populate: ["image"],
})
.then((result) => {
return result;
})
.catch((error) => {
return error;
});
},
};

Which `apollo-server-express` Version Work Best For These Apollo Server Packages?

I’m trying to get apollo-server-lambda or apollo-server-express to work with an executable schema for v3.36.
Here are the packages we use:
apollo-server-express#3.36 or apollo-server-lambda#3+
graphql-constraint-directive#3.0.0
#graphql-tools/schema#7.1.3
I ran multiple regression test to make it work, and it does not seem to hit GraphQL.
Here’s my Apollo server config:
const apolloServer = new ApolloServer({
schema: initializeSchema(),
plugins: [
ApolloServerPluginLandingPageGraphQLPlayground(),
{
didEncounterErrors(errors) {
logger.info(`didEncounterErrors:`)
logger.info(errors)
},
async requestDidStart(requestContext) {
logger.info(`Request started! ${requestContext}`);
return {
async parsingDidStart(requestContext) {
logger.info(`Parsing started! ${requestContext}`);
},
async validationDidStart(requestContext) {
logger.info(`Validation started! ${requestContext}`);
}
}
},
}],
context: async ({ event, context, express }) => {
logger.info(`Loading event... ${JSON.stringify(event)}`)
const newContext = {
headers: event.headers,
functionName: context.functionName,
event,
context,
expressRequest: express.req,
user: {} ?? null,
}
logger.info(`context ${JSON.stringify(newContext)}`)
return newContext
},
dataSources: () => {
logger.info('!initializing datasource')
initializeDbConnection()
return {}
},
...(['staging', 'production', 'demo'].includes(process.env.stage as string)
? { introspection: false, playground: false }
: {}),
})
I was able to log the executable schema inside initializeSchema, but it does not seem to hit the GraphQL Typedef and Resolver after upgrading. It just goes straight to context. So, I'm kinda stumped how to make HTTP request hit the Typedef and Resolvers using makeExecutableSchema()
I just need some advise or a list of table that could help me which version works best with the given apollo-server-<server_version>.

Pubsub publish multiple events Apollo Server

I am using Apollo Server and I want to publish 2 events in the row from same resolver. Both subscriptions are working fine but only if I dispatch only one event. If I try to dispatch both, second subscription resolver never gets called. If I comment out the first event dispatch second works normally.
const publishMessageNotification = async (message, me, action) => {
const notification = await models.Notification.create({
ownerId: message.userId,
messageId: message.id,
userId: me.id,
action,
});
// if I comment out this one, second pubsub.publish starts firing
pubsub.publish(EVENTS.NOTIFICATION.CREATED, {
notificationCreated: { notification },
});
const unseenNotificationsCount = await models.Notification.find({
ownerId: notification.ownerId,
isSeen: false,
}).countDocuments();
console.log('unseenNotificationsCount', unseenNotificationsCount);// logs correct value
// this one is not working if first one is present
pubsub.publish(EVENTS.NOTIFICATION.NOT_SEEN_UPDATED, {
notSeenUpdated: unseenNotificationsCount,
});
};
I am using default pubsub implementation. There are no errors in the console.
import { PubSub } from 'apollo-server';
import * as MESSAGE_EVENTS from './message';
import * as NOTIFICATION_EVENTS from './notification';
export const EVENTS = {
MESSAGE: MESSAGE_EVENTS,
NOTIFICATION: NOTIFICATION_EVENTS,
};
export default new PubSub();
Make sure, that you use pubsub from context of apollo server, for example:
Server:
const server = new ApolloServer({
schema: schemaWithMiddleware,
subscriptions: {
path: PATH,
...subscriptionOptions,
},
context: http => ({
http,
pubsub,
redisCache,
}),
engine: {
apiKey: ENGINE_API_KEY,
schemaTag: process.env.NODE_ENV,
},
playground: process.env.NODE_ENV === 'DEV',
tracing: process.env.NODE_ENV === 'DEV',
debug: process.env.NODE_ENV === 'DEV',
});
and example use in resolver, by context:
...
const Mutation = {
async createOrder(parent, { input }, context) {
...
try {
...
context.pubsub.publish(CHANNEL_NAME, {
newMessage: {
messageCount: 0,
},
participants,
});
dialog.lastMessage = `{ "orderID": ${parentID}, "text": "created" }`;
context.pubsub.publish(NOTIFICATION_CHANNEL_NAME, {
notification: { messageCount: 0, dialogID: dialog.id },
participants,
});
...
}
return result;
} catch (err) {
log.error(err);
return sendError(err);
}
},
};
...
It has been a while since this moment.
I have also been a struggle with pubsub not working problem.
and I would like to see your ApolloClient setup code.
I changed my configurations with regard to graphql version and client-side setup.
graphql version : 14.xx.xx -> 15.3.0
const client = new ApolloClient({
uri: 'http://localhost:8001/graphql',
cache: cache,
credentials: 'include',
link: ApolloLink.from([wsLink, httpLink])
});
I want you to clarify link order, especially about httpLink, if you use in your case, "HttpLink is a terminating Link.", according to Apollo official site.
At first, I used link order [httpLink, wsLink].
Therefore, pubsub.publish didn't work.
I hope this answer will help some of graphql users.

Nuxt: Proxy VS Async data VS Reload page

I am building a nuxt application and I am facing an issue with Proxy and Async data.
This is my nuxt.config (simplified)
modules: [
'#nuxtjs/axios',
'#nuxtjs/proxy'
],
axios: {
proxy: true
},
proxy: {
'/api': {
target: 'http://www.example.com',
pathRewrite: {
'^/api': '/'
}
}
}
This is my asyncData code fragment (simplified):
async asyncData ({ store }) {
await store.dispatch('fetchData')
}
Store action fetchData code (simplified):
async fetchData({ commit }) {
const response = await myService.fetchData()
commit('setData', response.data)
}
And at last, myService function (simplified):
fetchData () {
return axios.get('/api/path-to-my-resource')
}
What is expected:
To have the service triggering a call to the proxied endpoint, on both cases: visiting the page through a link or refreshing the page
What is happening:
When I hit refresh on the page, instead of firing a call to the http://www.example.com/path-to-my-resource, I see that it tries to do it at /api/path/to-my-resource and of course it fails. From what I understand, when I refresh the page, the proxy is not working inside the asyncData hook.
I am pretty sure that there is something that I attempt wrongly, but I cannot find it. Can someone point me towards the right direction?
Try something like:
proxy: {
'/api/': { target: 'http://www.example.com', pathRewrite: {'^/api/': ''} }
// ^^^^^ ^^^^^^ ^^
// Note the ending slashes.
// And the rewrite rule.
}
That's how the docs are written:
http (ky) module: https://http.nuxtjs.org/api/#proxy
Axios module: https://axios.nuxtjs.org/options#proxy

How to stub a call to graphql using cypress?

I'm writing a Vue app that uses vue-apollo to interact with graphql. I'm wondering if it's possible to stub the graphql requests. I thought this should work:
it('should access a story', function() {
cy.server();
cy.route('http://localhost:3002/graphql', {
data: {
Story: { id: 2, title: 'story title', content: 'story content' }
}
});
cy.visit('/stories/2');
});
Unfortunately, I get an error from graphql complaining that id is an Int instead of an ObjectId. Am I missing something?
The problem was that stubbing fetch requests isn't yet implemented in Cypress (which is what Vue Apollo is using). I ended up following these instructions:
Install github/fetch
Add this to cypress/support/index.js:
.
Cypress.on('window:before:load', win => {
win.fetch = null;
win.Blob = null;
});
Now it works!
I got it working with this package here:
npm i #iam4x/cypress-graphql-mock
Add this line to 'support/commands.js'
import "#iam4x/cypress-graphql-mock";
go to your graphiql playground and download your schema
add task command to 'plugins/index.js' (REMEMBER TO CHANGE PATH TO SCHEMA FILE YOU DOWNLOADED EARLIER)
module.exports = (on, config) => {
on("task", {
getSchema() {
return fs.readFileSync(
path.resolve(__dirname, "../../../schema.graphql"),
"utf8"
);
}
});
};
write your tests with loaded schema
beforeEach(() => {
cy.server();
cy.task("getSchema").then(schema => {
cy.mockGraphql({
schema
});
});
});`
describe("Login Form", () => {
it("should redirect after login", () => {
cy.mockGraphqlOps({
operations: {
Login: {
login: {
jwt: "some-token",
user: {
id: "5d5a8e1e635a8b6694dd7cb0"
}
}
}
}
});
cy.visit("/login");
cy.getTestEl("email-input").type("Max Mustermann");
cy.getTestEl("password-input").type("passwort");
cy.getTestEl("submit").click();
cy.getTestEl("toolbar-title").should("exist");
});
})
Visit the original repo for further explanation as i find it less confusing. The package you have installed is just a working fork of this one:
https://github.com/tgriesser/cypress-graphql-mock

Resources