Implement gRPC in an iOS React Native app - node.js

As described in this issue, we can't implement a gRPC client using the Node implementation because "RN is not pure Node".
So I started working on an Objective-C implementation using the Native Modules.
[service postWithRequest:request handler:^(RequestConfirmation * _Nullable response, NSError * _Nullable error) {
if (response) {
// This prints correctly in my JS console
RCTLogInfo(#"%#", response.message);
// This generates an error, see below
resolve(response);
// This works
NSDictionary *formattedResponse = #{
#"id": response.id_p,
#"message": response.message
};
resolve(formattedResponse);
} else {
reject(#"error", #"An error occurred while saving", error);
}
}];
Error :
RCTJSONStringify() encountered the following error: Invalid type in JSON write (RequestConfirmation)
As you can see the problem is with the resolve method. I suppose React does not find any way to convert my proto message to JSON.
How can I keep the response as is and pass it to the resolve method ?
Then I can decode it in my JS code.
Thanks.
EDIT 1 :
RequestConfirmation is defined in my proto file like this :
message RequestConfirmation {
string id = 1;
string message = 2;
}
And then it is generated in Objective-C :
#interface RequestConfirmation : GPBMessage
#property(nonatomic, readwrite, copy, null_resettable) NSString *id_p;
#property(nonatomic, readwrite, copy, null_resettable) NSString *message;
#end

Maybe the following is a potential solution for this.
Improbable Engineering have coded:
grpc-web - Typescript/Javascript, browser or NodeJS!
Aside from the unfortunate naming, this appears not to be a mere fork of the official, C++-using, grpc-web project).
Quoting the Improbable project's own grpc-web-client page:
This library is intended for both JavaScript and TypeScript usage from either a browser or Node.js
The possible benefits of Improbable's version seem to be:
It doesn't appear to use native code (i.e. no C/C++/Java)
It can generate Typescript (therefore JavaScript) for Node.JS
So, maybe, we could get GRPC-on-RN working, when point No. 2 is coupled with a NodeJS-on-RN project such as rn-nodeify.
Please provide feedback, if you have any success with this.

At the time of writing, Improbable Engineering's gRP-Web can't be used with React Native.
Instead you must use React Native Native Modules and build native modules in Swift or Objective-C. Since React Native doesn't talk to Swift directly, you must create an Objective-C bridge if you choose to use Swift.
You will:
implement a gRPC client in the native language of your device,
export it using React Native's Native module framework
access the native module and its gRPC methods through React Native
Call those exported methods in React your Native code
The basic structure of this relationship is:
# Swift project
Reat Native <-> ObjC Bridge <-> Swift <-> gRPC
# Objective-C project
Reat Native <-> ObjC <-> gRPC
It's a pretty lengthy explanation of how to integrate these components. I've written a tutorial for Building a gPRC Client in React Native on iOS/Swift. I hope people find that useful.

Related

Having Issues using Esri ArcGIS API for JavaScript in Lightning Web Component (require is not defined at eval)

I'm trying to implement Esri ArcGIS JS in Lightning Web Component. While using ArcGIS JS, the sample code uses require function to load modules. In order to do that I'm trying to use require.js. I downloaded it from here (Require.js). And then uploaded to my sandbox as static resource. I'm trying to use that static resource in my Lightning Web Component. I also added the script tag for the ArcGIS Javascript API in my Experience Cloud site's header as
<script src="https://js.arcgis.com/4.24"></script>
Lightning Web Component:
import { LightningElement, track } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import requireJS from '#salesforce/resourceUrl/requireJS';
export default class TestMap extends LightningElement {
renderedCallback() {
loadScript(this, requireJS).then(() => {
console.log('requireJS loaded');
require([
"esri/geometry/Extent"
], (
Extent
) => {
var initExtent = new Extent({
xmin: -15884312,
ymin: 1634835,
xmax: -6278767,
ymax: 7505198,
spatialReference: 102100
});
});
}).catch(exception => {
console.log(exception);
});
}
}
My problem right now, eventhough I can see in the Network tab that the require.js is loaded from static resource, require function cannot be found.
Exception message catched
I'm not sure where is the issue since this is how I loaded my all javascript files before.
I was expecting to see the the require function is working after the require.js script loaded from Static Resource.
This one is a bit tricky, I will try to guide you as much as I can.
First, don't put the script tag in your website header. This is a last chance solution, we'll keep it if nothing else work.
Second, requireJS is not compatible with LWC (or Locker Service to be precise). So you can forget it. loadScript is in someways similar.
Now the solution, usually I download the whole from a CDN and host it as a static resource. Then you can load it via loadScript and use it as per the documentation.
In case the library is really small, it could be created as a LWC and then be imported but usually libraries are too heavy regarding Salesforce limit.
Looking at the library, it seems that they do not provide any compiled full version (which is probably huge). In this case I would recommend to make a custom build locally containing only the necessary pieces of code and then uploading as a static resource. Unfortunately I can't help on this part as I still didn't do it myself yet.
Feel free to comment and I will improve my answer is it's unclear.

Nuxt3 - how to use vite-plugin-wasm

