Quasar 2 + Apollo: Error: Apollo client with id default not found. Use provideApolloClient() if you are outside of a component setup - vue.js

followed the steps in https://github.com/quasarframework/app-extension-apollo/tree/v2 to install Apollo extension to Quasar 2.4.9:
"devDependencies": {
"#babel/eslint-parser": "^7.13.14",
"#quasar/app": "^3.0.0",
"#quasar/quasar-app-extension-apollo": "^2.0.0-beta.3",
"eslint": "^7.14.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-vue": "^7.0.0",
"eslint-webpack-plugin": "^2.4.0"
},
found two files generated which are related to apollo:
src/boot/apollo.js
src/apollo/index.js, where I modified the process.env.GRAPHQL_URI to be mine GraphQL server endpoint
I also created apollo.provider.js under root manually with :
// apollo.config.js
module.exports = {
client: {
service: {
name: "my-app",
// URL to the GraphQL API
url: "http://localhost:4000/graphql",
},
// Files processed by the extension
includes: ["src/**/*.vue", "src/**/*.js"],
},
};
in My Vue file, I have the following code:
<script>
import { useQuery } from "#vue/apollo-composable";
import gql from "graphql-tag";
export default {
setup() {
const { result } = useQuery(gql`
query GetAllBooks {
getAllBooks {
id
name
}
}
`);
},
...
However, running this code led to the following error:
index.esm.js?0df5:48 Uncaught (in promise) Error: Apollo client with id default not found. Use provideApolloClient() if you are outside of a component setup.
at resolveClient (index.esm.js?0df5:48:1)
at start (index.esm.js?0df5:277:1)
at immediate (index.esm.js?0df5:493:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?9e79:6737:1)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?9e79:6746:1)
at job (runtime-core.esm-bundler.js?9e79:7154:1)
at doWatch (runtime-core.esm-bundler.js?9e79:7199:1)
at watch (runtime-core.esm-bundler.js?9e79:7040:1)
at useQueryImpl (index.esm.js?0df5:491:1)
at useQuery (index.esm.js?0df5:228:1)
Any idea which part's wrong?
I found this post I am using vue 3 with apollo/client but getting an error, seems Ricky Vadala's also using Quasar and following the same steps. However, the following doesn't work:
import { apolloClients } from 'src/extensions/apollo/boot'
as 'src/extensions/apollo/boot' does not exist.
Also, I cannot find your-app\node_modules#quasar\quasar-app-extension-apollo\README.md. Maybe Ricky Vadala was using an older version?
Please kindly shed some light on this. Surprisingly I cannot find an example of Quasar 2 + Apollo from the Internet.

Got help from Scott in here.
End of the day, it's an RTFM issue. I didn't read README carefully:
The extension will add a configuration file into src/apollo and a boot file. You'll need to manually register the latter into quasar.conf.js > boot.
Translate that to real-world action, I need to modify quasr.conf.js, find the boot part, and modify it to be:
boot: ["apollo.js"],
After that, the error went away, and I could see the call to my GraphQL endpoint from Chrome dev tools.

Related

Getting: "ESLint: Unable to resolve path to module '#vercel/analytics/react'.(import/no-unresolved)" but package & path inside is actually present

