Heroku Error: ENOENT: no such file or directory, stat '/app/build/index.html' - heroku

I am getting this error in my heroku logs.
Same Question
All the solutions provided here did not address the issue.
I tried the different variations of the get method:
app.use(express.static('build'));
app.get('*', function (req, res) {
res.sendFile('index.html');
});
What else could I try or am I missing from here?
App.js
const configuration = require('#feathersjs/configuration');
const feathers = require('#feathersjs/feathers');
const express = require('#feathersjs/express');
const socketio = require('#feathersjs/socketio');
const moment = require('moment');
class IdeaService {
constructor() {
this.ideas = [];
}
async find() {
return this.ideas;
}
async create(data) {
const idea = {
id: this.ideas.length,
text: data.text,
tech: data.tech,
viewer: data.viewer
};
idea.time = moment().format('h:mm:ss a');
this.ideas.push(idea);
return idea;
}
}
const app = express(feathers());
app.feathers().configure(configuration());
app.use(express.static('build'));
app.get('*', function (req, res) {
res.sendFile('index.html');
});
// Parse JSON
app.use(express.json());
// Configure SocketIO realtime API
app.configure(socketio());
// Enable REST services
app.configure(express.rest());
// Register services
app.use('/ideas', new IdeaService());
// Connect new streams
app.on('connection', conn => app.channel('stream').join(conn));
// Publish events to stream
app.publish(data => app.channel('stream'));
const PORT = process.env.PORT || 3030;
app.listen(PORT).on('listening', () => console.log(`Server running on port ${PORT}`));
app.service('ideas').create({
text: 'Build a cool app',
tech: 'Node.js',
viewer: 'John Doe'
});
export default IdeaService;
package.json

Related

How to resolve KOA- next() is not a function error?

I have built a simple koa framework application.After adding routes am trying to hit the /health GET route. It throws the below error:
TypeError: next is not a function
at cookieParser (c:\Userxxs\x\gimt\dp-my-app\node_modules\cookie-parser\index.js:46:14)
at dispatch (c:\Users\B748806a\gimt\dp-my-app\node_modules\koa-compose\index.js:42:32)
at bodyParser (c:\Users\B748806a\gimt\dp-my-app\node_modules\koa-bodyparser\index.js:95:11)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Below are the files and their order of execution:
server.js
const app = require("./app.js");
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`));
app.js
"use strict";
const koa = require('koa');
const koaRouter = require('koa-router');
const app = new koa();
const router = new koaRouter();
const middleware = require("./src/main/middlewares/middlewares");
const routes = require("./src/main/middlewares/route-path");
const init = async () => {
try {
/**
* Step 2: load endpoint routes for the application
*/
routes(router)
} catch (err) {
logger.error({
err
});
}
};
/**
* Step 1: load middleware setup - cors,helmet from KP Spring cloud service
*/
middleware(app);
init();
module.exports = app
middleware.js
const koa = require("koa");
const koaRouter = require('koa-router');
const router = new koaRouter();
const cors = require("koa-cors");
const compression = require("koa-compress");
const helmet = require("koa-helmet");
const cookieParser = require("cookie-parser");
const bodyParser = require('koa-bodyparser')
const ActuatorRouter = require('pm-js-actuator').koa //internal library
const ACTUATOR_OPTIONS = {
health: {
enabled: true
},
livenessprobe: {
enabled: true
},
env: {
enabled: false
},
info: {
enabled: true,
secure: false
}
}
function middleware(app) {
// Use the CORS for the time being.
app.use(cors())
// Let's don the security helmet
app.use(helmet())
app.use(helmet.frameguard())
app.use(helmet.ieNoOpen())
app.use(helmet.frameguard({
action: 'sameorigin'
}))
app.use(helmet.noSniff())
app.use(helmet.referrerPolicy({
policy: 'same-origin'
}))
app.use(helmet.xssFilter())
//app.disable('x-powered-by')
app.use(ActuatorRouter.getRouter(ACTUATOR_OPTIONS).routes())
app.use(bodyParser())
app.use(cookieParser());
// Set up compression
app.use(compression());
}
module.exports = middleware;
route-path.js
const RootHeathController = require("../controller/root-health-controller")
const routes = (router) => {
router.get("/health", RootHeathController.handler)
};
module.exports = routes
root-health-controller.js
const handler = async (ctx, next) => {
ctx.body="Hi";
}
module.exports = {
handler
};
The application is started successfully on port 3000. But when i hit, /health from postman, it throws the mentioned error. Any solution?
The problem here is, that cookie-parser seems to be an express - thing (see also repo url: https://github.com/expressjs/cookie-parser). So to test this I created a minimal version of your code:
const koa = require('koa');
const koaRouter = require('koa-router');
const bodyParser = require('koa-bodyparser');
const cookieParser = require("cookie-parser");
const app = new koa();
app.use(bodyParser());
app.use(cookieParser()); // <-- comment this line
const router = new koaRouter();
router.get("/health", async (ctx, next) => {
ctx.body = 'hi';
});
app.use(router.routes());
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`));
Calling the localist:3000/health endpoint throws the same error. But if you comment the app.use(cookie-parser()) line all works fine.
The question is, why you would need this library? You should be able to set and get cookies in koa with ctx.cookies.get and ctx.cookies.set

