How to access native functionality from an included Java dependency - javascript

I'm looking to create a Nativescript wrapper for a Java library so I can utilize functionalities of it for a Nativescript app. There does not seem to be too many articles that go into this in detail, and there does not seem to be a clear way to do this within the Nativescript app itself which is why I am now making this a plugin wrapper.
The specific Java library I am working to include is Libsignal-protocol-java. I've gone ahead and cloned the Nativescript Plugin Seed and added this Java library as a dependency:
src/platforms/android/include.gradle
android {
}
dependencies {
compile 'org.whispersystems:signal-protocol-android:2.3.0+'
}
I then found the particular package that contains the method I am trying ro access within the Java source: KeyHelper.generateRegistrationId(); source. One article mentioned this is required as you'll have to specify the package when instantiating the class and method.
I then setup my libsignal-protocol.common.ts as follows to attempt and use the native method:
src/libsignal-protocol.common.ts
import { Observable } from 'tns-core-modules/data/observable';
export class Common extends Observable {
constructor() {
// does not work
let test1 = new org.whispersystems.libsignal.util.KeyHelper.generateRegistrationId();
// does not work
let test2 = org.whispersystems.libsignal.util.KeyHelper.generateRegistrationId();
console.log(test1);
console.log(test2);
}
}
To my dismay, the logger returned this error:
System.err: Error: java.lang.Exception: Failed resolving method generateRegistrationId on class org.whispersystems.libsignal.util.KeyHelper
I am not sure where else to go here now, I wanted to go this route as it seemed safer/cleaner to create a wrapper for this awesome Java library than trying to browserify their javascript library as it requires certain features not available within Nativescript.
Any help or suggestions would be appreciated! For sanity, I will include some articles I have found on this matter that has helped lead me to where I am now.
Sources
Using libsodium in Android/Nativescript
How to use JAR file in Nativescript