As the title says, ESLint is complaining with this error message:
ESLint: Unable to resolve path to module '#vercel/analytics/react'.(import/no-unresolved)
In the line: import { Analytics } from '#vercel/analytics/react';
When following the instructions from this Vercel quickstart guide, using Next.js.
To sum up, the instructions are:
1- install package via NPM
npm install #vercel/analytics
2- in /pages/_app.tsx file, import it:
import { Analytics } from '#vercel/analytics/react';
function MyApp({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<Analytics />
</>
);
}
export default MyApp;
My packages used:
"next": "^12.1.0",
"react": "17.0.2",
"#typescript-eslint/eslint-plugin": "^4.33.0",
"#typescript-eslint/parser": "^4.33.0",
"eslint": "^7.32.0",
"eslint-config-next": "^12.2.5",
"eslint-config-prettier": "^6.15.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.10.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jest": "^24.7.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.27.0",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-testing-library": "^3.10.2",
The NPM package installed, has this folder structure:
/node_modules/#vercel
analytics/
dist/
react/
index.cjs
index.d.ts
index.js
index.cjs
index.d.ts
index.js
package.json
tsconfig.json
...
Notice how the path in node_modules actually is '#vercel/analytics/dist/react' rather than just '#vercel/anaylitics/react' as the instructions state to do in the code to use it.
But, when CTRL+click'ing on the variable imported Analytics, my IDE properly navigates me to the definition in node_modules, to the file #vercel/analytics/dist/react/index.d.ts, which is defined like so:
// ./node_modules/#vercel/analytics/dist/react/index.d.ts
// ...
declare function Analytics(props: AnalyticsProps): JSX.Element;
export { Analytics };
My ESLint config related to the import/ module is
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
paths: ['src'],
},
},
},
If I import it as this instead:
import { Analytics } from '#vercel/analytics/dist/react'
then ESlint doesn't complain, but TSC does, with this error message:
TS2305: Module '"#vercel/analytics/dist/react"' has no exported member 'Analytics'.
Which also doesn't seem to make sense as the IDE is still finding the definition, and I can also see how the export { Analytics } line is there, so it should work...
What ESlint config or steps should I take differently to make this work without any lint/compiler errors?
When using eslint you will need to use the plugin: eslint-import-resolver-typescript with version 3.1.0 or later.
We also merged this version into eslint-config-next in this Pull Request. So this issue should also be resolved by upgrading to the latest package (13.0.4)
There is also a issue on our Github repo which with the solution: https://github.com/vercel/analytics/issues/18#issuecomment-1318424277
I have a question into vercel for a solution as I have the same issue. Probably to be expected since this is a beta product. I added the following line to my _app.js file in the meantime which allowed me to bypass the linting error and deploy to vercel. I have tested and the analytics is showing so must simply be a bug.
...
// eslint-disable-next-line import/no-unresolved
import { Analytics } from "#vercel/analytics/react";
...
Try this way
//tsconfig.json
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#vercel/analytics/react": ["./node_modules/#vercel/analytics/dist/react"]
}
}

How to connect socket from VueJs with Sails js built in socket with sails.io.js in vue js?

