Fauna: Select from pure JS - javascript

I'm interested in using Fauna from browser from pure JS in read-only mode.
Either official documentation lacks understandable information for this case or I can't figure it out.
Please help me to understand.
I'm trying to run such query:
Map(Paginate(Documents(Collection('spells'))), Lambda('x', Get(Var('x'))));
Running this query from the shell gives me the result.
I want to push this query to JavaScript variable.
But I don't understand what to do.
Here is my code:
var client = new faunadb.Client({
secret: '320438826900127936',
keepAlive: false,
domain: 'db.eu.fauna.com',
// NOTE: Use the correct domain for your database's Region Group.
port: 443,
scheme: 'https',
});
var helper = client.paginate(
q.Match(
q.Index('spells'),
'101'
)
)
paginate.then(function(response) {
console.log(response.ref) // Would log the ref to console.
})
Please help me to get output from DB using pure JavaScript.

Using the JavaScript driver, all of the FQL functions are in faunadb.query namespace. Typically, developers would do this at the top of their scripts:
const faunadb = require('faunadb')
const q = faunadb.query
After that, the FQL functions can be access using the q object. For example: q.Add(1, 2).
Otherwise, you can use destructuring to import FQL functions into the script's namespace, like so:
const faunadb = require('faunadb')
const {
Documents,
Collection,
Get,
Index,
Lambda,
Match,
Paginate
} = faunadb.query
and then you can call the FQL functions "directly", e.g. Add(1, 2).
If you use destructuring, be sure to import all of the FQL functions that you intend to use in your queries. Not all FQL functions can be imported "as-is", since some of their names would collide with built-in JavaScript names, such as Function. For those, you have to assign them directly:
const FaunaFunction = faunadb.query.Function
And then use the local name that you specified (FaunaFunction in this case) when composing queries.
Either way, the query itself isn't sent to Fauna until the client.query(), or in your case, client.paginate(), function is called.
That means that you can assign the FQL function calls to JavaScript variables. With the desired query, that could look like this:
const spellsQuery = q.Map(
q.Paginate(
q.Documents(q.Collection('spells'))
),
q.Lambda('x', q.Get(q.Var('x')))
)
Then you can do this:
client.query(spellsQuery)
.then(res => console.log(res))
You can use the client.paginate if you are only performing pagination. Your desired query calls Map, so the client.pagination helper gets in your way. My example uses client.query.
Note that when you configure your client connection object, you don't need to specify the port and scheme options; you're using the default values already. And you likely shouldn't change the keepAlive option unless your workflow specifically requires it.
Plus, I see that you didn't include an actual secret in your example, which is a good thing: if you did include an actual secret, anyone with that secret could access your database just like you can.
If you want to see a complete (but simple) Fauna-based application that runs in a web page, see: https://github.com/fauna-labs/todo-vanillajs

Related

Creating a new array inside of guild Discord.js, TypeError: interaction.guild.push is not a function

I am trying to make a /quote command where it saves the discord id of the person mentioned and the quote itself. I want to save it to the specific guild so that I can use it later for a command like /quote-list, but I am getting the error interaction.guild.push is not a function. My code is:
async execute(interaction) {
let inputuser = interaction.options.getUser('user');
let quote = interaction.options.getString('quote');
function QuoteObjectCheck(){
if (!interaction.guild.quotes){
var quoteObject = []
interaction.guild.push(quoteObject);
}
console.log(interaction.guild.quotes);
}
QuoteObjectCheck();
const newQuote = { userid: `${inputuser.id}`, quote: `${quote}`};
interaction.guild.quotes.push(newQuote)
console.log(interaction.guild.quotes);
interaction.followUp(`Succesfully saved new quote from ${inputuser}. Do /quote-list to get a random quote`)
},
I am new to discord.js and javascript in general btw and I would appreciate any help.
So this isn't going to work at all. You're writing a value to the local interaction parameter from your handler function. That's not persistent. If you want to save a list of things you either need a database hooked up to your bot, store in a local file that you read/write to/from, or you need to store it for the runtime of the bot.
Also, you shouldn't just freely define functions inside other functions like you did.
For example, you'd write this instead:
async execute(interaction) {
let inputuser = interaction.command.options.getUser('user');
let quote = interaction.command.options.getString('quote');
const newQuote = { userid: `${inputuser.id}`, quote: `${quote}`};
//Your code to save it to a database or other location
//Console log the quotes from wherever you stored them
console.log()
interaction.followUp(`Successfully saved new quote from ${inputuser}. Do /quote-list to get a random quote`)
}
I can't really help you write the database part because it's up to you and what database you want to use and how you want to implement it. However, just remember that you can't randomly append properties to objects in JS and expect them to stick around. The JS lifecycle doesn't allow for that. I'm not sure which other languages you know if any, but take some time to read some basic JS tutorials so you know how the language fundamentally works before diving into the rest of your discord bot.
You can't store the quotes in a guild.
You need to save them in either a json file or a database.
I recommend creating a database like MongoDB, follow the steps here:
https://www.mongodb.com/basics/create-database
https://www.mongodb.com/docs/atlas/tutorial/connect-to-your-cluster/

