Firestore keeps saying "fetch is not defined" on electron with vue - node.js

I'm trying to get firebase firestore to work in electron. Firebase is initialized fine but when I try to run firestore, it says:
Error adding document: ReferenceError: fetch is not defined
at e (webpack:///./node_modules/#firebase/firestore/dist/lite/index.browser.esm2017.js?:3242:30)
at nn (webpack:///./node_modules/#firebase/firestore/dist/lite/index.browser.esm2017.js?:3243:10)
.
.
.
at __webpack_require__ (D:\Desktop\Projects\casedb\dist_electron\index.js:20:30)
I'm pretty sure that's happening because firestore is thinking it's running on the web and has access to fetch while it's actually running on node.js.
Now, I'm not sure what to do to make this work. I'm using a vue-cli plugin to use electron with vue. I've gone through their documentation and tried the following.
Added firebase and firestore as a native dependency
Tried running my test script in a normal node.js environment
Tried using require instead of import
None of these have worked so far. From what I can gather by googling for 8 hours, it probably has something to do with webpack. But I can't figure out what to do.
Here is my vue.config.js which configures the cli plugin:
module.exports = {
pluginOptions: {
electronBuilder: {
externals: [
"pouchdb-node",
"firebase",
"firebase/firestore",
"firebase/firestore/lite",
"firestore",
],
preload: "src/preload.js",
nodeIntegration: true,
builderOptions: {
nsis: {
oneClick: false,
createDesktopShortcut: true,
perMachine: true,
},
},
},
},
};
Here is my firebase test script just in case:
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore/lite";
import { collection, addDoc } from "firebase/firestore/lite";
const firebaseConfig = {
apiKey: "AIzaSyCwzmIhPhUxB7uFsCHlWhARTiSzMylDn0A",
// authDomain: "casedb-29442120.firebaseapp.com",
projectId: "casedb-29442120",
storageBucket: "casedb-29442120.appspot.com",
messagingSenderId: "354561150712",
appId: "1:354561150712:web:3db5b0d737be49a90bf50d",
};
const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore();
export const syncWithDB = async () => {
try {
const docRef = await addDoc(collection(db, "records"), {
first: "Ada",
last: "Lovelace",
born: 1815,
});
console.log("Document written with ID: ", docRef.id);
} catch (e) {
console.error("Error adding document: ", e);
}
};

Related

How to deep mock Prisma Client in JavaScript (not TypeScript)?

I'm want to unit test Next.js API route with Prisma in JavaScript. Unfortunately, the Prisma's unit testing guide is written for Typescript.
I have jest.config.js which will setup the mock in jest.setup.js
const nextJest = require("next/jest");
const createJestConfig = nextJest({
dir: "./",
});
const config = {
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
moduleDirectories: ["node_modules", "<rootDir>/"],
moduleNameMapper: {
"#/(.*)$": "<rootDir>/$1",
},
};
module.exports = createJestConfig(config);
and this is how I configured the mock in jest.setup.js
import prisma from "#/utils/client";
jest.mock("#/utils/client", () => ({
__esModule: true,
default: {
user: {
findMany: jest.fn(),
},
// ... and each and everyone of the entities
},
}));
export const prismaMock = prisma;
and the following test case passed
describe("Calculator", () => {
it("renders a calculator", async () => {
await prismaMock.user.findMany.mockResolvedValue(["abc]);
const { req, res } = createMocks();
await handler(req, res);
expect(res._getStatusCode()).toBe(200);
expect(res._getData()).toBe('["abc"]');
});
});
With this approach, I have to mock each and everyone of the models and function in jest.setup.js. Is there a way to mock all the models and functions automatically? Is there a similar JavaScript library which provides mockDeep from jest-mock-extended?

Jest environment has been torn down error in graphql, nodejs project. Used jest.useFakeTimers but still getting the error

Getting ReferenceError: You are trying to import a file after the Jest environment has been torn down From office/test/office.test.ts.
Used jest.useFakeTimers(); after imports, but the issue still exists. Is there any way to resolve it ?
Here is my jest.config.ts
import type { Config } from "#jest/types"
const config: Config.InitialOptions = {
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
moduleFileExtensions: [ 'js','ts'],
testEnvironment: "jest-environment-node",
fakeTimers: {
enableGlobally: true,
},
verbose: true
}
export default config
The test file office.test.ts
import {ApolloServer} from 'apollo-server'
import {expect,test,jest} from '#jest/globals';
import officeGql from '../controllers/controller'
jest.useFakeTimers();
test('Office Module Test', async () => {
let typeDefs = officeGql.types
let resolvers = officeGql.resolvers
let testServer = new ApolloServer({
typeDefs,
resolvers,
});
const response = await testServer.executeOperation({
query: `query offices(limit: $limit,offset: $offset){name, address}`,
variables: { limit: 10,offset:0 },
});
expect(response.data).toBeTruthy();
});

Fastify CLI decorators undefined

I'm using fastify-cli for building my server application.
For testing I want to generate some test JWTs. Therefore I want to use the sign method of the fastify-jwt plugin.
If I run the application with fastify start -l info ./src/app.js everything works as expected and I can access the decorators.
But in the testing setup I get an error that the jwt decorator is undefined. It seems that the decorators are not exposed and I just can't find any error. For the tests I use node-tap with this command: tap \"test/**/*.test.js\" --reporter=list
app.js
import { dirname, join } from 'path'
import autoload from '#fastify/autoload'
import { fileURLToPath } from 'url'
import jwt from '#fastify/jwt'
export const options = {
ignoreTrailingSlash: true,
logger: true
}
export default async (fastify, opts) => {
await fastify.register(jwt, {
secret: process.env.JWT_SECRET
})
// autoload plugins and routes
await fastify.register(autoload, {
dir: join(dirname(fileURLToPath(import.meta.url)), 'plugins'),
options: Object.assign({}, opts),
forceESM: true,
})
await fastify.register(autoload, {
dir: join(dirname(fileURLToPath(import.meta.url)), 'routes'),
options: Object.assign({}, opts),
forceESM: true
})
}
helper.js
import { fileURLToPath } from 'url'
import helper from 'fastify-cli/helper.js'
import path from 'path'
// config for testing
export const config = () => {
return {}
}
export const build = async (t) => {
const argv = [
path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'app.js')
]
const app = await helper.build(argv, config())
t.teardown(app.close.bind(app))
return app
}
root.test.js
import { auth, build } from '../helper.js'
import { test } from 'tap'
test('requests the "/" route', async t => {
t.plan(1)
const app = await build(t)
const token = app.jwt.sign({ ... }) //-> jwt is undefined
const res = await app.inject({
method: 'GET',
url: '/'
})
t.equal(res.statusCode, 200, 'returns a status code of 200')
})
The issue is that your application diagram looks like this:
and when you write const app = await build(t) the app variable points to Root Context, but Your app.js contains the jwt decorator.
To solve it, you need just to wrap you app.js file with the fastify-plugin because it breaks the encapsulation:
import fp from 'fastify-plugin'
export default fp(async (fastify, opts) => { ... })
Note: you can visualize this structure by using fastify-overview (and the fastify-overview-ui plugin together:

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);
}
})
};

TypeError: Slackbot is not a constructor

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

Resources