I am trying to connect VueJs with Sails js over socket connection through Sails.io.js package but got not success till now.
I have taken VuejS starter template and sails js starter template to make this whole thing work.
My Frontend packages contains:
"sails.io.js": "^1.2.1",
"socket.io": "^3.1.0",
"socket.io-client": "^3.1.0",
"vue": "^2.6.11"
My Backend packages contains:
"#sailshq/connect-redis": "^3.2.1",
"#sailshq/lodash": "^3.10.3",
"#sailshq/socket.io-redis": "^5.2.0",
"grunt": "1.0.4",
"nodemon": "^2.0.7",
"sails": "^1.3.1",
"sails-hook-grunt": "^4.0.0",
"sails-hook-orm": "^2.1.1",
"sails-hook-sockets": "^2.0.0",
"socket.io": "^3.1.0"
On vuejs, my code is,
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script>
var io = require('sails.io.js')( require('socket.io-client') );
io.sails.autoConnect = false;
io.sails.useCORSRouteToGetCookie = false
io.sails.url = 'http://localhost:1337';
export default {
name: 'Home',
components: {},
mounted() {
setTimeout(() => {
var socket0 = io.sails.connect();
}, 2000)
}
};
</script>
So I am trying to connect it after 2 seconds after vue component is mounted.
But every time i am getting one same error that is,
WebSocket connection to
'ws://localhost:1337/engine.io/?EIO=4&transport=websocket' failed:
Connection closed before receiving a handshake response
Then i tried changing io.sails.url = 'http://localhost:1337' to io.sails.url = 'ws://localhost:1337' with
but then it started showing error that is (incase of io.sails.useCORSRouteToGetCookie = true),
GET ws://localhost:1337/__getcookie net::ERR_DISALLOWED_URL_SCHEME
but then it started showing error that is (incase of io.sails.useCORSRouteToGetCookie = false),
WebSocket connection to 'ws://localhost:1337/engine.io/?EIO=4&transport=websocket' failed: Connection closed before receiving a handshake response
In sails js my setting for socket in config/sockets.js file is,
module.exports.sockets = {
transports: [ 'websocket' ],
};
I have gone through so many links and documentation of sails js, but no success till now.
After this i tried to connect socket with other available packages. those are,
"socket.io": "^3.1.0",
"socket.io-client": "^3.1.0",
"vue-socket.io-extended": "^4.0.6",
While using above packages,
My Vue js code is,
<script>
import Vue from 'vue';
import Axios from 'axios'
import VueSocketIOExt from 'vue-socket.io-extended';
import { io } from 'socket.io-client';
var socket = io('http://localhost:1337', { transports: ["websocket"] } );
Vue.use(VueSocketIOExt, socket);
export default {
sockets: {
connect() {
console.log('socket connected')
},
disconnect() {
console.log('socket disconnected')
},
foo(data) {
console.log('this method was fired by the socket server. eg: io.emit("customEmit", data): ')
console.log('data');
console.log(data);
}
},
name: 'Home',
components: {},
mounted () {
this.checkHello()
},
methods: {
checkHello () {
Axios.get('http://localhost:1337/api/testhello')
.then((response) => {
console.log('response');
console.log(response);
}).catch((error) => {
console.log('error');
console.log(error);
})
}
}
};
</script>
I have created on route with /api/testhello on sails js controller,
whose code is,
module.exports = {
testHello: function(req, res) {
// req.socket is undefind here
console.log('Hello Called')
let socketClientObj = sails.io.sockets.clients();
console.log('socketClientObj.server.eio.clients');
console.log(socketClientObj.server.eio.clientsCount);
sails.io.sockets.emit('foo', { thisIs: 'thisMessage'});
return res.status(200).json({
anyData: 'we want to send back'
});
}
}
With this, I am getting output on console of sails,
Hello Called
socketClientObj.server.eio.clients
1
But with this, My vuejs is connected with sails js and i am getting that one client is connected through the socket but i dont know how to get the connected user socket id or how to get the Socket instance.
with above what i am seeking is:
how to make room with approach of not using sails.io.js at frontend but using sails default build in socket functionality ?
how to connect particular user to that room because i am not getting Socket id of user who requested the URL in this approach of not using sails.io.js?
How to configure Redis Pub sub for cluster mode in sails js in case of above approch of not using sail.io.js in vue js?
Thanks in advance.
After battling with the
WebSocket connection to 'ws://localhost:1337/engine.io/?EIO=4&transport=websocket' failed: Connection closed before receiving a handshake response
error for the longest time digging around everywhere and taking the same steps you did,
what solved my problem eventually was:
npm remove vue-socket.io-extended (if installed)
npm remove socket.io-js
npm install socket.io-js#^2.4.0
Seems that sails.js adapter doesn't support socket.io-js#3.0.0 yet,
connection is working with version socket.io-js version 1 and 2 only, 2.4.0 is the latest.

Use optimized es6 build of MobX for React Native in Metro config

I'm trying to use the optimized, es6 build of Mobx, as per the documentation:
Tip: the main entry point of the MobX 5 package ships with ES5 code for backward compatibility with all build tools. But since MobX 5 runs only on modern browsers anyway, consider using the faster and smaller ES6 build: lib/mobx.es6.js. For example by setting up a webpack alias: resolve: { alias: { mobx: __dirname + "/node_modules/mobx/lib/mobx.es6.js" }}
https://mobx.js.org/README.html#browser-support
This allows me to import mobx and get the mobx.es6.js build:
import mobx from 'mobx' // Yay, es6 build!!!
This works great for Webpack-based projects, such as Electron ones, where I already have it working.
For React Native, I can specify extraNodeModules in metro.config.js like so:
module.exports = {
resolver: {
extraNodeModules: {
"mobx": path.resolve(__dirname, 'node_modules/mobx/lib/mobx.es6.js'),
},
},
};
...except that doesn't work, I presume, because the mobx dependency resolves fine on its own, and so this configuration option is never checked.
I can use a separate alias for mobx, such as mobx-es6 but that's not ideal, to put it nicely:
module.exports = {
resolver: {
extraNodeModules: {
// Nooo I don't want to update a bazillion source files!.
"mobx-es6": path.resolve(__dirname, 'node_modules/mobx/lib/mobx.es6.js'),
},
},
};
Is there some other way to configure Metro so that I can override the mobx import like I can with Webpack?
I'm using RN 0.60.0.
The solution is to add a browser section to package.json:
"name": "My React Native Project",
"version": "0.0.1",
"browser": {
"mobx": "mobx/lib/mobx.es6.js"
},
This is undocumented, AFAICT, but there are hints here:
resolverMainFields
Type: Array<string>
Specify the fields in package.json files that will be used by the module resolver to do redirections when requiring certain packages. For example, using ['browser', 'main'] will use the browser field if it exists and will default to main if it doesn't.
https://facebook.github.io/metro/docs/configuration#resolvermainfields
import mobx from 'mobx' // Yay, es6 build!!!