Access multiple gRPC Services over the same Connection (with a single Channel)

Note that this is not a duplicate of a similar question for go, since this uses grpc-node. For some reason, there seems to be differences in the API
I do the standard procedure of creating my APIPackageDefinitions and APIPackagePbjects, and create two separate clients from each one, individually.
let grpc = require('grpc')
let protoLoader = require('#grpc/proto-loader')
async function createGrcpConnection() {
const HOST = 'localhost'
const PORT = '50053'
const PORT2 = '50054'
let physicalProjectAPIPackageDefinition = await protoLoader.load(
'./physical_project_api.proto',protoLoaderOptions
)
let configAPIPackageDefinition = await protoLoader.load(
'./config_api.proto', protoLoaderOptions
)
let physicalProjectAPIPackageObject = grpc.loadPackageDefinition(
physicalProjectAPIPackageDefinition
).package.v1
let configAPIPackageObject = grpc.loadPackageDefinition(
configAPIPackageDefinition
).package.v1
let grpcClient1 = physicalProjectAPIPackageObject.PhysicalProjectAPI(
`${HOST}:${PORT}`,
grpc.credentials.createInsecure()
)
let grpcClient2 = configAPIPackageObject.ConfigAPI(
`${HOST}:${PORT2}`,
grpc.credentials.createInsecure()
)
return { grpcClient1, grpcClient2 }
}
I am looking for a way to create two clients that share the same connection. I think I am close to the solution by creating a new Channel and replacing the last two let statements with
let cc = new grpc.Channel(
`${HOST}:${PORT}`,
grpc.credentials.createInsecure()
)
let grpcClient1 = physicalProjectAPIPackageObject.PhysicalProjectAPI(cc)
let grpcClient2 = configAPIPackageObject.ConfigAPI(cc)
However, I received a TypeError: Channel's first argument (address) must be a string. I'm not sure how to incorporate the newly instantiated Channel to create new clients for each service. I couldn't find any useful methods on the docs. Any help would be appreciated.
P.S. At the moment I am trying to use two services, and create a client for each service, and have those two clients share a connection on the same channel. Is it possible to use two service, and create a single client for both services? Maybe I can use .proto package namespaces to my advantage here? My internet search fu failed me on this question.
There is an API to do this, but it is a bit more awkward than what you were trying. And you don't actually need to use it to get what you want. The grpc library internally pools connections to the same server, as long as those connections were created with identical parameters. So, the Client objects created in your first code block will actually use the same TCP connection.
However, as mentioned, there is a way to do this explicitly. The third argument to the Client constructor is an optional object with various additional options, including channelOverride. That accepts a Channel object like the one you constructed at the beginning of your second code block. You still have to pass valid values for the first two arguments, but they will actually be ignored and the third argument will be used instead. You can see more information about that constructor's arguments in the API documentation.

How to get parameter from previous context in Dialogflow