Deno oak websocket must have a method that returns an async iterator

I am trying to build up a WebSocket with oak (not the native deno one).
The following code is how I build the server.
import {Application, Router, Context, send } from "https://deno.land/x/oak#v10.6.0/mod.ts";
const runWS = async (ctx: Context, next: () => Promise<unknown>) => {
try{
const ws = await ctx.upgrade();
ws.onopen = () => {
chatConnection(ws);
};
ws.onclose = () => { console.log('Disconnected from the client!');};
}catch{await next();}
}
let sockets = new Map<string, WebSocket>();
const chatConnection = async (ws: WebSocket) => {
console.log('new websocket, ws: ',ws);
const uid = globalThis.crypto.randomUUID();
sockets.set(uid,ws);
console.log('socket: ',sockets);
for await (const ev of ws){
console.log('ev: ', ev);
}
}
export const wsRoutes = new Router()
.get('/ws', runWS);
But in the for loop (at the end), for ws it says Type 'WebSocket' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.. What's the deal with this and how to fix it?
The error message is providing you with useful information: the WebSocket is not AsyncIterable, which means that it cannot be used with a for await...of loop.
Here is the type documentation for WebSocket in Deno. It is (for the most part) the same as the WHATWG standard WebSocket that is documented on MDN.
If your intention is to respond to incoming message events, you'll need to attach an event listener:
webSocket.addEventListener("message", (messageEvent) => {
// Do something in response to each message event
});
Additional:
Here's an observation based on the code you've shown, but not in response to your question:
It's probably more ergonomic to store the sockets as the keys of your map, and the associated state data in the values. (This is the inverse of what you've shown). Here's an example of why:
import {
Router,
type RouterMiddleware,
} from "https://deno.land/x/oak#v10.6.0/mod.ts";
// You seem to want to log data to the console.
// This function will help you easily log only certain properties of objects:
/**
* Functional implementation of the type utility
* [`Pick<Type, Keys>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)
*/
function pick<T, K extends keyof T>(
obj: T,
keys: readonly K[],
): Pick<T, K> {
const result = {} as Pick<T, K>;
for (const key of keys) result[key] = obj[key];
return result;
}
type SocketData = { id: string };
const socketMap = new Map<WebSocket, SocketData>();
// Do something when a connection is opened
function handleOpen(ev: Event, ws: WebSocket) {
const socketData: SocketData = { id: window.crypto.randomUUID() };
socketMap.set(ws, socketData);
console.log({
event: pick(ev, ["type"]),
socketData,
});
}
// Do something when an error occurs
function handleError(ev: Event, ws: WebSocket) {
const socketData = socketMap.get(ws);
console.log({
event: pick(ev, ["type"]),
socketData,
});
socketMap.delete(ws);
}
// Do something when a connection is closed
function handleClose(ev: CloseEvent, ws: WebSocket) {
ev.code; // number
ev.reason; // string
ev.wasClean; // boolean
const socketData = socketMap.get(ws);
console.log({
event: pick(ev, ["type", "code", "reason", "wasClean"]),
socketData,
});
socketMap.delete(ws);
}
// Do something when a message is received
// Change `unknown` to the type of message payloads used in your application.
// (for example, JSON messages are `string`)
function handleMessage(ev: MessageEvent<unknown>, ws: WebSocket) {
ev.data; // unknown
ev.lastEventId; // string
ev.ports; // readonly MessagePort[]
const socketData = socketMap.get(ws);
if (socketData) {
socketData.id; // string
}
console.log({
event: pick(ev, ["type", "data", "lastEventId", "ports"]),
socketData,
});
}
const webSocketMiddleware: RouterMiddleware<"/ws"> = async (ctx, next) => {
const ws = ctx.upgrade();
ws.addEventListener("open", (ev) => handleOpen(ev, ws));
ws.addEventListener("error", (ev) => handleError(ev, ws));
ws.addEventListener("close", (ev) => handleClose(ev, ws));
ws.addEventListener("message", (ev) => handleMessage(ev, ws));
await next();
};
export const router = new Router();
router.get("/ws", webSocketMiddleware);
This is my updated code. It avoids the problem entirely
import {Application, Router, Context, send } from "https://deno.land/x/oak#v10.6.0/mod.ts";
interface BroadcastObj{
name: string,
mssg: string
}
const runWS = async (ctx: Context, next: () => Promise<unknown>) => {
if(!ctx.isUpgradable){
ctx.throw(501);
}
const uid = globalThis.crypto.randomUUID();
try{
const ws = await ctx.upgrade();
ws.onopen = () => {
chatConnection(ws);
};
ws.onmessage = (m) => {
let mssg = m.data as string;
if(typeof(mssg) === 'string'){
chatMessage(JSON.parse(mssg));
}
};
ws.onerror = (e) => {console.log('error occured: ', e);};
ws.onclose = () => { chatDisconnect(uid);};
}catch{await next();}
}
let sockets = new Map<string, WebSocket>();
const chatConnection = async (ws: WebSocket, uid: string) => {
await sockets.set(uid,ws);
}
const chatMessage = async (msg: BroadcastObj) => {
await sockets.forEach((ws: WebSocket) => {
ws.send(JSON.stringify(msg));
});
}
const chatDisconnect = async (uid: string) => {
await sockets.delete(uid);
}
export const wsRoutes = new Router()
.get('/ws', runWS);