How to use npm package dependency

I am learning to create npm packages by creating a session check function sessionFn that will popup a modal 1 minute before the session expires.
The function works as expected on the main app (a nuxtJS app) but when I make use it as an npm module I have to pass moment as an argument even though moment is listed as a dependency and is imported on the module.
I am missing something, why is my module not picking up moment? I want to use the module like sessionFn(this, to.path); instead of sessionFn(this, to.path, moment); moment is undefined when I don't pass it
Package files
package.json
{
"name": "hello-stratech",
"version": "1.0.17",
"description": "Hello Stratech",
"main": "index.js",
"keywords": [
"npm",
"hello",
"stratech"
],
"author": "Simo Mafuxwana",
"license": "ISC",
"dependencies": {
"moment": "^2.22.2"
}
}
index.js (main js file)
import moment from "moment";
module.exports = {
greeting(name) {
alert("Hello.. " + name);
},
department(dev) {
...
},
sessionFn(context) {
const exp = context.$store.state.session.exp;
let userSystemTime = new Date();
userSystemTime = moment.utc(userSystemTime)
const diff = moment(userSystemTime).diff(moment(exp), 'minutes');
if (diff = 1) {
// open modal
}
}
}
Usage
This is how I use the package in the main app
import moment from 'moment';
import { sessionFn } from "hello-stratech";
export default {
...
watch: {
$route(to) {
sessionFn(this, to.path, moment);
}
}
...
}
You dont need to import and pass moment into your function since you are importing it in your function file. You are not even using the passed argument in your function. So you can just safely dont pass it. You are also not using second argument that u pass to.path, so u can omit it too.
As a suggestion you should install and use eslint, which will catch such things. You can setup a nuxt project with eslint using create nuxt app for example.
There is also a bug in esm 3.21-3.22 that prevent commonjs and es6 imports work together https://github.com/standard-things/esm/issues/773 . That should be fixed when a new esm will be released
Try making moment as devDependancy through npm i moment --save-dev instead of dependency.
That way moment will only be needed when the package is development (means when you are developing the project) but not when it is used.
Hope it fixes your issue
for more depth knowledge

Including javascript globally using webpack

I'm using webpack and Vuejs. I have several components in my application, and I want to use momentjs globally. Everything I've tried so far doesn't seem to work and throws and Undefined error in console. Is there a way to get set moment.js globally available to all components from main.js using webpack?
These are the things I've tried (in main.js):
import moment from 'moment';
Vue.prototype.$moment = moment;
In a component I try to access it via this.$moment but get an undefined error.
I also tried:
import moment from 'moment';
Object.definePrototype(Vue.prototype, '$moment', { value: moment });
I also tried to access it via this.$moment, but get the same undefined error on this.$moment.
Am I missing a step or doing something wrong to include a javascript file globally to all components using webpack?
Thanks again for the help!
UPDATES
By the way, momentjs works fine if I import it in every component I want to use it in (as follows, however, this is what I'm trying to avoid):
import moment from 'moment';
...
let today_date = moment().format('YYYY-MM-DD');
UPDATES 2*
This is the exact error (with using this.):
Error in render function: "TypeError: Cannot read property '$moment' of undefined"
This is error (without using this.):
Error in render function: "ReferenceError: $moment is not defined"
Moment is added via dependencies in package.json:
...
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"css-loader": "^0.28.5",
"es6-promise": "^4.1.1",
"moment": "^2.18.1",
...
Code usage within a component:
...
filters: {
getYear(date) {
return this.$moment(date).format('YYYY');
},
getMonth(date) {
return this.$moment(date).format('MMM');
},
getDay(date) {
return this.$moment(date).format('D');
},
},
...