I am creating a chatbot for an IP firm. Its have an entity named service to have 4 type values. (Patent, Copyright, Trademark, design).
Client: What is a patent?
Bot: (Answer)
Client: how much cost to file it?
How I can know client asking about the patent from the previous context?
I can't use followup-intent in every intent.
Right now I'm using a global variable to get the slot agent.parameters.Service inside fulfillment.
let slot='patent';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
function service_typeHandler(agent){
var serv ='';
serv = agent.parameters.Service;
if(serv ===''){
serv=slot;
}
else{
slot=serv;
}
switch( serv ){
case 'patent':
First of all, you're correct on two fronts:
Don't use followup Intents. There are few cases where you actually want followup Intents. Most of the time you want to do this with other means.
Use Contexts. These are (part of) the "other means" in most cases.
In this case, it sounds like you'll have two Intents (and likely more, but this illustrates the point):
"ask.what" - which is the user saying things like "What is a patent?"
"ask.price" - which is the user saying things like "How much to file a patent?", but also "How much to file it?"
For the "ask.what" Intent, you would set an "Outgoing Context". This will automatically capture the parameters that are attached to the Intent. If you want to control it more yourself, you can create your own Context in your webhook and set parameters to whatever value you want. I suggest the latter, because it lets you use a parameter name that you don't use elsewhere. Let's assume that you're using a context named "savedInfo" and that you're setting the parameter to "savedService".
In your "ask.price" Intent, you'd do something similar to what you're doing now. Except that if the Service parameter is empty, get the parameters from the "savedInfo" context and, specifically, the savedService parameter.

clojurescript equivalent of javascript's module pattern

I am just starting to work with clojurescript on the node-js side. I'm using it for building command line tools that will run on node.
Now that I have my proof of concept already setup and doing more or less what I want is time to organize the code a bit better.
On JS when I need something similar to a configured http client I usually export a single function that accepts the basic parameters and returns an object with methods bound to that parameters (normally using the revealing module pattern). Something similar to creating a new instance on OOP.
Here is a small example of how I would do this on JS:
const request = require('request')
module.exports = (user, pass, baseUrl) => {
const client = request.defaults({baseUrl, auth: {user, pass}})
const getSomething = (name) => client.get('resources/' + name)
const createSomething = (name, options) => client.post('resources', {...})
return { getSomething, createSomething }
}
However on clojurescript I can't find a proper way of doing this. All defines are top level declarations computed at compile time, and making an structure such the one above would require to declare all my functions with a client parameter, then partially apply them and them use them on the body of the logic. This can be something like this:
(ns some-client [:require ["request" :as request]])
(defn get-something [client, name]
(.get client (str "resources/" name)))
(defn create-something [client, name, options]
(.post client (str "resources") {:name name :data: options}))
(defn make-client [usr, pass, baseUrl]
(let [client (.defaults request {:auth {:user usr :pass pass} :baseUrl baseUrl})]
{:get-something (partial get-something client)
:create-something (partial create-something client)}))
This may not look so bad, but as soon as you need to use it on another place where all the functions would require such client things start to get messy. You will need to accept the client on all the functions and if that other namespace is just a collection of functions that you will need to use on another place, you will be forced to follow the same schema of return a client creator, accept the client you depend on and make sure you pass it to every function that could need it. I can become as horrible as this:
(ns other-helper)
(defn trivial-stuff [client name bla]
(let [get-something (client :get-something)]
(get-something name))) ; make things like filtering and that
(defn more-trivial-stuff [client name bla]
(let [get-something (client :get-something)])
(get-something name)) ; make things like filtering and that
(defn non-trivial-stuff [client name bla]
(->>
(trivial-stuff client name bla)
(more-trivial-stuff client name)))
(defn more-non-trivial-stuff [client name bla]
(->>
(trivial-stuff client name bla)
(more-trivial-stuff client name)))
(defn compile-utils [client]
{:more-non-trivial (partial more-non-trivial-stuff client)
:non-trivial (partial non-trivial-stuff client)})
I can't make any def for the clients because I will need the credentials at runtime, so I have to accept all that stuff as parameters and bind the results, To me that looks like a lot of boilerplate and repetitive code that is not maintainable at all.
Does clojurians have a better approach ? Is any style guide on this regard ?
This is the second time I approach clojurescript and it looks very appealing at first, but as soon as you start building non trivial stuff it starts to become messy.
NOTE: for the shake of simplicity I didn't managed any js interop or used channels for async handling. I just declared js objects as normal cljs maps and took everything as it were synchronous, but including js interop and all that stuff will make things even worse.
EDIT (for clarification):
My question is not about if this is possible on clojure, I know it is possible since CLJS and JS share the required set of functionalities to make it possible. However, using the same patter on a totally different language not only feels wrong, but it also looks ugly due to the lisp syntax. The other alternatives I can think about also looks ugly, and involves a lot of repetition because it requires to get the client use it and pass it around on every single function, which leads to very repetitive and distracting code.
To make clear how would I use this on js it will be like this
const makeClient = require('./my-http')
const client = makeClient('my-user','my-pass','http://google.es')
client.getSomething('dude')
As you can see, I can create as many clients with different settings as I may need, I can even make some destructuring and pick only the methods I need since they do not depend on their bindings at all.
Note: I haven’t used Clojure/Script “in anger” yet, so this is a learning experience for me as well :) I haven't validated the code in a REPL unfortunately.
If I understand correctly, the JS module pattern is a function that returns a dictionary of two functions. At some point in your code you “create” this module, perhaps giving it a name, and you pass it around in your code like so:
let client = require("mymodule")("user", "pass", "http://example.com");
client.getSomething("foo")
You could do the same thing with ClojureScript:
(defn create-client [user pass base]
(let [get-something (fn [name] ...)
create-something (fn [name other] ...)]
{:get get-something :create create-something}))
(let [client (create-client "user" "pass" "http://example.com")]
((client :get) "foo"))
Now arguably this might look a bit more clunky but it is exactly the same code: close over a few variables, stick two functions in a map, get a function out of a map and call it.
The second part of your question looks like it's about global state – you have to carry around the client object everywhere, and it feels clunky. I don't think though that it looks any better in Javascript?
let client = require("mymodule")("user", "pass", "http://example.com");
let trivialStuff = (client, name, blah) => { client.getSomething(name); ... };
let moreTrivialStuff = (client, name, blah) => { client.getSomething(name); ... };
let nonTrivialStuff = (client, name, blah) => {
let result = trivialStuff(client, name, blah)
return moreTrivialStuff(client, name, result)
}
i.e. you are still passing client around. You could make it a module-level variable after initialisation, but then you lose the ability to make two different clients at runtime.
Are you saying that with the revealing module pattern you would also expose nonTrivialStuff, therefore you could do client.nonTrivialStuff()?
How about creating a namespace with all the functions that expect a client (which could be just a plain map containing the JS requests client), and just using them directly?
e.g.
(ns some-client [:require ["request" :as request]])
(defn make-client [usr pass base-url]
{:client (.defaults request {:auth {:user usr :pass pass} :baseUrl baseUrl})}) ;; you might want to use #js here, since you usually cannot pass CLJS maps to JS directly
(defn get-something [client name]
(.get (client :client) (str "resources/" name)))
(defn create-something [client name options]
(.post (client :client) (str "resources") {:name name :data options}))
Then in other namespaces:
(ns other-code [:require [some-client :as client]])
(def c (atom nil))
;; get user and pass from runtime, then call
(reset! c (client/make-client user pass base-url))
;; use like so
(client/get-something #c "name")
I opted into putting the JS client object into a CLJS map to allow for flexibility – in the future you may want to add more data into this map. Of course, the client code would not change since it it should treat it as an opaque value.

Writing JS code to mimic api design

We're planning on rebuilding our service at my workplace, creating a RESTful API and such and I happened to stumble on an interesting question: can I make my JS code in a way that it mimics my API design?
Here's an example to illustrate what I mean:
We have dogs, and you can access those dogs doing a GET /dogs, and get info on a specific one by GET /dogs/{id}.
My Javascript code would then be something like
var api = {
dogs : function(dogId) {
if ( dogId === undefined ) {
//request /dogs from server
} else {
//request /dogs/dogId from server
}
}
}
All if fine and dandy with that code, I just have to call api.dogs() or api.dogs(123) and I'll get the info I want.
Now, let's say those dogs have a list of diseases (or whatever, really) which you can fetch via GET /dogs/{id}/disases. Is there a way to modify my Javascript so that the previous calls will remain the same - api.dogs() returns all dogs and api.dogs(123) returns dog 123's info - while allowing me to do something like api.dogs(123).diseases() to list dog 123's diseases?
The simplest way I thought of doing it is by having my methods actually build queries instead of retrieving the data and a get or run method to actually run those queries and fetch the data.
The only way I can think of building something like this is if I could somehow, when executing a function, if some other function is chained to the object, but I don't know if that's possible.
What are your thoughts on this?
I cannot give you a concrete implementation, but a few hints how you could accomplish what you want. It would be interesting to know, what kind of Server and framework you are using.
Generate (Write yourself or autogenerate from code) a WADL describing your Service and then try do generate the Code for example with XSLT
In my REST projects I use swagger, that analyzes some common Java REST Implementation and generates JSON descriptions, that you could use as a base for Your JavaScript API
It can be easy for simple REST Apis but gets complicated as the API divides into complex hierarchies or has a tree structure. Then everything will depend on an exact documentation of your service.
Assuming that your JS application knows of the services provided by your REST API i.e send a JSON or XML file describing the services, you could do the following:
var API = (function(){
// private members, here you hide the API's functionality from the outside.
var sendRequest = function (url){ return {} }; // send GET request
return {
// public members, here you place methods that will be exposed to the public.
var getDog = function (id, criteria) {
// check that criteria isn't an invalid request. Remember the JSON file?
// Generate url
response = sendRequest(url);
return response;
};
};
}());
var diseases = API.getDog("123", "diseases");
var breed = API.getDog("123", "breed");
The code above isn't 100% correct since you still have to deal with AJAX call but it is more or less what you what.
I hope this helps!

Categories