apollo explorer say "isTrusted": true when i try use Subscription

guys, I have a problem when I want to use a Subscription I'm facing this issue I don't find a solution in any place, I'm a GQL user and i decide to use Subscription to make real-time website but I'm facing a a this issue ,
hare is code
I'm trying to show apollo docs but I'm facing another issue(graphql doesn't find my resolver), so I try to use this pace of code in my mind it's work but the issue is it says
Unable to connect wss://localhost:4001 also I'm trying to use Unable to connect wss://localhost:4001/graphql and Unable to connect wss://localhost:4001/subscription, also i try this three way with using ws
// my resolver
const somethingChanged = () => {
// subscribe: () => {
console.log("subscribe")
pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC)
// }
}
const makeId = () => {
// make id generator 36 symbols
let id = Math.random().toString(36).split(".")[1]
pubsub.publish(SOMETHING_CHANGED_TOPIC, {
somethingChanged: {
id,
},
})
return id
}
const resolvers = {
Subscription: {
somethingChanged,
},
Query: {
hello: () => "Hello world!",
},
Mutation: {
makeId,
},
}
// app.ts
import { createServer } from "http"
import express from "express"
import { ApolloServer, gql } from "apollo-server-express"
import { typeDefs } from "./graphql/schema"
import "colors"
import resolvers from "./graphql/root"
import connect from "./db/connect"
import { PubSub } from "graphql-subscriptions"
const SOMETHING_CHANGED_TOPIC = "something_changed"
require("dotenv").config()
export const pubsub = new PubSub()
// 1 creating one function for app
const startServer = async () => {
// 2 // declaring app as express
const app = express()
const httpServer = createServer(app)
setInterval(() => {
console.log(`Server was work ${Math.random().toString()}`.green)
}, 2000)
// middleware's
connect()
// 5
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => req,
})
// 6
await apolloServer.start()
// 7
apolloServer.applyMiddleware({
app,
path: "/graphql",
})
// 8
httpServer.listen({ port: process.env.PORT || 4001 }, () =>
console.log(
`Server listening on localhost:4001${apolloServer.graphqlPath}`.blue
)
)
}
startServer()
I just want to test in apollo explorer but it doesn't work

Could anyone provide a fastapi websocket endpoint which could connect with the example given for RTK Query streaming updates

