I am working with a full stack GraqlQL based application. The server is working fine and now I need to try out the first queries and mutations on the client side. For some reason, the "monitoring" route, and everything that follows it, is not displayed. Below I will show the files that I have edited or created.
items.graphql:
query {
items {
_id
name
}
}
environment.js:
'use strict';
module.exports = function(environment) {
let ENV = {
apollo: {
apiURL: 'http://localhost:5000/graphql'
},
modulePrefix: 'client',
environment,
rootURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
//
},
EXTEND_PROTOTYPES: {
Date: false
}
},
APP: {
//
}
};
if (environment === 'development') {
//
}
if (environment === 'test') {
ENV.locationType = 'none';
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
ENV.APP.rootElement = '#ember-testing';
ENV.APP.autoboot = false;
}
if (environment === 'production') {
//
}
return ENV;
};
monitoring.js (route):
import Route from '#ember/routing/route';
import { queryManager } from 'ember-apollo-client';
import query from 'client/gql/items.graphql';
export default Route.extend({
apollo: queryManager(),
model() {
return this.apollo.watchQuery({ query }, 'items');
}
});
monitoring.hbs:
<h3>Monitoring</h3>
<div>
{{#each model as |item|}}
<h3>{{item.name}}</h3>
{{/each}}
</div>
{{outlet}}
Thank you for attention!
I see this error:
Uncaught (in promise) Error: fetch is not defined - maybe your browser targets are not covering everything you need?
The solution is to fix two things.
First is to put this in ember-cli-build.js:
'ember-fetch': {
preferNative: true
}
And fix the route file:
import Route from '#ember/routing/route';
import { queryManager } from 'ember-apollo-client';
import query from 'client/gql/queries/items.graphql';
export default Route.extend({
apollo: queryManager(),
async model() {
let queryResults = await this.apollo.watchQuery({ query }, 'items');
return Object.values(queryResults);
}
});
Related
I am integrating Vite SSR to existing vue project. I copied vite configuration from SSR playground project and bumped ionic version to 6 because of dynamic loading issue from stencil.
After upgrading, it isn't compiling, showing this error.
12:03:15 AM [vite] Error when evaluating SSR module /src/components/ImportType.vue:
/data/Work/ssr-vue/node_modules/#ionic/core/components/ion-accordion.js:4
import { proxyCustomElement, HTMLElement, h, Host } from '#stencil/core/internal/client';
^^^^^^
SyntaxError: Cannot use import statement outside a module
Here is my vite.config.js file
const vuePlugin = require('#vitejs/plugin-vue')
const vueJsx = require('#vitejs/plugin-vue-jsx')
const virtualFile = '#virtual-file'
const virtualId = '\0' + virtualFile
const nestedVirtualFile = '#nested-virtual-file'
const nestedVirtualId = '\0' + nestedVirtualFile
/**
* #type {import('vite').UserConfig}
*/
module.exports = {
plugins: [
vuePlugin(),
vueJsx(),
{
name: 'virtual',
resolveId(id) {
if (id === '#foo') {
return id
}
},
load(id) {
if (id === '#foo') {
return `export default { msg: 'hi' }`
}
}
},
{
name: 'virtual-module',
resolveId(id) {
if (id === virtualFile) {
return virtualId
} else if (id === nestedVirtualFile) {
return nestedVirtualId
}
},
load(id) {
if (id === virtualId) {
return `export { msg } from "#nested-virtual-file";`
} else if (id === nestedVirtualId) {
return `export const msg = "[success] from conventional virtual file"`
}
}
}
],
ssr: {
external: ["npm: #ionic/vue"]
},
build: {
minify: false
}
}
Please help me.
I have a chrome extension with the following webpack.config.js:
module.exports = {
mode,
entry: {
"content/content": [
"./src/js/content/content.js",
"./src/js/store.js",
"./src/js/content/overlay/style.scss",
],
"background/background": [
"./src/js/background/utils.js",
"./src/js/background/background.js",
],
"overlay/overlay": "./src/js/content/overlay/index.js",
"popup/popup": "./src/js/content/popup/index.js",
},
looking at
Shared vuex state in a web-extension (dead object issues)
https://github.com/xanf/vuex-shared-mutations
Adding a wrapper around browser local storage:
browserStore.js
import browser from "#/js/browser";
export function getStorageValue(payload) {
return new Promise((resolve) => {
browser.storage.local.get(payload, (items) => {
if (items) {
resolve(items);
}
});
});
}
export function setStorageValue(payload) {
return new Promise((resolve) => {
browser.storage.local.set(payload, (value) => {
resolve(value);
});
});
}
In "./src/js/content/popup/firstpage/store/index.js" vuex store is defined as:
import Vue from "vue";
import Vuex from "vuex";
import "es6-promise/auto";
import createMutationsSharer from "vuex-shared-mutations";
import dummyData from "./dummyData";
import { getStorageValue, setStorageValue } from "#/js/store";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
chromePagesState: {
allSections: [],
},
},
getters: {
...
},
mutations: {
setChromePagesState(state, value) {
...
},
// this function is to be called from a content script
addWhiteListedItem(state, item) {
// state not initialized here
state.chromePagesState.allSections[0].itemSectionCategory[0].tasks.splice(
0,
0,
item
);
},
...
}
actions: {
async saveChromePagesState({ state }) {
// Save only needed fields
let data = {
...
};
await setStorageValue({ inventoryData: JSON.stringify(data) });
},
async loadChromePagesState({ commit }) {
const json = await getStorageValue("inventoryData");
// json always an empty object
commit(
"setChromePagesState",
Object.keys(json).length === 0 && json.constructor === Object
? json
: dummyData
);
},
async loadChromePagesStateBrowser({ commit }) {
browser.runtime
.sendMessage({ type: "storeinit", key: "chromePagesState" })
.then(async (chromePagesState) => {
const json = await getStorageValue("inventoryData");
commit(
"setChromePagesState",
Object.keys(json).length === 0 && json.constructor === Object
? json
: dummyData
);
});
},
plugins: [
createMutationsSharer({
predicate: [
"addWhiteListedItem",
"loadChromePagesState",
"loadChromePagesStateBrowser",
],
}),
],
},
the background script has a listener; src/background/background.js:
browser.runtime.onMessage.addListener((message, sender) => {
if (message.type === "storeinit") {
return Promise.resolve(store.state[message.key]);
}
});
The content script that needs to make use of the shared store has an entry point in content.js:
import { initOverlay } from '#/js/content/overlay';
import browser from '#/js/browser';
browser.runtime.onMessage.addListener(function (request, _sender, _callback) {
// vue component gets created here:
if (request && request.action === 'show_overlay') {
initOverlay();
}
return true; // async response
});
initOverlay() creates a vue component in ./src/js/content/overlay/index.js:
import Vue from "vue";
import Overlay from "#/js/content/overlay/Overlay.vue";
import browser from "#/js/browser";
import { getStorageValue } from "#/js/store";
import store from "../popup/firstpage/store";
Vue.prototype.$browser = browser;
export async function initOverlay(lockScreen = defaultScreen, isPopUp = false) {
...
setVueOverlay(overlayContainer, cover);
...
}
function setVueOverlay(overlayContainer, elem) {
if (!elem.querySelector("button")) {
elem.appendChild(overlayContainer);
elem.classList.add("locked");
new Vue({
el: overlayContainer,
store,
render: (h) => h(Overlay, { props: { isPopUp: isPopUp } }),
});
}
}
Overlay.vue only needs to call a mutation (addWhiteListedItem) from store:
<template>
<button
#click="addToWhiteList()"
>White list!</button
>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
data() {
return {
};
},
computed: mapState(["chromePagesState"]),
methods: {
...mapMutations(["addWhiteListedItem"]),
addToWhiteList() {
console.log("addToWhiteList()");
let newItem = {
...
};
// store not defined fails with:
Uncaught TypeError: Cannot read property 'itemSectionCategory' of undefined
at Store.addWhiteListedItem (index.js:79)
at wrappedMutationHandler (vuex.esm.js:853)
at commitIterator (vuex.esm.js:475)
at Array.forEach (<anonymous>)
at eval (vuex.esm.js:474)
at Store._withCommit (vuex.esm.js:633)
at Store.commit (vuex.esm.js:473)
at Store.boundCommit [as commit] (vuex.esm.js:418)
at VueComponent.mappedMutation (vuex.esm.js:1004)
at eval (Overlay.vue?./node_modules/vue-loader/lib??vue-loader-options:95)
this.addWhiteListedItem(newItem);
}, 1500);
},
},
};
</script>
Why doesn't Overlay.vue "see" the state of store?
Flow:
enabling the extension injects a content script into a page
content script imports store object (that is not yet initialized)
upon clicking popup (/new tab) popup.js sends a message to the background script that also imports store and calls a mutation (that initializes state):
background.js
import store from "../content/popup/firstpage/store";
browser.runtime.onMessage.addListener((message, sender) => {
console.log("in background");
if (message.type === "storeinit") {
console.log("got storeinit message. Message key: ", message.key);
store.dispatch("loadChromePagesState");
console.log("current state in store:", JSON.stringify(store.state));
console.log(
"store.state[message.key]:",
JSON.stringify(store.state[message.key])
);
return Promise.resolve(store.state[message.key]);
}
});
now the store's state should be initialized and the mutation callable from the content script (vue-shared-mutations guarantees it)
Does export default new Vuex.Store mean that every script that imports the store gets a new instance with a default state that is not in sync with other imports?
As the error message suggests itemSectionCategory can not be found as it is expected to be an element of allSections[0]. However you never define index 0 of allSections before calling it.
So in short you need to either define allSections index 0 before using it, or make the index part optional and create it if it's not found.
Otherwise you could try one of the following solutions:
if you need to rely on index 0 being available, check if it is set before calling your function
!state.chromePagesState.allSections[0] ? [... insert initialize function call ...]
Maybe optional chaining could be another solution depending on what you use it for afterwards, for an example How to use optional chaining with array or functions?
I'm currently migrating an application I developed from redux to apollo. I'm following this example trying to implement apollo-link-state and apollo-cache-inmemory but I'm struggling to understand how their framework works. It would be great if someone could answer some questions, so here we go:
Use Case: Store modals information (basically wether it's open or not) in my cache memory
Here is my code:
// apollos.js
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { withClientState } from 'apollo-link-state';
import { HttpLink } from 'apollo-link-http';
import { ApolloLink } from 'apollo-link';
import { modalStateQuery } from "./common/queries/modal.query";
const httpLinkOptions = {
uri: 'http://localhost:8080/graphql',
};
const httpLink = new HttpLink(httpLinkOptions);
const cache = new InMemoryCache({
dataIdFromObject: o => o.id
});
const typeDefs = `
type Modal {
id: ID!
open: Boolean!
}
type Query {
modal(id: ID!): Modal
modals: [Modal]
}
`;
const defaults = {
modals: [
{
__typename: "Modal",
id: "login",
open: false
},
{
__typename: "Modal",
id: "signup",
open: false
}
]
};
const resolvers = {
Query: {
modal: (_, { id }, { cache }) => {
console.log("get modal");
try {
const data = cache.readQuery({ query: modalStateQuery.getOne, variables: { id } });
console.log("data", data);
} catch (e) {
console.log("error", e);
}
return null;
},
modals: (_, { }, { cache }) => {
console.log("Modal List Resolver"); // this is never logged
}
}
}
const stateLink = withClientState({
cache,
resolvers,
defaults,
typeDefs
});
const link = ApolloLink.from([stateLink, httpLink]);
const client = new ApolloClient({
link,
cache,
dataIdFromObject: o => o.id
});
export default client;
-
// modal.query.js
import gql from "graphql-tag";
export const modalStateQuery = {
getOne: gql`
query ModalState($id: String!) {
modal(id: $id) #client {
id
open
}
}`,
getAll: gql`
query {
modals #client {
id
open
}
}
`
};
-
// modal.js
// ...
// fetching both for test purposes
export default compose(
graphql(modalStateQuery.getOne, { name: "modal" }),
graphql(modalStateQuery.getAll, { name: "allModals" })
)(Modal);
Ok, now the questions:
The number one problem I'm having is with the modal($id: id) query. When I execute modalStateQuery.getAll the modals resolver is never called, but I still get the list I defined in defaults in my component. But when I execute modalStateQuery.getOne I always get the same error:
error Error: Can't find field modal({"id":"login"}) on object (ROOT_QUERY) {
"modals": [
{
"type": "id",
"generated": false,
"id": "login",
"typename": "Modal"
},
{
"type": "id",
"generated": false,
"id": "signup",
"typename": "Modal"
}
]
}.
at readStoreResolver (readFromStore.js:71)
at executeField (graphql.js:90)
at graphql.js:46
at Array.forEach (<anonymous>)
at executeSelectionSet (graphql.js:40)
at graphql (graphql.js:35)
at diffQueryAgainstStore (readFromStore.js:124)
at readQueryFromStore (readFromStore.js:37)
at InMemoryCache../node_modules/apollo-cache-inmemory/lib/inMemoryCache.js.InMemoryCache.read (inMemoryCache.js:84)
at InMemoryCache../node_modules/apollo-cache-inmemory/lib/inMemoryCache.js.InMemoryCache.readQuery (inMemoryCache.js:181)
What is this array it is showing to me? Why isn't there all the props I defined in defaults (like open: false)? Could it be something wrong with the way I create my defaults?
In the apollo-cache-inmemory docs it doesn't define any resolvers, it just says that you should query your data just like you are doing it in the backend, passing the variables.
Also, why does modalStateQuery.getAll works even though the resolver is never called? What if I do want that resolver to be called (Maybe I want to check my backend first to check permissions or smth)?
Another curious behavior I noticed: When executing the modal resolver, the id variable is always correct, even though I didn't explicitly pass it as variable in my component, but the Modal.js component does have an id props that I pass to it:
return <Modal id="login"><LoginForm /></Modal>;
It makes me believe that apollo already recognizes that the Modal.js is being called with an id prop and automatically passes it to the query as a variable. Is that correct? It does it for any variable?
Thanks!
I am trying to get the following example working:
https://github.com/typeorm/javascript-example/tree/master/src/app3-es6
I am running into the following error:
Error
at new RepositoryNotFoundError (...\node_modules\typeorm\connection\error\RepositoryNotFoundError.js:24:23)
at Connection.findRepositoryAggregator (...\node_modules\typeorm\connection\Connection.js:513:19)
at Connection.getRepository (...\node_modules\typeorm\connection\Connection.js:405:21)
at ...\index.js:27:37
name: 'RepositoryNotFoundError',
message: 'No repository for "Post" was found. Looks like this entity is not registered in current "default" connection?'
here is index.js
const typeorm = require("typeorm"); // import * as typeorm from "typeorm";
const Post = require("./model/Post"); // import {Post} from "./model/Post";
// import Post from './model/Post.js';
const Category = require("./model/Category"); // import {Category} from "./model/Category";
typeorm.createConnection({
driver: {
type: "oracle",
host: "localhost",
port: 1521,
username: "uname",
password: "pwd",
sid: "dev"
},
entities: [
__dirname + "/entity/*.js"
],
autoSchemaSync: true
}).then(function (connection) {
console.log(connection);
let post = new Post.Post();
post.title = "Control flow based type analysis";
post.text = "TypeScript 2.0 implements a control flow-based type analysis for local variables and parameters.";
post.categories = [new Category.Category(0, "TypeScript"), new Category.Category(0, "Programming")];
let postRepository = connection.getRepository(Post.Post);
postRepository.persist(post)
.then(function(savedPost) {
console.log("Post has been saved: ", savedPost);
console.log("Now lets load all posts: ");
return postRepository.find();
})
.then(function(allPosts) {
console.log("All posts: ", allPosts);
});
}).catch(function(error) {
console.log("Error: ", error);
});
Post.js in /model/
/*export */ class Post {
constructor(id, title, text, categories) {
this.id = id;
this.title = title;
this.text = text;
this.categories = categories;
}
}
module.exports = {
Post: Post
};
Category.js
/*export */ class Category {
constructor(id, name) {
this.id = id;
this.name = name;
}
}
module.exports = {
Category: Category
};
PostSchema.js in /entity/
const Post = require("../model/Post"); // import {Post} from "../model/Post";
const Category = require("../model/Category"); // import {Category} from "../model/Category";
const PostSchema = {
target: Post,
columns: {
id: {
primary: true,
type: "int",
generated: true
},
title: {
type: "string"
},
text: {
type: "text"
}
},
relations: {
categories: {
target: Category,
type: "many-to-many",
joinTable: true,
cascadeInsert: true
}
}
};
module.exports = {
PostSchema: PostSchema
};
CategorySchema.js
const Category = require("../model/Category"); // import {Category} from "../model/Category";
const CategorySchema = {
target: Category,
columns: {
id: {
primary: true,
type: "int",
generated: true
},
name: {
type: "string"
}
}
};
module.exports = {
CategorySchema: CategorySchema
};
i dont know what i am doing wrong
It looks like your entity import is not working. If you import via the wildcard:
entities: [
__dirname + "/entity/*.js"
],`
Make sure your model is compiled to js. You also could just import
createConnection({
...,
entities: [
Post,
...
],}).then(...)
For those who are using typescript and experience this problem: Be reminded that you need to include both ts and js file suffixes when specifying the entities-path:
ts used when locally running with ts-node
js used when having
built for production via tsc.
Code:
import * as path from 'path';
// ...
entities: [
// assuming _dirname is your project root
path.resolve(__dirname, '**/*.entity{.ts,.js}'),
],
I had the same problem for months and finally figured out what I was doing wrong.
When you import Entities, make sure the file names are EXACTLY matching. It's not going to throw any errors, but during the run time, it's going to throw the above error.
Ex. In the entity or model classes, if we import like this,
import { FooClass } from "./foo-Class.model";
it's different from
import { FooClass } from "./foo-class.model";
It won't show any errors, but when you try to call the table, it will show the exact same error.
I had the same problem. None of the solutions worked for me. After much debugging I figured out that you'll receive this error if your connection is closed.
So if you are facing this error, make sure your connection is not closed.
try {
connection = getConnection(config.name)
//after adding this if block, I no longer received this error
if (!connection.isConnected) {
await connection.connect();
}
} catch(err) {
connection = await createConnection(config);
}
If it is closed, connect it again.
I am trying to create a Todos example app using the generator-react-webpack from here. Everything works until I started using alt for the flux pattern. When I run the project using npm run, I got the following error:
TodoStore.js: Unexpected token (12:0)
10 | import _ from 'lodash';
11 |
12 | #datasource(CategorySource)
It complains about the line 12 above for the #datasource decorator. Below is the code from my TodoStore.js:
'use strict';
const alt = require('../alt');
const Actions = require('../actions');
import {decorate, bind, datasource} from 'alt/utils/decorators';
import CategorySource from '../sources/CategorySource';
import _ from 'lodash';
#datasource(CategorySource)
#decorate(alt)
class TodoStore {
constructor() {
this.state = {
user: null,
todos: null,
todosLoading: true
};
}
#bind(Actions.todosLoading)
todosLoading() {
this.setState({
todosLoading: true
});
}
#bind(Actions.todosReceived)
receivedTodos(todos) {
_(todos)
.keys()
.each((k) => {
todos[k].key = k;
})
.value();
this.setState({todos, todosLoading: false});
}
#bind(Actions.categoriesReceived)
receivedCategories(categories) {
let selectedCategory;
_(categories)
.keys()
.each((key, index) => {
categories[key].key = key;
if (index == 0) {
categories[key].selected = true;
selectedCategory = categories[key];
}
})
.value();
this.setState({categories, selectedCategory, todosDirty: true});
}
#bind(Actions.login)
login(user) {
this.setState({user: user});
}
}
export default alt.createStore(TodoStore);
I found this post for a similar problem, but I don't have any luck getting it to work by changing this line: test: /\.jsx?$/, in my webpack.config.js file.
found out the reason: because it does not recognize the ES7 decorator syntax. I created a file named .babelrc at the root and its content is:
{
"stage": 0
}
Now everything works! Hope this will help someone in the future.