ExpressJS - Small curiosity - express

My thing is a small project.
In main what it does is that the "server" will get a call from the link directly what will run some functions that will update the database and the data that has to be shown.
I will show what I mean:
function updateData(){
connection.query(`SELECT * FROM muzica WHERE melodie = "${updateList()}"`, function (error, rezultat, fields) {
if (error) {console.log('err la selectare')};
//express output
let data = {
melodie: rezultat[0].melodie,
likes: rezultat[0].likes
}
console.log(data.likes);
app.get('/like', (req,res) =>{
res.json(`${data.likes}`);
});
}
setInterval(()=>{
updateData();
}, 20000)
Uhh, how to explain it, I'm so bad at this...
So, in main, I'm new to back-end work, everything that I did was based on their Documentation as I learn way faster by my needs than some guides and so on.
So, when I or someone does my http://website/like it should show just data.likes, cause that is all that I need, don't count data.melodie (i will clean that later on) after I finish all the code.
Anyway, whenever I do website/like data.likes is not updating to the new database data.likes.
For example, data.likes before were 5, in a few minutes it can be 2 but whenever I call website/like show "5" than its new value 2.
Don't be hash on me, I'm new and I want to learn as much as I can, but I can't understand the above case, by my logic it should ALWAYS show what its in database when it refreshes each 10 seconds(I run this in localhost so I will not stress any online server).
But if there is any better way to check for databases update than "setInterval" please notice me.
It's hard to learn alone without a mentor or someone else to talk about this domain.
Thank you for your time!
Kind regards,
Pulsy

You have things a bit inside out. A request handler such as app.get('/like', ...) goes at the top level and you only ever call it once. What that statement does is register an event handler for any incoming requests with the /like path. When the server receives an incoming request for /like, it will then call the function for this route handler.
You then put inside that route handler the code that you want to run to generate the response and send the response back to the client.
app.get('/like', (req, res) => {
connection.query(`SELECT * FROM muzica WHERE melodie = "${updateList()}"`, function (error, rezultat, fields) {
if (error) {
console.log(error);
res.sendStatus(500);
} else {
//express output
let data = {
melodie: rezultat[0].melodie,
likes: rezultat[0].likes
}
res.json(data);
}
});
});

The endpoints need to be outside of any functions in express.
For example, if you look at the express "hello world" example here, you will see that they have a basic app that only has a single GET endpoint defined which is "/" so you would access it by running "localhost/" or "127.0.0.1/".
In your case, you want your endpoint to be "/like", so you must define something like:
const express = require('express')
const app = express()
const port = 3000
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
app.get('/like', (req, res) => {
// do database stuff and assign data variable
// res.json(data);
}

Related

Trying to code using tRPC and T3 stack with no internet connection

What about tRPC or the T3 stack breaks when trying to code offline? My console.log gets called when online, but when I try to code offline the procedure doesn't get called.
router.ts
export const exampleRouter = router({
hello: publicProcedure
.input(z.object({ text: z.string().nullish() }).nullish())
.query(({ input }) => {
console.log("WHY DON'T I GET CALLED WHEN OFFLINE???");
return {
greeting: `Hello ${input?.text} `,
};
}),
});
index.tsx:
const hello = trpc.example.hello.useQuery({ text: "World" });
return (
<>
...
{hello.data ? <p>{hello.data.greeting}</p> : <p>Loading..</p>}
</>
);
tRPC does not directly call your procedure like a function, it's just an additional layer around your API calls that provides amazing DX and typing based on your procedure definitions. In reality it's still making a network request to your procedure, so if you're offline that's not going to happen.
Since the tRPC client uses React Query under the hood, you can take advantage of caching and RQ's offline capability, but you're still not going to be able to hit your endpoint when offline.
J. Sheets' answer pointed me in the right direction. There was a simple fix:
const hello = trpc.example.hello.useQuery(
{ text: "from tRPC" }
{ networkMode: "always" } <== the fix
);
More info:
https://tkdodo.eu/blog/offline-react-query
https://tanstack.com/query/v4/docs/react/guides/network-mode

Header is empty when making a fetch-api call

I am trying to generate a session ID and then send that session ID to the front end of my application in the header (I know I should use the body to do this but my prof wants us to use header so we know how to use it).
The fetch response that I get has head but its value is {}, but I'm also getting a 200 'OK' so I know it is at least connected to the front end correctly.
My backend code is this:
router.get('/sid', function (req, res) {
res.setHeader('X-sid', getSid());
res.send();
});
My frontend code is this:
function sessionId() {
fetch('/wordgame/api/v1/sid').then(x => {
console.log(x);
});

Cycle through test data from within a Testcafe test? How to?

I'm wanting to log into an app, run several searches from test data, then log out. I don't want to login and out for each item in the data set, which would be the case if I coded this way...
dataSet.forEach(data =>{
test('Search Test', async t => {......
I would like to be able to...
test('Search Test', async t => {......
foreeach(data in Data set)
call a function to search
call a function to verify search return.
Something like this...
test('Simple Search Test', async t => {
//await t
await loginPage.login(loginName, password);
await t
.expect(getURL()).contains('home')
// Check logged in user display...
.expect(pageHeader.userName.withText(data.loggedInUser).visible).ok()
dataSet.forEach(data =>{
leftSidebar.searchWithCriteria(data.criteria, 'Filename');
recordNav.verifyTotal(data.srchresult);
});
// Log out
await pageHeader.logout();
await t
.expect(loginPage.copyRight.visible).ok();
});
enter code here
I've tried everything, but can't get it to work. Is this possible or does the entire test have to be run for each data record in the set?
TestCafe allows you to loop through test code in any manner, including iterating through custom data.
To help us determine why this does not work for you, please provide an example that I can run on my machine (including the test code, page object, and the tested page's URL).
I got it to work using this...
for (var i = 0; i < dataSet.length; i++){
leftSidebar.searchWithCriteria(dataSet[i].criteria, 'Filename');
recordNav.verifyTotal(dataSet[i].srchResult);
}

How to delete all products matching a collection - Shopify

I have this retarded amount of product in a collection on Shopify (over 50k products) and I would need to delete them all, is there a way I can automate that? All I can find on the internet is to use the "bulk edit tool" which is the most useless thing I've ever seen as it can only grab 50 products at a time.
I've tried automating a script to update the rows with the CSV export file, but it takes over 6 hours for 20K products to import. Plus, since there are hashtags in the title and handle, it apparently doesn't overwrite the products for some reason. So I just can't use the archive anymore...
Has anyone ran into this issue and found a solution?
Thank you!
When it comes to this kinds of tasks I usually write myself a quick dev console script that will do the job for me instead of relying on an app.
Here is a script that you can use in the dev console of your shopify admin page (just copy /paste):
let productsArray = [];
// Recursive function that will grab all products from a collection
const requestCollection = (collectionId, url = `https://${window.location.host}/admin/api/2020-10/collections/${collectionId}/products.json?limit=250`) => {
fetch(url).then(async res => {
const link = res.headers.get('link');
const data = await res.json();
productsArray = [...productsArray, ...data.products];
if(link && link.match(/<([^\s]+)>;\srel="next"/)){
const nextLink = link.match(/<([^\s]+)>;\srel="next"/)[1];
requestCollection(collectionId, nextLink)
} else {
initDelete(productsArray)
}
})
}
// Get CSRF token or the request will require password
const getCSRFToken = () => fetch('/admin/settings/files',{
headers: {
"x-requested-with": "XMLHttpRequest",
"x-shopify-web": 1,
"x-xhr-referer": `https://${window.location.host}/admin/settings/files`
}
}).then(res => res.text()).then(res => {
const parser = new DOMParser();
const doc = parser.parseFromString(res, 'text/html');
return doc.querySelector('meta[name="csrf-token"]').getAttribute('content')
})
// The function that will start the deleting process
const initDelete = async (products) => {
const csrfToken = await getCSRFToken();
products.forEach(item => {
fetch(`https://${window.location.host}/admin/api/2020-10/products/${item.id}.json`, {
method: "delete",
credentials: 'include',
headers: {
"x-csrf-token": csrfToken,
"x-requested-with": "XMLHttpRequest",
"x-shopify-web": 1,
"x-xhr-referer": `https://${window.location.host}/admin/settings/files`
}
})
})
}
And you start it by using requestCollection(ADD_YOUR_COLLECTION_ID_HERE).
To clarify the script, there are 3 main functions:
requestCollection - this handles the product grabbing from the collection. It's a recursive function since we can't grab more than 250 products at the same time.
getCSRFToken - this grabs the CSRF token since most of the post/update/delete request requires it or they will fail (I grab it from the files page)
initDelete - this function start the delete process where we stack all the request one of the other without waiting, you may want to await each request, but even if you crash your browser I think it will be still faster to repeat the process rather then wait for each request to finish.
If you plan to use this script please TEST IT BEFORE USING IT. Create a collection with a few products and run against that, in case there are issues. I've tested it on my side and it's working but it's a code I wrote in 10 minutes after midnight, there can be issues there.
Have in mind that this script will delete ALL products in the collection you specify in the requestCollection(1231254125) method.
PS: All of this can be done using a Private App as well with the products scope set to read/write, using a back-end language of your choice. The main difference will be that you won't need the CSRF token and most of the headers that I set above. But I like quick solutions that doesn't require you to pull out the big guns.

Is it okay to update or delete data inside of router.post, instead of .delete/.patch?

I created some example code underneath to show what I mean.
Is it okay to update some data after saving inside of a post route? I often update and save data in a single route, and I never know if it is okay to do this and if there are any consequences of the code that I am unaware of.
router.post('/sync-steam', auth, async(req, res) => {
const { steamID, steamName } = req.body
try {
await req.user.save( steamID )
await req.user.updateOne( steamName )
res.send("OK")
} catch(err) {
res.status(400).send(err)
}
})
Yes, it is OK to do that. There should not be any issues regarding that as long as your logic that communicates with your database is correct.
However, you should try to follow the convention of REST API, and use the correct method:
GET for listing/reading content
POST for creating content
PUT for replacing content
PATCH for updating part of the content
DELETE for deleting content