I am very new to GraphQL, so maybe I am just missing something here.
i am currently creating an GraphQL endpoint of a Postgres SQL Database using the PostGraphile
I am able to perform queries, but i just found out about GraphQL Subscriptions and apparently PostGraphile supports it as explained here. Here its what I doing.
Express Server
const express = require("express");
const { postgraphile, makePluginHook } = require("postgraphile");
const { default: PgPubsub } = require("#graphile/pg-pubsub");
const pluginHook = makePluginHook([PgPubsub]);
var cors = require('cors');
const app = express();
app.use(cors());
let url = "postgres://postgres:docker#localhost:5432/dvdrental";
app.use(postgraphile(url,"public", {
graphiql:true,
pluginHook,
subscriptions: true,
simpleSubscriptions: true,
}));
app.listen(3000);
Subscribing like
subscription {
listen(topic: "hello") {
query {
allPayments {
nodes {
customerId
paymentDate
nodeId
}
}
}
}
}
Triggering like
postgres=# select pg_notify( 'postgraphile:hello', '{}' );
But I am not seeing anything on the graphiql response
WebSocket/Network
Here it is what I get at the WebSocket/Network panel #Benjie.
The {type:"ka} actions appears to be fired in a random interval.
Related
I've been following video link from Moralis web3 (youtube) meanwgile I got stuck when I need to fetch data using token price Moralis API. I want the price details to be printed in the console when i do
npm start
the expected output in console is:
{
nativePrice: {
value: '13851123944545175839',
decimals: 18,
name: 'Ether',
symbol: 'ETH'
},
usdPrice: 23176.58785953117,
exchangeAddress: '0x1f98431c8ad98523631ae4a59f267346ea31f984',
exchangeName: 'Uniswap v3'
}
In localhost it should return empty json object '{}' but when I opened the same in localhost it is showing:
Cannot GET /tokenPrice
I tried different method provided in moralis doc its working fine but I did same as the tutorial that throws me error:
const express = require("express");
const Moralis = require("moralis").default;
const { EvmChain } = require("#moralisweb3/common-evm-utils");
const app = express();
const cors = require("cors");
require("dotenv").config();
const port = 3001;
app.use(cors());
app.use(express.json());
app.get("./tokenPrice", async (req, res) => {
const { query } = req;
const responseOne = await Moralis.EvmApi.token.getTokenPrice({
address: query.addressOne,
});
const responseTwo = await Moralis.EvmApi.token.getTokenPrice({
address: query.addressTwo,
});
console.log(responseOne.raw);
console.log(responseTwo.raw);
return res.status(200).json({});
});
Moralis.start({
apiKey: process.env.MORALIS_KEY,
}).then(() => {
app.listen(port, () => {
console.log(`Listening for API Calls`);
});
});
also I want to know what does that {query} & addressOne means here as I've never declared any var like before in my code.
I want to know what {query} and addressOne is , whether express js property or moralis
want to know why and where error occured and solution to resolve.
For addressOne and addressTwo, those are the query parameters used in your request. If you check the video you can see him showcasing an example of how the request should look like:
http://localhost:3001/tokenPrice?addressOne=0x51491...cf986ca&addressTwo=0xdac17f...6994597
And use 2 addresses of the tokens you wish to get the price for. You can indeed extend the logic to use more addresses
In the video at minute 45:00 You can see how the code should look like. Please make sure you complete your code for it to work properly.
I have a Nuxt.js app.
How to use Apollo writeQuery method on client side without using mutation?
I want when I click the button (bind to transfer method), all products (on backend) to be saved on client server (frontend) cache, and never query the main server.
When a new person visit the page for first time, I don't want any query to be sent to the backend server and always use frontend nodejs cache. Even for first visit.
For the backend I use WP-GraphQL
When I use:
import gql from 'graphql-tag';
const getProducts = gql`
query getProducts {
products {
nodes {
name
id
}
}
}
`
export default{
methods: {
async transfer() {
const { data } = await this.$apollo.query({
query: getProducts,
fetchPolicy: 'network-only',
})
await this.$apollo.writeQuery({
query: getProducts,
data,
})
},
},
async asyncData({ app }) {
let client = app.apolloProvider.defaultClient
const { data } = await client.query({
query: getProducts,
fetchPolicy: 'cache-only',
})
return { products: data }
},
}
It returns error:
TypeError: _this.$apollo.writeQuery is not a function
How can I have a Foxx service use base collections for auth operations? For example I want the User management tutorial at https://docs.arangodb.com/3.3/Manual/Foxx/Users.html
to use collections "users" and "sessions" instead of "test_users" and "test_sessions", where "test" is the name of my mountpoint.
I want to run multiple services all working off the same base collections. But if I go with whats given in the tutorials, I end up with auth collections and routes which are specific to a service, which doesnt males much sense to me.
My setup.js is;
'use strict';
const db = require('#arangodb').db;
const sessions = module.context.collectionName('sessions');
const users = module.context.collectionName('users');
if (!db._collection(sessions)) {
db._createDocumentCollection(sessions);
}
if (!db._collection(users)) {
db._createDocumentCollection(users);
}
db._collection(users).ensureIndex({
type: 'hash',
fields: ['username'],
unique: true
});
and my index.js is;
'use strict';
const joi = require('joi');
const createAuth = require('#arangodb/foxx/auth');
const createRouter = require('#arangodb/foxx/router');
const sessionsMiddleware = require('#arangodb/foxx/sessions');
// const db = require('#arangodb').db;
const auth = createAuth();
const router = createRouter();
const users = db._collection('users');
const sessions = sessionsMiddleware({
storage: module.context.collection('sessions'),
transport: 'cookie'
});
module.context.use(sessions);
module.context.use(router);
// continued
router.post('/signup', function (req, res) {
const user = {};
try {
user.authData = auth.create(req.body.password);
user.username = req.body.username;
user.perms = [];
const meta = users.save(user);
Object.assign(user, meta);
} catch (e) {
// Failed to save the user
// We'll assume the uniqueness constraint has been violated
res.throw('bad request', 'Username already taken', e);
}
req.session.uid = user._key;
req.sessionStorage.save(req.session);
res.send({success: true});
})
.body(joi.object({
username: joi.string().required(),
password: joi.string().required()
}).required(), 'Credentials')
.description('Creates a new user and logs them in.');
I tried using const users = db._collection('users'); instead of const users = module.context.collection('users'); but that throws swagger api errors.
to achieve that you need to change the assignment of collection names from module.context.collectionName('nameOfCollection') to 'nameOfCollection' in all files, because module.context.collectionName prefixes string with name of service
so
setup.js
const sessions = 'sessions';
const users = 'users';
index.js
const users = db._collection('users');
const sessions = sessionsMiddleware({
storage: 'sessions',
transport: 'cookie'
});
however, that approach is antipattern for case when more services need access to same underlying collections (for example teardown of one service can delete those collections for other services).
for that case you should utilize dependencies, only your auth service should have access to its own collections and other services should have auth service as dependency and access auth data through auth service.
auth service needs to have
in manifest.json
"provides": {
"myauth": "1.0.0"
}
in index.js or what file you pointing as main in manifest.json
module.exports = {
isAuthorized (id) {
return false; // your code for validating if user is authorized
}
};
consuming service needs to have
in manifest.json
"dependencies": {
"myauth": {
"name": "myauth",
"version": "^1.0.0",
"description": "Auth service.",
"required": true
}
}
and then you can register it and call it
const myauth = module.context.dependencies.myauth;
if (myauth.isAuthorized()) {
// your code
} else {
res.throw(401);
}
for further steps in terms of authorization of requests check how to use Middleware and Session middleware
god speed
Really hoping someone can help me.
What I am trying to do: Call a REST API for a json and resolve a Angular 2 promise.
ServerAPI running Node.js/ExpressJS/Lodash
Server.js file:
var express = require('express');
var app = express();
var bodyParser = require("body-parser");
var data = require('./data.json');
var _ = require('lodash');
var cors = require('cors');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());
app.get('/GetData', function (req, resp) {
if (req.query.search != null) {
var result = _.find(data, function (o) {
return o.value === req.query.search.toLowerCase().trim()
});
return resp.send(result)
}
});
app.listen(1337, function () {
console.log('Listening at Port 1337');
});
Ran as tested http://localhost:1337/GetData?search=colorado and returns a vaild json object.
ClientAPI
Service file calling HTTP request:
import {Injectable} from "#angular/core";
import {Http} from "#angular/http";
import {Config} from "../config";
import {SearchResult} from "../models/search-result.model";
import {MockSearchData} from "../mock/mock-search-results";
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
#Injectable()
export class ApiDataService {
constructor(private http:Http) {
}
public performSearchRequest(searchTerm:string,queryType:string):Promise<SearchResult[]> {
return new Promise<SearchResult[]>((resolve, reject) => {
let url = Config.apiBaseUrl + Config.searchApi;
url += "?search=" + searchTerm;
console.log("Your query to be: " + url);
if (searchTerm != "") {
if (queryType == 'mock') {
resolve(MockSearchData);
} else if (queryType == 'api') {
let data = [];
this.http.get(url)
.map(resp => resp.json())
.subscribe(getData => data = getData);
resolve(data);
} else {
reject("No query type found.");
}
} else {
reject("Please enter a search term.");
};
});
}
}
The resolve of the mock data which is a local json file within the ClientAPI works perfectly. I need to get the if function for the api query type to work.
The Angular app starts with no issue and runs the http.get without error. I checked the network tab under the dev tools and can see that a HTTP request was done and returns its response is the valid JSON object I want resolved e.g there is data being returned. Yet the table i am resolving this into is blank.
WHAT AM I DOING WRONG!
The issue occurs here:
this.http.get(url)
.map(resp => resp.json())
.subscribe(getData => data = getData);
resolve(data);
You subscribe to the observable, but it isn’t “resolved” yet when you call resolve directly afterwards. That means you’re really just calling resolve([]).
Instead, do something like this:
this.http.get()./*...*/.subscribe(result => resolve(result));
You also might want to look into the toPromise method on Observables as well as the way to construct a resolved promise directly.
In express code:
var kue = require('kue');
var express = require('express');
var ui = require('kue-ui');
var app = express();
app.use('/api', kue.app);
app.use('/kue', ui.app);
I can access: http://localhost:1337/kue and http://localhost:1337/api just fine.
I tried to move this into my sails hook:
var kue = require('kue');
var ui = require('ui');
module.exports = function galaxyKueSyncHook(sails) {
return {
routes: {
before: {
'get /kue': ui.app,
'get /api': kue.app
}
}
};
}
It doesn't work. I get a blank pages when access the same URLs.
How do properly get this to work in sails?
Additionally, I was able to get express code to work in config/http.js with
module.exports.http = {
customMiddleware: function (app) {
app.use(...);
But, I really want the function to be added in an installable hook.
You can use express like:
var app = sails.hooks.http.app;
app.use('/api', kue.app);