TypeError: Slackbot is not a constructor - node.js

I need your help because it's the first time that I develop a Slack bot and I don't understand why this message appear:
const botSlack = new Slackbot ({
^
TypeError: Slackbot is not a constructor
Here my code : slack.js
const {Slackbot} = require('#slack/bolt');
const botSlack = new Slackbot({
token : process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
});
(async () => {
await botSlack.start(process.env.PORT || 3000);
})();
Part of my package.json:
"scripts": {
"dev": "nodemon slack.js",
},
"dependencies": {
"#slack/bolt": "^3.11.0",
},
In the bolt documentation (https://api.slack.com/tutorials/hello-world-bolt) and others, it's the same and it's run.
Please someone can explain to me why ?

The documentation has this code - App instead of Slackbot. You can rename the local variable if you want, but the import statement requires the exact name:
const { App } = require('#slack/bolt');
const botSlack = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
(async () => {
await botSlack.start(process.env.PORT || 3000);
})();
if you do want to rename the value, you can use
const { App: Slackbot } = require('#slack/bolt');
It is more common to use import statements for this, you can still alias it using import { App as Stackbot} from '#slack/bolt', see MDN - import

Related

Apollo subscriptions - Nextjs - Error: Observable cancelled prematurely at Concast.removeObserver

I am trying to use apollo/graphql subscription in my nextjs project, my graphql server is placed in external nextjs service,I can work with queries and mutation without any problem but when I use an implementation of useSubscription I get the following error:
"Error: Observable cancelled prematurely
at Concast.removeObserver (webpack-internal:///../../node_modules/#apollo/client/utilities/observables/Concast.js:118:33)
at eval (webpack-internal:///../../node_modules/#apollo/client/utilities/observables/Concast.js:21:47)
at cleanupSubscription (webpack-internal:///../../node_modules/zen-observable-ts/module.js:92:7)
at Subscription.unsubscribe (webpack-internal:///../../node_modules/zen-observable-ts/module.js:207:7)
at cleanupSubscription (webpack-internal:///../../node_modules/zen-observable-ts/module.js:97:21)
at Subscription.unsubscribe (webpack-internal:///../../node_modules/zen-observable-ts/module.js:207:7)
at eval (webpack-internal:///../../node_modules/#apollo/client/react/hooks/useSubscription.js:106:26)
at safelyCallDestroy (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:22763:5)
at commitHookEffectListUnmount (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:22927:11)
at invokePassiveEffectUnmountInDEV (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:24998:13)
at invokeEffectsInDev (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:27137:11)
at commitDoubleInvokeEffectsInDEV (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:27110:7)
at flushPassiveEffectsImpl (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:26860:5)
at flushPassiveEffects (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:26796:14)
at eval (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:26592:9)
at workLoop (webpack-internal:///../../node_modules/scheduler/cjs/scheduler.development.js:266:34)
at flushWork (webpack-internal:///../../node_modules/scheduler/cjs/scheduler.development.js:239:14)
at MessagePort.performWorkUntilDeadline (webpack-internal:///../../node_modules/scheduler/cjs/scheduler.development.js:533:21)"
I know that the subscriptions server is working right because I can to listening from apollo studio and I have created a spa with create-react-app and it works fine
I have used:
Server:
"apollo-server-express": "^3.6.7"
"graphql-ws": "^5.7.0"
Client
"next": "^12.1.5"
"#apollo/client": "^3.5.10"
"graphql-ws": "^5.7.0"
Hook implementation
const room = useSubscription(
gql`
subscription onRoomAdded($roomAddedId: ID!) {
roomAdded(id: $roomAddedId) {
id
name
}
}
`
);
Client implementation
import { ApolloClient, HttpLink, InMemoryCache, split } from '#apollo/client';
import { GraphQLWsLink } from '#apollo/client/link/subscriptions';
import { getMainDefinition } from '#apollo/client/utilities';
import { createClient } from 'graphql-ws';
import fetch from 'isomorphic-fetch';
const HOST = 'http://localhost:3001/graphql';
const HOST_WS = 'ws://localhost:3001/graphql';
const isServer = typeof window === 'undefined';
if (isServer) {
global.fetch = fetch;
}
const httpLink = new HttpLink({
uri: HOST,
});
const link = isServer
? httpLink
: split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
new GraphQLWsLink(
createClient({
url: HOST_WS,
})
),
httpLink
);
const client = new ApolloClient({
ssrMode: isServer,
link,
cache: new InMemoryCache(),
});
export default client;
any idea about the problem? I think the problem could be that NextJS only works with subscriptions-transport-ws but in the official apollo documentation indicates that the new official way is to use graphql-ws the other library is unmaintained already
UPDATE!
I have checked that the subscriptions are working right in production build, I'm investigating how to implement in development process. any suggestions are welcome.
If it is working in production, but in not in dev, you may have the same issue I had with my React SPA: StrictMode and double rendering as described in this github issue.
So far I have found 2 ways to make it work:
remove StrictMode
subscribe with vanilla JS instead ofuseSubscription
const ON_USER_ADDED = gql`
subscription OnUserAdded {
userAdded {
name
id
}
}
`;
const subscribe = () => {
client.subscribe({
query: ON_USER_ADDED,
}).subscribe({
next(data) {
console.log('data', data);
},
complete(){
console.log('complete');
},
error(err) {
console.log('error', err);
}
})
};

Next.js - using BigQuery client library gives an error : Module not found: Can't resolve 'child_process'

I am trying to query bigQuery dataset from a next.js project.
I have installed #google-cloud/bigquery and followed the steps from here
I have also tried next.js related solutions from this link but still getting below error.
It looks like next.config.js needs to be configured for this to allow this api call. I am not sure what needs to be changed.
Could someone please help me resolve this issue?
here is my code :
const { BigQuery } = require("#google-cloud/bigquery");
const bigquery = new BigQuery();
useEffect(() => {
async function queryBigQuery() {
const query = `
SELECT fieldname
FROM \`db.dataset.tablename\` WHERE columnname = 50
LIMIT 10`;
const options = {
query: query,
};
// Run the query
const [rows] = await bigquery.query(options);
console.log("Query Results:");
rows.forEach((row) => {
const url = row["url"];
const viewCount = row["view_count"];
console.log(`url: ${url}, ${viewCount} views`);
});
}
queryBigQuery();
}, []);
**wait - compiling...
error - ./node_modules/google-auth-library/build/src/auth/googleauth.js:17:0
Module not found: Can't resolve 'child_process'**
UPDATED:
I am able to load bigQuery library I think on client side but its giving me new error.
Here is my latest next.config.js file
module.exports = {
webpack: (config, { isServer, webpack }) => {
if (!isServer) {
config.node = {
dgram: "empty",
fs: "empty",
net: "empty",
tls: "empty",
child_process: "empty",
};
}
return config;
},
env: {
project variables.
};
New Error:
#google-cloud/bigquery is meant to run on a Node.js environment, it won't work in the browser.
You'll need to move your code to a data fetching method like getStaticProps/getServerSideProps or to an API route, as they all run server-side.
Here's an example using an API route, as it seems to fit your use-case best.
// pages/api/bigquery
const { BigQuery } = require("#google-cloud/bigquery");
const bigquery = new BigQuery();
export default function handler(req, res) {
const query = `
SELECT fieldname
FROM \`db.dataset.tablename\` WHERE columnname = 50
LIMIT 10
`;
const options = {
query: query,
};
// Run your query/logic here
res.json(data); // Return your JSON data after logic has been applied
}
Then, in your React component's useEffect:
const queryBigQuery = async () => {
const res = await fetch('api/bigquery');
const data = await res.json(); // Returns JSON data from API route
console.log(data);
}
useEffect(() => {
queryBigQuery();
}, []);

nodejs unit test PubSub.publish not sending data

I'm having issues doing a unit test with the following environment:
"pubsub-js": "^1.9.2",
"#types/chai": "^4.2.14",
"#types/mocha": "^8.2.0",
"chai": "^4.2.0",
"firebase-functions-test": "^0.2.3",
"mocha": "^8.2.1",
"ts-node": "^9.1.1",
"ts-sinon": "^2.0.1",
When publish a message to my pubsub the data received by it is always: Message { data: undefined, attributes: {}, _json: undefined } and I can't figure out why.
There is some code to describe my scenario:
pubsub-myFunc.ts
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1")
console.log(message)
/**
* Received message from topic
*/
const myMessage = Buffer.from(message.data, "base64").toString("utf-8")
pubsub-myFunc.spec.ts
import * as functions from 'firebase-functions';
import * as PubSub from 'pubsub-js';
import * as tsSinon from 'ts-sinon';
import { pubsubMyFunc } from './pubsub-myFuncr';
import * as sendEmail from './send-mail';
describe("PubSub tests", () => {
beforeEach(() => {
process.env.GCLOUD_PROJECT = "my env"
})
it("Should call sendNotificationMessage", function (done) {
// this.timeout(60000)
const today = new Date()
const data = {
dateCreated: today,
expireDate: today.getDate() + 30,
objId: "id",
objParentId: "parentId",
}
const spy = tsSinon.default.spy(sendEmail, "sendNotificationMessage")
const dataBuffer = Buffer.from(JSON.stringify(data))
const pubsubMessage = new functions.pubsub.Message(dataBuffer)
PubSub.subscribe("on-myTopic", pubsubMyFunc)
console.log("publish")
PubSub.publish("on-myTopic", pubsubMessage)
setTimeout(() => {
// check if spy was called
tsSinon.default.assert.calledOnce(spy)
done()
}, 15000)
})
})
I have tried to pass directly the dataBuffer but without any luck as well, the outputs of my console logs are:
publish
version 1
Message { data: undefined, attributes: {}, _json: undefined }
Is there any reason for my Message.data to be undefined?
I'm not sure if pubsub-js's subscribe function is compatible with the output of firebase-functions' onPublish method.
You could use firebase's emulators to run your functions locally and test them by sending messages like you would normally instead of going through pubsub-js.
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1");
console.log(message);
/**
* Received message from topic
*/
const myMessage = message.json;
...
Make sure pubsubMyFunc is being exported at firebase functions entry point.
Install and configure firebase emulators, make sure PUBSUB_EMULATOR_HOST env var is set to localhost:$PORT where $PORT is set to the port you have configured for pub sub emulator, located in firebase.json under emulators.pubsub.port.
Once that's all setup, you can send a message to pubsub by:
import {PubSub} from "#google-cloud/pubsub";
cont getTopic = () => {
const topic = new PubSub().topic("on-myTopic");
topic.exists().then(([exists]) => exists
? topic
: topic.create().then(([newTopic]) => newTopic)
);
};
describe("PubSub tests", () => {
let topic;
beforeEach(async() => {
process.env.GCLOUD_PROJECT = "my env"
topic = await getTopic();
});
it("should test something", async() => {
await topic.publishJSON(const data = {
dateCreated: today,
expireDate: today.getDate() + 30,
objId: "id",
objParentId: "parentId",
});
// rest of your code here.
});
});
This will work on the process of hack
export const pubsubMyFunc= functions.pubsub
.topic("on-myTopic")
.onPublish(async (message) => {
console.log("version 1");

compile typescript in chatbot

I'm trying to create a chatbot I'm following a tutorial on youtube
https://www.youtube.com/watch?v=cYuWse7GB9E
However at the end of the tutorial you build the typescript using the command Ctrl + Shift + b
my tsconfig.json file looks like this
{
"conpileOnSave":true,
"compileOptions":{
"module":"commonjs",
"target":"es6",
"sourceMap":true,
"declaration":false,
"removeComments":true,
"outDir":"./dist",
"allowJs":true
},
"files":[
"./lib/types.ts",
"./lib/app.ts"
]
}
and my app.ts file looks like this
import { BotFrameworkAdapter, MemoryStorage,ConversationState } from "botbuilder";
import * as restify from "restify";
//import { ConfState } from "./types";
let server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`${server.name} listening on ${server.url}`);
})
const adaptor = new BotFrameworkAdapter({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
let conversationState;
const memoryStorage = new MemoryStorage();
conversationState = new ConversationState(memoryStorage);
//const conversationState = new ConversationState(new MemoryStorage());
adaptor.use(conversationState);
server.post("/api/messages",(req,res) => {
adaptor.processActivity(req,res,async(context) =>{
if(context.activity.type === "message") {
const state = conversationState.get(context);
await context.sendActivity(`you said ${context.activity.text}`);
} else {
await context.sendActivity(`${context.activity.type} event detected`);
}
})
});
my problem is that it builds, well doesn't have any errors but nothing is ever built into the "dist" folder so when I then run "node server.js" which contains this code
module.exports = require("./dist/app");
It throws an error
internal/modules/cjs/loader.js:638
throw err;
^
Error: Cannot find module './dist/app'
Has anyone any idea what is wrong. I have changed the permissions on the dist folder to full but still nothing.
thanks
my complete source code can be found here
https://github.com/andrewslaughter/chatbot/tree/master/video2

Need to find the error with connecting subscription with schema stitching

I am using apollo-server-express for graphql back-end. I am going to process only mutations there, but I want to redirect query and subscription on hasura by means of schema stitching with introspection. Queries through apollo-server to hasura are working fine and returning the expected data.
But subscriptions are not working and I am getting this error: " Expected Iterable, but did not find one for field subscription_root.users".
And besides, server hasura is receiving events:
But apollo-server resents the answer from hasura. It is not the first day I suffer with this and I can not understand what the problem is.
In the editor hasura subscriptions work.
Link to full code
If you need any additional info, I will gladly provide it to you.
import {
introspectSchema,
makeExecutableSchema,
makeRemoteExecutableSchema,
mergeSchemas,
transformSchema,
FilterRootFields
} from 'graphql-tools';
import { HttpLink } from 'apollo-link-http';
import nodeFetch from 'node-fetch';
import { resolvers } from './resolvers';
import { hasRoleResolver } from './directives';
import { typeDefs } from './types';
import { WebSocketLink } from 'apollo-link-ws';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import * as ws from 'ws';
import { OperationTypeNode } from 'graphql';
interface IDefinitionsParams {
operation?: OperationTypeNode,
kind: 'OperationDefinition' | 'FragmentDefinition'
}
const wsurl = 'ws://graphql-engine:8080/v1alpha1/graphql';
const getWsClient = function (wsurl: string) {
const client = new SubscriptionClient(wsurl, {
reconnect: true,
lazy: true
}, ws);
return client;
};
const wsLink = new WebSocketLink(getWsClient(wsurl));
const createRemoteSchema = async () => {
const httpLink = new HttpLink({
uri: 'http://graphql-engine:8080/v1alpha1/graphql',
fetch: (nodeFetch as any)
});
const link = split(
({ query }) => {
const { kind, operation }: IDefinitionsParams = getMainDefinition(query);
console.log('kind = ', kind, 'operation = ', operation);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const remoteSchema = await introspectSchema(link);
const remoteExecutableSchema = makeRemoteExecutableSchema({
link,
schema: remoteSchema
});
const renamedSchema = transformSchema(
remoteExecutableSchema,
[
new FilterRootFields((operation, fieldName) => {
return (operation === 'Mutation') ? false : true; // && fieldName === 'password'
})
]
);
return renamedSchema;
};
export const createNewSchema = async () => {
const hasuraExecutableSchema = await createRemoteSchema();
const apolloSchema = makeExecutableSchema({
typeDefs,
resolvers,
directiveResolvers: {
hasRole: hasRoleResolver
}
});
return mergeSchemas({
schemas: [
hasuraExecutableSchema,
apolloSchema
]
});
};
Fixed by installing graphql-tools 4th version. It tutns out the editor did not even notice that I do not have this dependency and simply took the version of node_modules, which was installed by some other package. Problem was with version 3.x. Pull request is where the bug was fixed.
I had the same problem, different cause and solution.
My subscription was working well, until I introduced the 'resolve' key in
my subscription resolver:
Here is the 'Subscription' part of My resolver:
Subscription: {
mySubName: {
resolve: (payload) => {
console.log('In mySubName resolver, payload:',payload)
return payload;
},
subscribe:() => pubSub.asyncIterator(['requestsIncomplete']),
// )
},
The console.log proved the resolve() function was being called with a well structured payload (shaped the same as my Schema definiton - specifically the an object with a key named after the graphQL Subscriber, pointing to an array (array is an iterable):
In mySubName resolver, payload: { mySubName:
[ { id: 41,
...,
},
{...},
{...}
...
...
]
Even though I was returning that same unadulterated object, it caused the error expected Iterable, but did not find one for field "Subscription.mySubName"
When I commented out that resolve function all together, the subscription worked, which is further evidence that my payload was well structured, with the right key pointing to an iterable.
I must be mis-using the resolve field. From https://www.apollographql.com/docs/graphql-subscriptions/subscriptions-to-schema/
When using subscribe field, it's also possible to manipulate the event
payload before running it through the GraphQL execution engine.
Add resolve method near your subscribe and change the payload as you wish
so I am not sure how to properly use that function, specifically don't know what shape object to return from it, but using it as above breaks the subscription in the same manner you describe in your question.
I was already using graphql-tools 4.0.0, I upgraded to 4.0.8 but it made no difference.

Resources