I'm building a Nuxt3 application where I need to import and use a 3rd party node package which internally is using webassembly.
In my case, the package I need is https://github.com/higumachan/lindera-js
Where do I import the package?
In one of my components, right at the beginning of the <script> tag.
And afterwards I'm using it in one of the methods.
(Note: I removed unnecessary code below)
<template>
...
</template>
<script>
import * as lindera from "lindera-js";
...
methods: {
doTranspile() {
const tokenized= lindera.tokenize(this.input);
console.log(tokenized);
},
},
...
</script>
What is the Problem?
After dev server compiles everything and I reload the page in the browser, I get the following error:
[vite] Internal server error: "ESM integration proposal for Wasm" is not supported currently.
Use vite-plugin-wasm or other community plugins to handle this.
Alternatively, you can use .wasm?init or .wasm?url.
See https://vitejs.dev/guide/features.html#webassembly for more details.
The Question
How can I use the package without problems in Nuxt3? Do I have to use vite-plugin-wasm and if so, how and where to use/import it?
Or is there any other way to use a package which is using webassembly?
I found some similar questions on SO, but not sure if they can be used like this in Nuxt3 as I'm fairly new to Nuxt in general.
How to use embedded Webassembly in Vite?
How to include an WASM npm module in svelte with vite?

How to use an angular module that does not support Universal with an angular/cli app using SSR

Hey everyone I have been building an Angular app that is using Universal with SSR for a while not and every so often I would include a module that would cause the server to fail silently and never knew why, last night I figured out it was because the module I tried to include (ngx-editor) does not support Universal.
Is there a way for me to include a module such as ngx-editor that does not support Universal in my application? Or do I have to find one that supports Universal?
Thanks a lot in advance.
You could try not calling this module's components depending on the platform, e.g. by checking the platform dynamically in your code ( https://angular.io/api/common/isPlatformBrowser)
import {isPlatformBrowser} from "#angular/common";
//...
constructor(#Inject(PLATFORM_ID) private platformId: Object)
{
if(isPlatformBrowser(this.platformId))
{
//call module's methods/components...
}
else { /*server side*/ }
}
You may also need to modify your server module (app.server.module.ts) to not include modules that do not support angular-universal

what is the proper way to create a swagger web service in TypeScript

I am part of a project written in TypeScipt and I am trying to add TypeScript Web Server which will be compatible with Swagger.
What is the most basic strategy to implement it, considering easy maintainability.
For Typescript I have notice that exists 'Typson' library for generating a JSON Model from TypeScript Interface.
For Swagger, I have tried using 'swagger-node-restify' library, since it supports adding JSON models to swagger.
However, I encounter some problems:
Typson doesn't support typeScript syntax of Import -
(import {Server} from "restify")
I tried to implement the 'swagger-node-restify' example (Pet Example), however the RESPONSE of the localhost:8080/api-docs.json GET Request is missing all the SPEC data of the API.
{"apiVersion":"0.1","swaggerVersion":"1.1","basePath":"http://localhost:8080","apis":[{"path":"/api-docs.{format}/pet","description":"none"}]}
I suggest to describe a Swagger compliant API using yaml or json and to generate the server from that.
swagger-server can build APIs on top of express in real time (no source code generation).
There are JavaScript code generators :
Call the swagger-codegen client with -l nodejs-server
swagger-node is a great alternative but seems hard to integrate with TypeScript
Yes, you can easily generate Swagger and OpenAPI documents from your TypeScript types by using tsoa. The readme contains all of the setup information that you would need to start using it. It's compatible with express, hapi, koa, and more (via the ability to add your own template for your preferred server type):
https://github.com/lukeautry/tsoa
The advantages that tsoa has over other libraries is:
it both generates the swagger/OpenAPI document and it also validates the types at runtime
(Full Transparency: I am one of the maintainers of tsoa. But I was first a consumer of tsoa and I find it to be a great product... that's why I asked to help maintain it! :) )

nwjs reactjs, confused about my context. Document is undefined

In my nwjs application i am using React to build my UI. Currently, React is being loaded via a <script> tag in the main file, index.html. index.html has another <script> tag which loads main.js containing code which defines and renders my React components as well as requiring (require()) a few Node modules such as "fs" and "McFly".
This all seems to be working, however when i try using another node module (react-inlinesvg) i get an error, "document is undefined".
Having looked online for help, i have come to the conclusion that React now believes that it is being run on the server? Which is odd, as before i started using the react-inlinesvg module it was happily rendering components using React.render (clientside rendering).
If you need any more context or information then please ask.
It could be that you are rendering on the server side, or also that you are rendering both sides. In the second case you could simple nest the line that is causing you error with:
if (process.env.BROWSER) {
the line causing the error
}
If the error disappears, it means that you are on the server side also!
I hope this helps...
Basically if you code is universal (or isomorphic, if you want...) with this check you can execute the code only on client side, you want to do this to use a particular style-sheet for example:
if (process.env.BROWSER) {
require("../style/main.scss");
}
Naturally if you want to do stuff server-side you can check
if (!process.env.BROWSER) {
}
if any one face this he can solve it in 2 ways:
Solution 1: if you are using nw.js 15 or above try to enable mix context mode:
in your package.json add this flag:
"chromium-args": "--mixed-context"
Solution 2: expose document to the global object using this hack:
global.document = window.document;

Resources