Node.js Inter-process communication Faulters - javascript

Given the following parent-process code:
//SSO
this.sso = fork('./app/utils/SSOproxy.js', [], {
stdio: [0, 1, 2, 'ipc']
});
console.log(process);
console.log(this.sso);
//__handshake
this.sso.send({
opcode: 'ACK',
params: [],
ref: null
});
console.log('STEP_1');
process.prependOnceListener('message', ((msg) => {
if (msg.status) {
if ((msg.opcode === 'ACK') && (msg.params[0] === 'ok')) {
console.log('STEP_3');
}
}
}));
//__e.o.handshake
And child-process (SSOproxy.js) code:
process.on('message', ((msg) => {
switch (msg.opcode) {
//handshake
case 'ACK':
process.send({
opcode: 'ACK',
params: ['ok'],
ref: null
});
console.log('STEP_2');
break;
//Other paths...
}
));
In the log observed - STEP_1 is followed by STEP_2 but I never see STEP_3 because I can't for-the-life of me figure out how to get duplex communication for child/parent. How to achieve the same?

In your prependOnceListener you have a condition for msg.status but I don't see this anywhere in your SSOproxy.js code.
This means your if will never evaluate true
Can you try adding a status to your message:
process.send({
opcode:'ACK',
params:['ok'],
ref: null,
status: 'test1234'
});

Related

Cannot read req.body in Next.js 13 middeware

In the code below I want to validate the request body with a schema from zod, currently, it will fail and catch. This is because req.body is returning a ReadableStream<Uint8Array> and not the object that it expects to parse.
export default async function middleware(req: NextRequest, res: NextResponse) {
const { pathname } = req.nextUrl;
if (pathname.startsWith('/api/user/create')) {
try {
createUserSchema.parse({
body: req.body,
params: req.nextUrl.searchParams,
});
return NextResponse.next();
} catch (error: any) {
console.log(req.body);
return NextResponse.json(
{ success: false, message: error },
{ status: 422, headers: { 'content-type': 'application/json' } }
);
}
}
return NextResponse.next();
}
this below is the output of the console.log(req.body);
<ref *1> ReadableStream {
_state: 'readable',
_reader: undefined,
_storedError: undefined,
_disturbed: false,
_readableStreamController: ReadableStreamDefaultController {
_controlledReadableStream: [Circular *1],
_queue: S {
_cursor: 0,
_size: 0,
_front: { _elements: [], _next: undefined },
_back: { _elements: [], _next: undefined }
},
_queueTotalSize: 0,
_started: false,
_closeRequested: false,
_pullAgain: false,
_pulling: false,
_strategySizeAlgorithm: [Function],
_strategyHWM: 1,
_pullAlgorithm: [Function],
_cancelAlgorithm: [Function]
}
}
I did some research and found that I need to run some kind of conversion method on this ReadableStream. The problem is that most of these include the Buffer module which cannot be run on the Edge and therefore cannot work in the middleware.ts. Is there perhaps a polyfill that I can use?
"next": "^13.0.7"
Node v16.17.0
Next.js middleware does not work the same as an Express middleware because it only runs on navigation and does not act as a catch-all for your API endpoints.
As per the documentation, you can only access cookies, access/modify request headers and perform redirects and rewrites using this feature.
You can use
const body = await req.json()

chess.com API does'nt bring back some requests

So im very new to fullstack and been working on a little vanilla js project to make a website that calls a server I run that calls chess.com api, for example retrieving all elo ratings is:
https://api.chess.com/pub/player/${username}/stats
So I made a backend call in node-js:
const fetch = require('node-fetch');
exports.getChessManStats = () => {
return (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
const username = req.param('username');
console.log(req.param('username'));
fetch(`https://api.chess.com/pub/player/${username}/stats`)
.then(res2 => res2.json() )
.then(chessManData => {
res.json({
daily: chessManData.chess_daily.last.rating,
rapid: chessManData.chess_rapid.last.rating,
blitz: chessManData.chess_blitz.last.rating,
bullet: chessManData.chess_bullet.last.rating,
})
})
.catch(err => console.log(err));
}
};
the code then runs with express on the main.js with:
const app = express();
app.get('/getRating',chessManController.getChessManStats());
obviously later down the line I called app.listen(3000) .
So then at the frontend I made a button that calls this function :
const makeUserStats = () => {
const username = document.getElementById('username').value;//id=username is type input
document.getElementById('rating').innerHTML = `Searching`; //making the rating div into 'searching'
console.log(`http://localhost:3000/getRating?username=${username}`)//just seeing the sting I send
fetch(`http://localhost:3000/getRating?username=${username}`)
.then(rating => {
document.getElementsByClassName('statButton').disabled = true;//disabling buttons until the data arrives
console.log('got json');
return rating.json();
})
.catch(err => console.log(err))//looking for errors
.then((userRating => {
window.userRating = userRating;//saving the stats globaly to use in other buttons
window.user = username;
}))
.then(() => {
document.getElementsByClassName('statButton').disabled = false;//enabling the buttons again
document.getElementById('rating').innerHTML = `${window.user} rating is:`;
})
}
and now when I press the button it works with some usernames and with some dont.
YoniRamot (mine) works, hikaru (pro player) works, atomicstew (friend) doesnt work, idobl (friend) doesnt work. and the wierd part is it does'nt catch any errors, just waiting for answer that it never gets.
but if you go the the api they all exist:
https://api.chess.com/pub/player/yoniramot/stats -- mine
https://api.chess.com/pub/player/hikaru/stats --proplayer
https://api.chess.com/pub/player/atomicstew/stats --friend
https://api.chess.com/pub/player/idobl/stats --friend
the console of the backend shows:
atomicstew
TypeError: Cannot read property 'last' of undefined
at C:\Users\Yonatan\Desktop\coding\training\intermediateChess\backend\controllers\chessStats.js:12:45
at processTicksAndRejections (internal/process/task_queues.js:93:5)
meaning that the backend gets the username but does'nt find it in the api for some reason.
please help my mind is blowing at this point.
-edit 1-
So I added a console log before sending the res with the data, and it printed:
atomicstew
{
chess_rapid: {
last: { rating: 1228, date: 1612114999, rd: 28 },
best: {
rating: 1265,
date: 1611786478,
game: 'https://www.chess.com/live/game/6380128206'
},
record: { win: 233, loss: 202, draw: 19 }
},
chess_blitz: {
last: { rating: 902, date: 1611928398, rd: 50 },
best: {
rating: 1010,
date: 1609882454,
game: 'https://www.chess.com/live/game/6297568401'
},
record: { win: 26, loss: 24, draw: 4 }
},
fide: 0,
tactics: {
highest: { rating: 1659, date: 1609635730 },
lowest: { rating: 387, date: 1608148134 }
},
lessons: {},
puzzle_rush: {}
}
TypeError: Cannot read property 'last' of undefined
at C:\Users\Yonatan\Desktop\coding\training\intermediateChess\backend\controllers\chessStats.js:13:45
at processTicksAndRejections (internal/process/task_queues.js:93:5)
and the references I am calling are right there, so I am still stuck.
-edit 2-
I noe realized that if a player didnt play a certain game mode than the api doesnt hold that values. any ideas how to save the data as 0 or null if there is no data neatly?
Issue is in following block of code where you are trying to access last field on different properties in response:
res.json({
daily: chessManData.chess_daily.last.rating,
rapid: chessManData.chess_rapid.last.rating,
blitz: chessManData.chess_blitz.last.rating,
bullet: chessManData.chess_bullet.last.rating,
})
I had quick look at response for following API and it does not have chess_daily and chess_bullet properties.
https://api.chess.com/pub/player/atomicstew/stats
Since you are trying to access chessManData.chess_daily.last.rating and chess_daily is not present in chessManData, you are getting exception for .last.
In order to fix it, you can replace above block by following:
res.json({
daily: chessManData.chess_daily && chessManData.chess_daily.last ? chessManData.chess_daily.last.rating : null, // replace null with appropriate default value for rating
rapid: chessManData.chess_rapid && chessManData.chess_rapid.last ? chessManData.chess_rapid.last.rating : null,
blitz: chessManData.chess_blitz && chessManData.chess_blitz.last ? chessManData.chess_blitz.last.rating : null,
bullet: chessManData.chess_bullet && chessManData.chess_bullet.last ? chessManData.chess_bullet.last.rating : null,
})

How can I fix the overwritePermissions error?

I'm trying to make a mute command.I am using v12 version. While coding this command I got stuck in the Permissions part.
can you help me please
Commands ;
if (!muterole) {
try {
muterole = await message.guild.roles.create({ data: {
name: 'Muted',
color: '#000000',
permission: []
}});
message.guild.channels.cache.forEach(async (channel, id) => {
await channel.overwritePermissions(muterole, {
'SEND_MESSAGES': false,
'ADD_REACTION': false,
'CONNECT': false
});
});
} catch(e) {
console.log(e.message);
}
};
if (user.roles.cache.has(muterole)) return message.channel.send(`**${user.user.username}** Başarıyla tamamlandı.`)
user.roles.add(muterole)
message.channel.send(`**${user.user.username}, Başarıyla mutelendi!**`);
Error:
<node:4788> UnhandledPromiseRejectionWarning: TypeError [INVALID_TYPE]: Supplied overwrites is not an Array or Collection of Permission Overwrites.
overwritePermissions requires an array in the permission field like this.
channel.overwritePermissions([
{
id: muterole.id,
deny: ['SEND_MESSAGES', 'the rest of your permissions'],
},
], 'Needed to change permissions');
The way you have it here is used in updateOverwrite, which is the better option anyway because it doesn't remove all permissions you had on channels before.
So to fix this, simply replace overwritePermissions with updateOverwrite.

Assert exception details with JestJS

Question
I set up the following Jest test to ensure an exception is thrown:
it('can not rollback a step', async () => {
await expect(app.service('rides').patch(ride._id, {
currentStep: 1,
})).rejects.toThrow(BadRequest);
});
How can I assert the exception content?
Example
Considering this BadRequest error:
BadRequest {
type: 'FeathersError',
name: 'BadRequest',
message: 'invalid data',
code: 400,
className: 'bad-request',
data: {},
errors: [
{
message: 'currentStep must be greater than 1',
path: [Array],
type: 'array.min',
context: [Object]
}
],
I would like to check errors[0].message content, regardless the rest of the error object.
you catch and then analyze. Don't forget jest.assertions() to ensure code really throws.
jest.assertions(1);
try {
await app.service('rides').patch(ride._id, {
currentStep: 1,
});
} catch(e) {
expect(e.errors[0].message).toEqual('abc');
}

Vue: Component method from vuex module?

I'm using namespaced modules for state management in vuex, I try to keep all my actions mutations inside my modules as this helps me keep most of my code in the same place (modules acting like classes or similar) hoever there's an issue, I'd like to fire a component method to clear a form when a vuex action is successfull (that is the axios request gets an OK/200 response) but sadly I can't fire a methos from vuex module into my component ( there's no this inisde module).
I also tried adding a .then to my action call but it fires right after I call the action...
I guess I could move the action into the component itself but I'd rather not, what do you guys suggest?
My component:
stripeSourceHandler: function(sourceId)
{
if(this.customerSources.length == 0)
{
console.log('createSourceAndCustomer');
this.createSourceAndCustomer({ id: sourceId });
}
else
{
console.log('addSource');
this.addSource({ id: sourceId }).then(alert('Form cleared')); //this fires right after calling addSource
};
},
My module action:
addSource({ commit }, sourceId)
{
commit('Loader/SET_LOADER', { status:1, message: 'Procesando...' }, { root: true });
axios.post('/stripe/add-source', sourceId)
.then((response) => {
commit('Loader/SET_LOADER', { status:2, message: response.data.message }, { root: true });
commit('ADD_SOURCE', response.data.customer);
//I can't clear component form from this...
},
(error) => {
commit('Loader/SET_LOADER', { status:3, errors: error, message: 'Error al añadir el pago.' }, { root: true });
});
},
Two issues:
You need to return the promise from the action so that you can use .then() to schedule code to be executed once the action has completed (this code being whatever you need to do to clear the form).
.then() takes one (or two) functions as parameters which will be called once the promise has resolved, instead you're just calling alert() immediately.
It'll be something like:
Component method
stripeSourceHandler(sourceId) {
if (this.customerSources.length == 0) {
this.createSourceAndCustomer({ id: sourceId });
} else {
this.addSource({ id: sourceId }).then(() => {
// Clear the form here
alert('Form cleared');
});
}
}
Vuex action
addSource({ commit }, sourceId) {
commit('Loader/SET_LOADER', { status:1, message: 'Procesando...' }, { root: true });
// Return the promise here
return axios.post('/stripe/add-source', sourceId)
.then(response => {
commit('Loader/SET_LOADER', { status:2, message: response.data.message }, { root: true });
commit('ADD_SOURCE', response.data.customer);
}, error => {
commit('Loader/SET_LOADER', { status:3, errors: error, message: 'Error al añadir el pago.' }, { root: true });
});
}

Categories