I've built a simple express app that uses child_process to run a command. I then need the output of each line sent to the browser using socket.io the following example app is partially working except it sends all of the output lines in a single string once the command has completed.
Is there a way to send each line and have it rendered in the client/browser?
//server.ts
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
const { exec } = require('child_process');
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
// io.emit('chat message', msg);
});
socket.on('chat message2', (msg) => {
console.log('message: ' + msg);
exec("kind create cluster", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
io.emit('chat message', `error: ${error.message}` );
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
io.emit('chat message', `error: ${stderr}` );
return;
}
console.log(`stdout: ${stdout}`);
io.emit('chat message', new Buffer("> "+ `error: ${stdout}` ));
//ws.send(JSON.stringify({id:"shell",data:{stdout}}), function () {
//
// Ignore errors.
//
});
});
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
Here's the client code:
//index.html
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</body>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(e){
e.preventDefault(); // prevents page reloading
socket.emit('chat message', $('#m').val());
socket.emit('chat message2', "Message 2 here!!");
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
<script>
var socket = io();
</script>
</html>
OK for those interested solution is to use spawn instead of exec. e.g.
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
//const { exec } = require('child_process');
const { spawn } = require('child_process');
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
// io.emit('chat message', msg);
});
socket.on('chat message2', (msg) => {
console.log('message: ' + msg);
const sh = spawn('kind', ['create', 'cluster']);
sh.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
io.emit('chat message', `stdout: ${data}` );
});
sh.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
io.emit('chat message', `stderr: ${data}` );
});
sh.on('close', (code) => {
console.log(`child process exited with code ${code}`);
io.emit('chat message', `child process exited with code ${code}`);
});
});
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
Related
I was practicing and learning about vuejs, specifically pagination.
I learn how to do it, and implemented it when I made the api calls in the component, then I moves the function to the actions in vuex, and mapped, them, now my pagination is not even showing up.
I wonder where I made the mistake ???
I have carefully paid attention to every single detail, and read about mutatioons, and actions, I do feel like I am doing everything right, I don't even have any mistakes showing up on the console. this is very wierd
my postModule
import axios from "axios";
export const postModule = {
state: () => ({
posts: [],
page: 1,
limit: 10,
totalPages: 0,
}),
mutations: {
setPosts(state, posts) {
state.posts = posts;
},
setPage(state, page) {
state.page = page;
},
setTotalPage(state, totalPages) {
state.setTotalPage = totalPages
},
},
actions: {
async fetchPosts( {state, commit}) {
try {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts", {
params: {
_page: state.page,
_limit: state.limit,
},
});
commit('setTotalPage', Math.ceil(response.headers["x-total-count"] / state.limit));
commit('setPosts', [...state.posts, ...response.data]);
} catch (e) {
console.log(e);
}
},
async loadPosts({
state,
commit
}) {
try {
commit('setPage', state.page + 1)
setTimeout(async () => {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts", {
params: {
_page: state.page,
_limit: state.limit,
},
});
commit('setTotalPage', Math.ceil(response.headers["x-total-count"] / state.limit));
commit('setPosts', [...state.posts, ...response.data]);
});
} catch (e) {
console.log(e);
}
},
},
namespaced: true,
}
<<<<<component >>>>
<template>
<div>
<h1>Page with the posts</h1>
<post-list :posts="posts" />
</div>
<div class="page__wrapper">
<div
v-for="pageNumber in totalPages"
:key="pageNumber"
class="page"
:class="{
'current-page': page === pageNumber,
}"
#click="changePage(pageNumber)"
>
{{ pageNumber }}
</div>
</div>
</template>
<script>
import PostList from "#/components/PostList";
// import axios from 'axios';
import { mapState, mapMutations, mapActions } from "vuex";
export default {
components: { PostList },
data() {
return {
// posts: [],
// page: 1,
// limit: 10,
// totalPages: 0,
};
},
methods: {
changePage(pageNumber) {
this.page = pageNumber;
this.fetchPosts();
},
...mapMutations({
setPage: "setPage",
}),
...mapActions({
// loadPosts: "post/loadPosts",
fetchPosts: "post/fetchPosts",
}),
},
watch: {
page() {
this.fetchPosts();
},
},
mounted() {
this.fetchPosts();
},
computed: {
...mapState({
posts: (state) => state.post.posts,
page: (state) => state.post.page,
limit: (state) => state.post.limit,
totalPages: (state) => state.post.totalPages,
}),
},
};
</script>
<style scoped>
.page__wrapper {
display: flex;
margin: 15px;
}
.page {
border: 1px solid black;
padding: 10px;
}
.current-page {
border: 2px solid red;
font-size: x-large;
}
</style>
I'm learning node express by making a to-do list. I'm having trouble with marking a to-do as complete/incomplete and deleting them. It's not giving me any errors so I'm trying to console log wherever I can.
The _id in the database is console logging so I think I have my variables correct? Please see below the server.js and main.js files for the comments where I think could be wrong.
I've been stuck on this problem for 3 days now...
EDIT: I just noticed findOneAndUpdate() is a mongoose function. I don't have mongoose yet... I think I'm on the right track...
server.js
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const MongoClient = require("mongodb").MongoClient;
const cors = require("cors");
const { request } = require("mongodb");
const PORT = process.env.PORT || 8000;
app.use(cors());
const username = "hidden";
const password = "hidden";
const connectionString = `mongodb+srv://${username}:${password}#cluster0.7k2ww.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`;
MongoClient.connect(connectionString, { useUnifiedTopology: true }).then(
(client) => {
console.log("Connected to database");
const db = client.db("to-do-list");
const toDoCollection = db.collection("to-dos");
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static("public"));
app.get("/", async (req, res) => {
const result = await toDoCollection.find().toArray();
const itemsLeft = await toDoCollection.countDocuments({
done: false,
});
res.render("index.ejs", { todos: result, left: itemsLeft });
});
app.post("/addtodo", (req, res) => {
toDoCollection
.insertOne({ todo: req.body.todo, done: false })
.then((result) => {
res.redirect("/");
})
.catch((error) => console.error(error));
});
app.put("/markComplete", async (req, res) => {
try {
await toDoCollection.findOneAndUpdate(
{
_id: req.body.todoId, // Is this line talking with my main.js file?
},
{
$set: { done: true },
},
{ sort: { _id: -1 }, upsert: false }
);
console.log(req.body.todoId);
res.json("Task completed");
} catch (err) {
console.log(err);
}
});
app.put("/markIncomplete", async (req, res) => {
try {
await toDoCollection.findOneAndUpdate(
{
_id: req.body.todoId,
},
{
$set: { done: false },
},
{ sort: { _id: -1 }, upsert: false }
);
console.log(req.body.todoId);
res.json("Task completed");
} catch (err) {
console.log(err);
}
});
app.delete("/deleteToDo", async (req, res) => {
console.log(req.body.todoId);
try {
await toDoCollection
.findOneAndDelete({ _id: req.body.todoId })
.then((result) => {
console.log("todo deleted");
res.json("todo deleted");
});
} catch {
console.log(err);
}
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
}
);
main.js
const deleteTask = document.querySelectorAll(".delete-todo");
const completeTask = document.querySelectorAll(".incomplete");
const incompleteTask = document.querySelectorAll(".complete");
Array.from(deleteTask).forEach((e) => {
e.addEventListener("click", deleteToDoFunc);
});
Array.from(completeTask).forEach((e) => {
e.addEventListener("click", completeToDoFunc);
});
Array.from(incompleteTask).forEach((e) => {
e.addEventListener("click", incompleteToDoFunc);
});
async function deleteToDoFunc() {
console.log("Delete working!");
const todoId = this.parentNode.dataset.id;
console.log(todoId);
try {
const res = await fetch("deleteToDo", {
method: "delete",
headers: { "Content-type": "application/json" },
body: JSON.stringify({
todoId: todoId,
}),
});
const data = await res.json();
console.log(data);
location.reload();
} catch (err) {
console.log(err);
}
}
async function completeToDoFunc() {
console.log("Update working!");
const todoId = this.parentNode.dataset.id;
console.log(todoId);
try {
const res = await fetch("markComplete", {
method: "put",
headers: { "Content-type": "application/json" },
body: JSON.stringify({
todoId: todoId, // Is this line talking with the server.js file?
}),
});
const data = await res.json();
console.log(data);
// location.reload();
} catch (err) {
console.log(err);
}
}
async function incompleteToDoFunc() {
console.log("Incomplete task");
const todoId = this.parentNode.dataset.id;
console.log(todoId);
try {
const res = await fetch("markIncomplete", {
method: "put",
headers: { "Content-type": "application/json" },
body: JSON.stringify({
todoId: todoId,
}),
});
const data = await res.json();
console.log(data);
location.reload();
} catch (err) {
console.log(err);
}
}
index.ejs
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="../css/font-awesome-4.7.0/css/font-awesome.min.css"
/>
<link rel="stylesheet" href="css/style.css" />
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght#300;400&display=swap"
rel="stylesheet"
/>
<title>To Do</title>
</head>
<body>
<div class="container">
<header class="flexContainer">
<h1 class="title main-font center">To Do List</h1>
</header>
<form class="center" action="/addtodo" method="POST">
<input type="text" placeholder="Add a To Do" name="todo" />
<button type="submit" class="submitButton">
<i class="fa fa-plus-square"></i>
</button>
</form>
<div class="to-do-list flexContainer">
<ul class="task-list center">
<% todos.forEach(todo => { %>
<li class="todo-name main-font complete-task" data-id="<%=todo._id%>"> <!-- The route should know which to-do to update/delete based on _id -->
<% if (todo.done === true) { %>
<span class="complete"><%= todo.todo %></span>
<% } else { %>
<span class="incomplete"><%= todo.todo %></span>
<% } %>
<span class="fa fa-trash delete-todo"></span>
</li>
<%}) %>
</ul>
</div>
<h2 class="main-font center">Left to do: <%= left %></h2>
</div>
<script type="text/javascript" src="/js/main.js"></script>
</body>
</html>
When you try to update your To-Do List, does it override everything in your document? I see that your using a PUT request instead of a PATCH request, and a PUT request would replace your all your data instead of updating a single field
Hello i am new to peerjs. currently i am trying to code a video call app. i face a problem in it. it shows only my video.it is not showing video and audio of another user .please help i am stuck.
error on console(front end) is
websocket.js:87 WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=4&transport=websocket&sid=uaFPNhLHfKuVgldiAAAA' failed: Invalid frame header
server.js (backend)
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const { v4: uuidV4 } = require('uuid');
const { ExpressPeerServer } = require('peer');
const peerServer = ExpressPeerServer(server, {
debug: true,
});
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use('/peerjs', peerServer);
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`);
});
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room });
});
io.on('connection', (socket) => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).emit('user-connected', userId);
});
});
server.listen(3000, () => {
console.log('running...');
});
room.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script>
const ROOM_ID = '<%= roomId %>';
</script>
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<title>Document</title>
<link rel="stylesheet" href="style.css" />
<style>
#video-grid {
display: grid;
grid-template-columns: repeat(auto-fill, 250px);
grid-template-rows: 160px;
}
video {
height: 100%;
width: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div id="video-grid"></div>
<script src="script.js"></script>
</body>
</html>
script.js
const socket = io('/');
const videoGrid = document.getElementById('video-grid');
const myPeer = new Peer(undefined, {
host: '/',
port: '3000',
path: '/peerjs',
});
const myVideo = document.createElement('video');
myVideo.muted = true;
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
addVideoStream(myVideo, stream);
myPeer.on('call', (call) => {
call.answer(stream);
const video = document.createElement('video');
call.on('stream', (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on('user-connected', (userId) => {
connectToNewUser(userId, stream);
});
});
myPeer.on('open', (id) => {
socket.emit('join-room', ROOM_ID, id);
});
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream);
const video = document.createElement('video');
call.on('stream', (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
call.on('close', () => {
video.remove();
});
// peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener('loadedmetadata', () => {
video.play();
});
videoGrid.append(video);
}
I've read through a couple of vuejs PWA examples for updating PWA, and it seems non worked for me and made me confused with these problems:
1. When I build the app and run it,
it will instantly download the content and shows the new content.
2. It will ask every time that there is a new version.
How should I fix these problems?
I just want to prompt the user to see that there is a new version(e.g.v1) and if he/she wants, update the app after accepting, and don't bother he/her on the next refresh until there is a new version(e.g. v2)
Thanks to custom service worker exmaple, Working solution on pwa update:
//vue.config.js
module.exports = {
publicPath: "./",
pwa: {
themeColor: "#42b983",
msTileColor: "#42b983",
appleMobileWebAppCache: "yes",
manifestOptions: {
background_color: "#42b983"
}
}
};
//registerServiceWorker.js:
import { Workbox } from "workbox-window";
let wb;
if ("serviceWorker" in navigator) {
wb = new Workbox(`${process.env.BASE_URL}service-worker.js`);
wb.addEventListener("controlling", () => {
window.location.reload();
});
wb.register();
} else {
wb = null;
}
export default wb;
//main.js
import Vue from "vue";
import App from "./App.vue";
import wb from "./registerServiceWorker";
Vue.prototype.$workbox = wb;
new Vue({
render: h => h(App)
}).$mount("#app");
//App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Vue.js with PWA" />
<div class="update-dialog" v-if="prompt">
<div class="update-dialog__content">
A new version is found. Refresh to load it?
</div>
<div class="update-dialog__actions">
<button
class="update-dialog__button update-dialog__button--confirm"
#click="update"
>
Update
</button>
<button
class="update-dialog__button update-dialog__button--cancel"
#click="prompt = false"
>
Cancel
</button>
</div>
</div>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld,
},
methods: {
async update() {
this.prompt = false;
await this.$workbox.messageSW({ type: "SKIP_WAITING" });
},
},
data() {
return {
prompt: false,
};
},
created() {
if (this.$workbox) {
this.$workbox.addEventListener("waiting", () => {
this.prompt = true;
});
}
},
};
</script>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.update-dialog {
position: fixed;
left: 50%;
bottom: 64px;
transform: translateX(-50%);
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
padding: 12px;
max-width: 576px;
color: white;
background-color: #2c3e50;
text-align: left;
&__actions {
display: flex;
margin-top: 8px;
}
&__button {
margin-right: 8px;
&--confirm {
margin-left: auto;
}
}
}
</style>
I'm not sure about the Vue,
But I used these below codes and worked just fine for me in a React project.
First, register the ServiceWorker by calling method registerValidSW:
function registerValidSW(swUrl: string) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
const event = new Event("app-event-newContentAvailable");
window.dispatchEvent(event);
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
I used workbox and this is what my workbox-build.js file looks like:
const workboxBuild = require('workbox-build');
// NOTE: This should be run *AFTER* all your assets are built
const buildSW = () => {
// This will return a Promise
return workboxBuild.injectManifest({
swSrc: 'src/sw-template.js', // this is your sw template file
swDest: 'build/sw.js', // this will be created in the build step
globDirectory: 'build',
globIgnores: ['**/service-worker.js', '**/precache-manifest.*.js'],
globPatterns: [
'**\/*.{js,css,html,png}',
]
}).then(({count, size, warnings}) => {
// Optionally, log any warnings and details.
warnings.forEach(console.warn);
console.log(`${count} files will be precached, totaling ${size} bytes.`);
});
}
buildSW();
And this is sw-template.js:
if ('function' === typeof importScripts) {
importScripts(
// 'https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'
'static/sw-workbox/v4.3.1/workbox-sw.js'
);
/* global workbox */
if (workbox) {
/* injection point for manifest files. */
workbox.precaching.precacheAndRoute([]);
const cacheConfig = {
images: [
/\.(?:jpg|jpeg|png|gif|svg|ico)$/,
new workbox.strategies.CacheFirst({
cacheName: "images",
plugins: [
new workbox.expiration.Plugin({
maxEntries: 6000,
maxAgeSeconds: 30 * 24 * 60 * 60 // 30 Days
})
]
}),
"GET"
],
fonts: [
/\.(?:eot|ttf|woff|woff2)$/,
new workbox.strategies.CacheFirst({
cacheName: "fonts",
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200]
}),
new workbox.expiration.Plugin({
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
maxEntries: 30
})
]
}),
"GET"
],
manifest: [
new RegExp('manifest.json'),
new workbox.strategies.CacheFirst({
cacheName: "manifest",
plugins: [
new workbox.expiration.Plugin({
// maxAgeSeconds: 60 * 60 * 24 * 2, // 2 days
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
maxEntries: 1
})
]
}),
"GET"
],
};
/* custom cache rules*/
workbox.routing.registerNavigationRoute('/index.html', {
blacklist: [
/^\/_/, /\/[^\/]+\.[^\/]+$/,
],
});
workbox.routing.registerRoute(...cacheConfig.images);
workbox.routing.registerRoute(...cacheConfig.fonts);
workbox.routing.registerRoute(...cacheConfig.manifest);
const SkipWaitingAndClaim = () => {
workbox.core.skipWaiting();
workbox.core.clientsClaim();
};
SkipWaitingAndClaim();
} else {
console.log('Workbox could not be loaded. No Offline support');
}
}
In the package.json I added a new line to my scripts so that I can build my sw.js file before building the app:
"scripts": {
"build-sw": "node ./src/sw-build.js",
...
...
},
And now you can add your EventListener in for instance App.tsx (I used modal with the reload action button):
componentDidMount() {
window.addEventListener("app-event-newContentAvailable", () => {
this.setState({ showConfirmReloadModal: true });
});
}
I configured a multiclient vue apollo, but for some reason it sends requests only to localhost. However I never specified a localhost endpoint. Here is my config file
vue-apollo.js:
import Vue from "vue";
import VueApollo from "vue-apollo";
import {
createApolloClient,
restartWebsockets
} from "vue-cli-plugin-apollo/graphql-client";
Vue.use(VueApollo);
const AUTH_TOKEN = "apollo-token";
const httpsEndpoint =
process.env.VUE_APP_GRAPHQL_HTTPS || "https://myst.endpoint.prod/graphql";
export const filesRoot =
process.env.VUE_APP_FILES_ROOT ||
httpsEndpoint.substr(0, httpsEndpoint.indexOf("/graphql"));
Vue.prototype.$filesRoot = filesRoot;
const defaultOptions = {
httpsEndpoint,
wssEndpoint:
process.env.VUE_APP_GRAPHQL_WSS || "wss://myst.endpoint.prod/graphql",
tokenName: AUTH_TOKEN,
persisting: false,
websocketsOnly: false,
ssr: false
};
const clientAOptions = {
httpsEndpoint: "https://myst.endpoint.prod/graphql"
};
const clientBOptions = {
httpsEndpoint: "https://mynd.endpoint.prod/graphql"
};
export function createProvider(options = {}) {
const createA = createApolloClient({
...defaultOptions,
...clientAOptions
});
const createB = createApolloClient({
...defaultOptions,
...clientBOptions
});
const a = createA.apolloClient;
const b = createB.apolloClient;
const apolloProvider = new VueApollo({
clients: {
a,
b
},
defaultClient: a,
defaultOptions: {
$query: {
}
},
errorHandler(error) {
console.log(
"%cError",
"background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;",
error.message
);
}
});
return apolloProvider;
}
export async function onLogin(apolloClient, token) {
if (typeof localStorage !== "undefined" && token) {
localStorage.setItem(AUTH_TOKEN, token);
}
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
try {
await apolloClient.resetStore();
} catch (e) {
console.log("%cError on cache reset (login)", "color: orange;", e.message);
}
}
export async function onLogout(apolloClient) {
if (typeof localStorage !== "undefined") {
localStorage.removeItem(AUTH_TOKEN);
}
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
try {
await apolloClient.resetStore();
} catch (e) {
console.log("%cError on cache reset (logout)", "color: orange;", e.message);
}
}
I edidted this file according to documentation. Why does apollo send request to wrong endpoint and how to fix it? I edidted this file according to documentation. Why does apollo send request to wrong endpoint and how to fix it? I