Reason React and Graphql handling ENUM values - graphql

Just started to learn reason react and struggle with a graphql setup trying to read an ENUM value.
setup
reason react
apollo graphql
graphql_ppx
github graphql endpoint
i am fetching the latest pull request data over the github api and reading the status property which is an enum and defined in the gql docs as:
OPEN
CLOSED
MERGED
checking the network tab, i see the states are received as strings. within the application when I log the field i get a bunch of integers reflecting the values. can smb explain me, how i can "print" the data as string to my view and why they are translated to integers? is there somewhere a type generated which i could use for a variant switch?
let stateEnum = data->map(node => node##state);
Js.log(stateEnum) // possible values: 880069578, 982149804 or -1059826260
// somehow switch these values here?! :)
// current type of `stateEnum` is option('a)
thanks a lot in advance and have a nice day!

GraphQL Enums are represented as Reason polymorphic variants. Under the hood, in runtime, they are just integers. If you want to display them to the user you have two options:
1. Map them to string by hand using a switch
let status =
switch(node#status) {
| `OPEN => “Open”
// other cases
}
You can use BuckleScript functionality do generate jsConverters:
[#bs.deriving jsConverter]
type status = [ |`OPEN | `CLOSED /* other cases */]
this will generate two functions for you: statusToJs and statusFromJs. They help you convert variant to and from string.
Here is BuckleScript documentation about it: https://bucklescript.github.io/docs/en/generate-converters-accessors#convert-between-js-string-enum-and-bs-polymorphic-variant

As #Herku mentioned in his comment, the key was just to do this:
// asume that your enum is on a gqp property called `state`
// and we use the built in lib `Belt.Option` and the fn `getWithDefault`
// this way we are sure, that `stateEnum` is defined with one of the valid enum values
let stateEnum = data->map(node => node##state)->getWithDefault(`OPEN);
// next we switch the polymorphic variant
let state = switch(stateEnum) {
| `OPEN => "open"
| `CLOSED => "close"
| `MERGED` => "merged"
}
// str = let str = ReasonReact.string;
str(state);

Related

How to represent method calls ReScript 9.1.2

ReScript 9.1.2 made the original #meth semantics inaccessible they said to use #send external instead to represent method calls
My questions are:
can #send external be inside a type?
and is this a correct way to use it knowing that it generates the same javascript code?
Using #meth:
#meth
"createElement": string => Web_node.t,
let createElement = typ => document["createElement"](typ
Using #send external:
#send external
createElement: (t,string) => Web_node.t="createElement"
let createElement = typ => createElement(document, typ)
I don't know what you mean by "inside a type", but yes, that is how you represent a method call. You can verify this by looking at the generated JavaScript. An easy way to do this is by creating an example in the rescript playground, which will show that it generates this:
function createElement(typ) {
return document.createElement(typ);
}
Another handy resource is the rescript bindings cookbook.

How to distinguish not provided and empty array in grpc service?

See https://github.com/grpc/grpc-node/issues/1202.
Usually in CRUD operations, the value not provided means do not change that field, and the empty array [] means to clear all items inside that field.
But if you tries to implement CRUD operations and provide them as services via grpc, then the above scenario is hard to implement.
service CRUD {
rpc updateTable(updateRequest) returns updateResponse {}
}
message updateRequest {
repeated string a = 1;
string b = 2;
}
message updateResponse {
boolean success = 1;
}
If you load the package with default options, then the client can't delete items of a by
client.CRUD.updateTable({a: []})
because the argument {a: []} becomes {} when it arrives the server side.
If you load the package with options {arrays: true}, then the field a will be cleared unintentionally while client side only tries to update other fields:
client.CRUD.updateTable({b: 'updated value'})
because the argument {b: 'updated value'} becomes {a: [], b: 'updated value'} when it arrives the server side.
Can anyone share some better ideas regards how to handle these 2 scenarios with grpc-node and proto3?
The protobuf encoding doesn't distinguish between these two cases. Since protobuf is language-agnostic, it doesn't understand the conceptual nuance of "undefined" versus "[]" of Javascript.
You would need to pass additional information inside the proto message in order to distinguish between the two cases.
I would highly suggest reading the design documentations here: https://developers.google.com/protocol-buffers

access golang struct field with variable

For reference: example here
I am trying to access a struct field using a variable key, to explain in PHP you can do the below.
$arr = ["test" => "foo"];
$key = "test";
$result = $arr[$key];
Or in Javascript you can do the below
const obj = {"test": "foo"}
const key = "test"
const result = obj[key]
Is this possible with go structs? I have searched for this functionality, but the answers always seem to point to the reflect package and running a for loop over the struct fields.
My code (linked above) gets the compile error of invalid operation: p[key] (type Post does not support indexing) which makes sense, but I can't find a way around this.
One of the main points when using structs is that the way how to access the fields is known at compile time.Then the produced code uses fixed indexes added to a base address of the struct.
For any kind of dynamism here you just need to use map[string]string or similar.

creating lettable rxjs "string.split" operator

I am attempting to do some string manipulation in rjxs, and while I can accomplish it with the built in behaviors on the string class and the array class in Javascript, I'm wanting to use this as an exercise to learn even more about rxjs and understand a fluent code-flow better.
To that end, it's imperative to me that I discover a way to do it that can fit in a fluent solution, instead of a series of variable assignments like I see in most rxjs examples.
Essentially, here's the situation; I've got a string of text;
const example = `
key || value
key || value
key || value
value
value
value
key || key[key1] = value | key[key2] = value
key || value
`;
The first thing that I need to do is use string.split('\n') to create an array of strings, so that I can through each line and perform further operation.
example.string.split('\n') does give the desired results, but trying to send this into rxjs begins to get rather mixed yield. With the pipe method, I know that I send the results into rxjs as an Observable, but I'm having a really troubling time grasping how to truly treat it from there without excessive nesting into the map operator.
For example, if I do ...
of(example.string.split('\n')).pipe(
map(results => results.toString().split('||')),
map(results => ... ),
...
).subscribe();
I can start to get a semblance of what I'm looking for, but what I'd really like to do is ...
of(example).pipe(
split('\n'),
split('||'),
concatMap(results => ...)
).subscribe();
Reading the documentation on lettable operators, seen here, it looks like this should be a pretty easy thing to create. In theory, it should look like this in my mind;
const split = (separator: string) => <T>(source: Observable<T>) =>
new Observable(observer => {
source.subscribe({
next(x) { observer.next(x.toString().split(separator)); },
error(err) { observer.error(err); },
complete() { observer.complete(); }
})
});
So that should make the whole code obvious enough;
of(example).pipe(
split('\n')
).subscribe(result => console.log(`[n]::${result}`));
But this doesn't give me what I really expect. I expected to get an array of the lines, but if I output it, I get ...
[n]::, key || value, key || value, key || value, ,
value, value, , value, key || key[key1] = value |
key[key2] = value, key || value,
I'm really unclear what I'm doing wrong, here. Since it's hard to demonstrate rxjs in most of the code playgrounds like plunkr or jsfiddle, at least to my knowledge, I've prepared a playground environment to demonstrate my work on stackblitz, if it helps.
You'll find all of the pertinent code in the playground/index.ts file. I've done the best I can to abstract away the need to have any knowledge of angular, as I've painstakingly earmarked the sections that should be left alone to make it continue showing output on the right side. If you do not know angular, but can help with rxjs, you should be able to work without ever disturbing that setup.
STACKBLITZ PLAYGROUND
Your code is working fine, just the es6 template string ${} flattened your array into a string. If you console.dir or log the result, you will see a correct array retrieved.

What's the difference between map and pluck in RxJS?

I am trying to understand the difference between map and pluck transformational operators in RxJS.
Can anyone help me with this?
The docs say
Pluck : Like map, but meant only for picking one of the nested
properties of every emitted object.
Therefore, let's say you have
[{ name: 'Joe', age: 30, job: { title: 'Developer', language: 'JavaScript' },
{ name: 'Sarah', age: 35 }]
and you want a list of all job titles.
Using map would be kind of a pain (because of the nullability of job), but with 'pluck' you can write pluck('job', 'title') and it will traverse the tree looking for job.title - and won't fail if job is null.
Example taken from : https://www.learnrxjs.io/operators/transformation/pluck.html
https://jsfiddle.net/btroncone/n592m597/
As #mgm87 said, you can perform an operation with map.
On the opposite, pluck is just taking a value.
For example, with map you could do something like that:
this.http.get('...some api url to get a user...')
.map(response => response.json())
.map(user => user.age > 18 ? 'major': 'minor')
.do(isMajorOrMinor => console.log(isMajorOrMinor))
So you can manipulate your data down the chain even conditionally.
BUT, for me one of the big differences is that map is typed.
Which means if you have some data let say:
interface IUser {
name: string;
age: number;
dogs: IDog[];
}
And you receive at some point a user, from which you want to get his dogs:
user$
.map(user => user.dogs)
.do(dogs => ...) // here, you do NOT need to precise (dogs: IDog[]) because Typescript will make a type inference
And that's why I'm always using map even to just "pluck" some data.
Stop using pluck!
Pluck is now planned to be removed in RxJS v8.
Do you know what is the reason?
Because after the addition of the optional chaining operator in JS, it's essentially, just a weak version of Map.
So what's the difference between the two?
Both are used to "transform" the data that is going to be emitted.
Map can be used to... map an observable emission (like we do in JS with Array.prototype.map), while Pluck is used to select/pick a property to emit (without having to emit properties that we don't care for, hence improving the performance).
But even before the optional chaining operator, you could just map the properties instead of plucking them. The result & performance were/are about the same.
pluck('prop')
is just a shorthand for:
map(x => x.prop)
Well, then what was the reason behind the implementation of Pluck?
It was basically implemented to achieve path traversal safety, meaning you could try to pluck a nested property without getting the error (that Map would throw) if the property is not defined:
pluck('foo', 'bar', 'baz'); // no error if foo is not defined
map(x => x.foo.bar.baz) // error if foo is not defined
With optional chaining, this advantage doesn't exists anymore, since we can just do this:
map(x => x?.foo?.bar?.baz)
This is the main reason why the Pluck operator is going to be deprecated and removed in the future.
Another important reason is TS typing for pluck is quite complex and not as robust as the map operator.
Got that info in GitHub:
The commit of Pluck deprecation is almost one year old but I still don't see any warning of future deprecation in the docs, hence I am posting here since I think it's a good thing to know. I already stopped plucking for this reason.
Map can perform an operation on each emitted value.
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-map
https://www.learnrxjs.io/operators/transformation/map.html
// value from observable = 10
map(x => 10*x)
// value from map = 100
Pluck simply picks one of the nested properties of each emitted value.
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-pluck
https://www.learnrxjs.io/operators/transformation/pluck.html
// value from observable = {p = 10, w = 100}
pluck('p')
// value from pluck = 10
They are very similar, but as I understand it, map works with an array whereas pluck takes the values from an object.
This is the place to go for specifics.

Resources