As you see in the source code generateRegistrationId method expects one boolean argument.
public static int generateRegistrationId(boolean extendedRange) {
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
if (extendedRange) return secureRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
else return secureRandom.nextInt(16380) + 1;
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
So you must pass a boolean to the method,
let test2 = org.whispersystems.libsignal.util.KeyHelper.generateRegistrationId(false);

Related

process.env.FOO transformed into {}.FOO and throwing error "expected expression, got "."

I wrote a TypeScript module that interacts with a specific RESTful API. The module never refers to process.env anywhere (target is browser, possibly Node down the line as well).
I use Rollup to transpile to a single JS file. From there, going into Node and require('./build/index') is successful, and I can even run the functions and get expected results. So Rollup itself appears to work.
But the file contains many references to things like process.env.DEBUG. (I suspect Rollup is doing something to create loggers that can work in both Node and browser.)
Now I import this into a Gatsby UI project that will need to connect to the API using this module:
import { api } from 'my-api'
api.someApiCall()
Problem is that when Gatsby compiles all this (using Webpack?) into commons.js (some big JS file with a lot of combined code from different libraries, including my API module), it appears to transform the module's process.env.DEBUG (for example) into {}.DEBUG. Then the browser complains that "expected expression, got '.'". Which makes sense. You cannot access {}.DEBUG. It would have to be ({}).DEBUG or const o = {}; o.DEBUG.
Now I have been off in the world of other languages for a while. Rollup is fairly new to me. Gatsby is very new to me. What is the way forward? Do I tell Rollup via a config to replace process.env with ({}) so that way ? But then that precludes the library from ever being used in Node.js and taking advantage of process.env.
Do I need to change something about Gatsby to have it replace process.env with ({})?
Edit For example, here is some output showing up in my browserin commons.js:
function save(namespaces) {
if (null == namespaces) {
// If you set a process.env field to null or undefined, it gets cast to the
// string 'null' or 'undefined'. Just delete instead.
delete {}.DEBUG;
} else {
{}.DEBUG = namespaces;
}
}
/**
* Load `namespaces`.
*
* #return {String} returns the previously persisted debug modes
* #api private
*/
function load() {
return {}.DEBUG;
}
In my module, those are process.env.DEBUG.
Edit 2 I've also tried putting a gatsby-node.js containing this:
exports.onCreateWebpackConfig = ({
plugins,
actions,
}) => {
const { setWebpackConfig } = actions;
setWebpackConfig({
plugins: [
plugins.define({
'process.env': "({})",
'{}.DEBUG': '({}).DEBUG',
})
]
})
}
No effect.

Is it possible to use Node.JS based module from Java?

I was working on a React Native Native Module for Android. And it is written in Java (as what I researched from official docs and the internet). The problem is, I need to use a Node.JS based module to implement the functions that I want. Is there any possibility to use Node.JS module in Java?
The Node.JS module currently using a few Node native libraries such as fs and path. The code is 100% written using Node.JS.
Or is there any other way to create a React Native module without the use of Java?
The ultimate goal is to use this Node.JS based module to React Native App (without create a bridge between Node and React Native).
As I understand your question, your module doesn't have to communicate with native side. If it's that what you need, it will so easy to achieve. I'll make a simple example:
yourModule.js
export function a() {
// do sth
}
export function b() {
// do sth
}
export function c() {
// do sth
}
yourComponent.js
There is 2 ways to use your module:
1.
import { a, b } from '/path/yourModule'; // if you want to import some of the functions
class yourComponent {
function test() {
a(); // call function a from module
}
}
// Remember to check function's name if it's duplicated with other modules
2.
import * as module1 from '/path/yourModule';
class yourComponent {
function test() {
module1.a(); // call function a from module
}
}
// In this case, you won't have to worry about duplicated function's name, but you still
// have to check duplicated of the name of modules you have imported. For this example,
// the name module1 has been used.
P/s: you might get some error when using export/import incorrectly. So please investigate more about React Native export/import.

Document function that returns object property by parameter

I'm making an Api repository for my Vue.js application, following this article.
Thing is, I like to document my functions so I have better code completion on VSCode. I typically use jsDoc for this.
I'm stuck here:
import DiarioEscolarRepository from './diarioEscolarRepository';
import PeriodoAvaliativoRepository from './periodoAvaliativoRepository';
import AtividadeAvaliativaRepository from './atividadeAvaliativaRepository';
import CorteEtarioRepository from './corteEtarioRepository';
const repositories = {
diarioEscolar: DiarioEscolarRepository,
periodoAvaliativo: PeriodoAvaliativoRepository,
atividadeAvaliativa: AtividadeAvaliativaRepository,
corteEtario: CorteEtarioRepository,
};
export default const RepositoryFactory = {
get(name){
return repositories[name];
}
};
I need to make it so the editor understands that the get function is a simple acessor to the repositories object.
I tried using #typedef and #type, but none of them worked properly.
I tried something like #returns {repositories.name}, but is also does not work.
Is there a way to document this?
I also thought about using a typescript definition file but I never did it, so I don't know where to begin.

Building Flux/React application without NodeJs EventEmitter

Hi I'm trying to build a Flux/React application with a go-lang back-end. I have been following a tutorial I found here. But I have a problem when building the store. In the tutorial something like this is used to create a base for the store.
var ProductStore = _.extend({}, EventEmitter.prototype, {...});
The problem I have is I do not have access to the EventEmitter library which I understand is a Nodejs lib? Is there an alternative I can use?
You can use NodeJS libraries in the browser! Take a look at browserify.
First some code:
// index.js
var EventEmitter = require("events").EventEmitter;
var ProductStore = function() {};
ProductStore.prototype = new EventEmitter;
Then you run browserify on it:
browserify index.js > bundle.js
Also worth a look is WebPack which does the same thing. (but has some additional features)
Well if you are using the flux implementation given by Facebook (https://github.com/facebook/flux), you can actually extends their FluxStore class which comes with a build in eventEmitter.
The only thing if you want to do that is you must use es6 classes (and use babel to transpile to es5).
The good thing about it is that you don't have to implement the addListener removeListener and emitChange methods, and that's very DRY :)
With this solution, your stores will end up looking like that :
var FluxStore = require("flux/utils").Store,
thing;
class ThingStore extends FluxStore {
getThing() {
return thing;
}
__onDispatch(payload) {
//your code
}
}

How to properly use es6 classes in different files by importing them in Meteor?

I have recently discovered Meteor and I am struggling with using ES6 classes and imports in a new Meteor project. What I want to do is to have a complex structure of classes, which methods get called from Meteor events/methods/helpers. I've added Babel.js to the project by writing a command $ meteor add grigio:babel and it works properly.
Example of what I am trying to achieve:
in server/models/article.js:
class Article {
static all() {
//returns all articles from db
}
}
in server/methods/articles.js:
Meteor.methods({
allArticles: {
Article.all();
}
})
Having just that raises ReferenceError: Article is not defined in a methods file, which is adequate. So I have got three options: write all classes in one file, append all classes to a global object or use a good module system like Browserify. Obviously, third option is better.
But how do I use that? Babel converts export, import into Browserify by default and Meteor raises a require is not defined error on page refresh. After googling the problem I didn't find a clear solution on how to add Browserify to Meteor. Should I add a npm packages support to Meteor, add a npm package of browserify and add it manually to Meteor on every page where I import/export anything? Or should I use a completely different approach? How is this task usually handled in Meteor? Thank you!
I was reading about this earlier and found this issue on github that may help.
Essentially just assign the class to a variable that is exposed to both the client and server (lib/both/etc depends on your file structure). Like so:
Article = class Article {...}
Seems to be the best solution at the moment.
The way I do this is to collect objects together into various namespaces, for example:
// Global
Collections = {};
class Article {
static all() {
//returns all articles from db
}
}
_.extend(Collections, { Article });
Then to avoid having to use Collections.Article everywhere I can use the following in the file I need to access Article in:
// Make `Article` available
let { Article } = Collections;
I am using Meteor 1.4.1.1 and the error remains, when reproducing your approach. However, there are some new ways to use es6 classes now:
1. Export your class as a constant (e.g. for use as a singleton object):
class MyModuleInternalClassName {
//... class internals
}
export const PublicClassName = new MyModuleInternalClassName();
You can import this one via
import {PublicClassName} from 'path/to/PublicClassFileName.js';
2. Export your class directly as the module's default
export default class PublicClassName {
//... class internals
}
and then import it (as with the above one) as the following
import {PublicClassName} from from 'path/to/PublicClassFileName.js';
let myInstance = new PublicClassName();
+++++++++++++++++++++++++++++++++
Regarding the question of OP and the error, you can try something like this:
Article.js
class InternalArticle {
constructor(){
//setup class
}
all() {
//returns all articles from db
}
register(article){
//add article to db
}
}
export const Article = new InternalArticle();
Import and use the Singleton
import {Article} from 'path/to/Article.js';
//either register some article
Article.register(someArticle);
//or get all your articles
const allArticles = Article.all();

Categories