I'm trying to get my head around RTK Query as it applies to websockets. The example given is
import { createApi, fetchBaseQuery } from '#reduxjs/toolkit/query/react'
import { createEntityAdapter, EntityState } from '#reduxjs/toolkit'
import { isMessage } from './schemaValidators'
export type Channel = 'redux' | 'general'
export interface Message {
id: number
channel: Channel
userName: string
text: string
}
const messagesAdapter = createEntityAdapter<Message>()
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
endpoints: (build) => ({
getMessages: build.query<EntityState<Message>, Channel>({
query: (channel) => `messages/${channel}`,
transformResponse(response: Message[]) {
return messagesAdapter.addMany(
messagesAdapter.getInitialState(),
response
)
},
async onCacheEntryAdded(
arg,
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved }
) {
const ws = new WebSocket('ws://localhost:8080')
try {
await cacheDataLoaded
const listener = (event: MessageEvent) => {
const data = JSON.parse(event.data)
if (!isMessage(data) || data.channel !== arg) return
updateCachedData((draft) => {
messagesAdapter.upsertOne(draft, data)
})
}
ws.addEventListener('message', listener)
} catch {}
await cacheEntryRemoved
ws.close()
},
}),
}),
})
export const { useGetMessagesQuery } = api
for the frontend. It looks as though the idea is to make a request to /messages/{channel} and on successful receipt and caching of these messages to connect to a websocket api. I'm struggling to create a fastapi app that connects with this example so I can figure out the workings. Does anyone have an example they might be willing to please share?

How to use Socket.io with Next.js API Routes

Next.js provides serverless API routes. By creating a file under ./pages/api you can have your service running, and I want to have a Socket.io service by using this mechanism.
I have created a client:
./pages/client.js
import { useEffect } from 'react';
import io from 'socket.io-client';
export default () => {
useEffect(() => {
io('http://localhost:3000', { path: '/api/filename' });
}, []);
return <h1>Socket.io</h1>;
}
And an API route:
./pages/api/filename.js
const io = require('socket.io')({ path: '/api/filename' });
io.onconnection = () => {
console.log('onconnection');
}
io.on('connect', () => {
console.log('connect');
})
io.on('connection', () => {
console.log('connection');
})
export default (req, res) => {
console.log('endpoint');
}
But I can't get the client to connect to the Socket.io server and succesfully see any of: 'onconnection', 'connect', or 'connection' printed.
The trick is to plug 'socket.io' into the http server only once, so checking every access to the api.
Try something like this:
./pages/api/socketio.js
import { Server } from 'socket.io'
const ioHandler = (req, res) => {
if (!res.socket.server.io) {
console.log('*First use, starting socket.io')
const io = new Server(res.socket.server)
io.on('connection', socket => {
socket.broadcast.emit('a user connected')
socket.on('hello', msg => {
socket.emit('hello', 'world!')
})
})
res.socket.server.io = io
} else {
console.log('socket.io already running')
}
res.end()
}
export const config = {
api: {
bodyParser: false
}
}
export default ioHandler
./pages/socketio.jsx
import { useEffect } from 'react'
import io from 'socket.io-client'
export default () => {
useEffect(() => {
fetch('/api/socketio').finally(() => {
const socket = io()
socket.on('connect', () => {
console.log('connect')
socket.emit('hello')
})
socket.on('hello', data => {
console.log('hello', data)
})
socket.on('a user connected', () => {
console.log('a user connected')
})
socket.on('disconnect', () => {
console.log('disconnect')
})
})
}, []) // Added [] as useEffect filter so it will be executed only once, when component is mounted
return <h1>Socket.io</h1>
}
You have to have the /api/pusher/auth to authenticate with pusher on the frontend. Then you use the key you get from that to communicate with pusher. It's for security purposes. You can do it all through the frontend, but depending on your app, if you're saving data (such as messages, or chats) then probably should authenticate.
You can use custom server and attach sockets to it (just like with express) and provide needed path where socket.io will listen. How to use custom server
You can write something like this server.js
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const { Server } = require('socket.io');
const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;
// when using middleware `hostname` and `port` must be provided below
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = createServer(async (req, res) => {
try {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
if (pathname === '/a') {
await app.render(req, res, '/a', query);
} else if (pathname === '/b') {
await app.render(req, res, '/b', query);
} else {
await handle(req, res, parsedUrl);
}
} catch (err) {
console.error('Error occurred handling', req.url, err);
res.statusCode = 500;
res.end('internal server error');
}
});
const io = new Server(server, {
path: '/socket.io' // or any other path you need
});
io.on('connection', socket => {
// your sockets here
console.log('IO_CONNECTION');
});
server.listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://${hostname}:${port}`);
});
});
You would need to run your server using node server.js

Resources