Load “Vanilla” Javascript Libraries into Node.js = 'Unexpected token export' - javascript

Building on related issue: Load "Vanilla" Javascript Libraries into Node.js
I'm trying to load a 'Vanilla' Javascript library 'rsa.js' into NodeJS, using the method described by Chris W. in the question above. In essence I've created a custom node_modules directory like this:
./node_modules/rsa/rsa-lib/rsa.js
./node_modules/rsa/rsa-lib/README
./node_modules/rsa/index.js
Only problem is, compiling the module fails on the last line of rsa.js:
undefined:836
export default rsa;
SyntaxError: Unexpected token export
rsa.js
var rsa = {};
(function(rsa) {
...
})(rsa);
console.log("rsa",rsa);
export default rsa;
index.js
var fs = require('fs');
// Read and eval library
filedata = fs.readFileSync('./node_modules/rsa/rsa-lib/rsa.js','utf8');
eval(filedata);
/* The rsa.js file defines a class 'rsa' which is all we want to export */
exports.rsa = rsa
Any suggestions how to fix this problem?

The error 'Unexpected token export' is caused because the library is using
export default thingToExport;
instead of
module.exports = thingToExport
This is an ES6 feature not supported by Node (yet), so when Node tries to run the code, it throws an error.
How to solve: try modifying the last line of the library so it says module.exports = rsa;.
I should add, though, that eval is not a good way to load a library into your own code. That is what require is for. If you have installed this library with npm i and it is in your node_modules, you should be able to load it into your code with var rsa = require('rsa');.
Again though, if you're not transpiling the code, it may have problems with export default, so you will probably want to change that to module.exports either way.

Related

How can I ensure browser compatibility for the webcrypto API in Typescript?

So, what I'm trying to achieve is to use the Webcrypto API in Typescript and compile it to Javascript code that runs in the browser.
In the Browser, accessing the Webcrypto API is simple. Just window.crypto or crypto for short.
In node.js, you have to import it from the built-in "crypto" library first:
import { webcrypto as crypto } from "crypto"
Since I want to run it in the browser, I don't have to and also can not import it.
And here is the problem: For Typescript, I have to import the node library to get the necessary types. If I don't, this is the error:
src/main.ts:15:43 - error TS2503: Cannot find namespace 'crypto'.
So, for Typescript to compile, I have to import "crypto", but for the browser to run it I must not.
Possible work-arounds I can think of are:
tell Typescript that "crypto" (window.crypto) exists and is equivalent to crypto.webcrypto from the node library
tell Typescript to not include the line with the import in the output Javascript file
tell the browser to ignore that import
None of those I could find in the internet.
What I also tried is to use a dynamic import so I can conditionally import it, something like:
let _crypto: any = window?.crypto
if (!_crypto) {
_crypto = await import("crypto")
}
const crypto: any = _crypto
In theory, this should make the browser just ignore that "crypto" import since window.crypto exists.
But Typescript doesn't import the necessary types for dynamic imports for some reason.
In case this is needed, this is part of my code:
export function sign(privkey: crypto.CryptoKey, data: any) {
data = YSON.stringify(data)
data = new TextEncoder().encode(data).buffer
return crypto.subtle.sign({name: "ECDSA", hash: {name: "SHA-256"}}, privkey, data)
}
This function takes some data, stringifies it, and signs it using a private key.
The Y in YSON is intended.
The error is in the first line of that code snippet, I'm using the crypto.CryptoKey type.

how to correctly use Google Protobuf, when using imports in Javascript

Lets suppose there are two .proto files, file hello.proto and file core.proto.
File core.proto is imported with import statement like
import "core.proto";
content of files:
hello.proto
syntax = "proto3";
import "core.proto";
message GetBalance {
string address = 1;
}
core.proto
syntax = "proto3";
message Block {
string chain = 1;
}
I run protoc with
protoc --proto_path=./ --js_out=import_style=commonjs,binary:./ *.proto
Javascript files are generated, but because of "import" statement there is something like
goog.object.extend(proto, core_pb);
and thats a problem because when I try to import this javascript file into my code,
import * as hello_pb from './hello_pb'
it does not work, it says "proto is not defined" it is a reference error.
What am I doing wrong?
Thanks!
While this answer will not directly solve your import problem, it may give you a workaround.
An alternative to "compiling" protobuf into JS is to use protobufjs which implements protobuf and can handle loading arbitrary .proto files. It has its disadvantages (not as lightweight as your solution could be) but it works well.
Assuming you distribute your .proto in your environment (service, app, whatever it is) importing protobufjs and deserializing a message would be something like:
import { loadSync } from 'protobufjs';
...
const protoRoot = loadSync('path/to/hello.proto'));
const Hello = protoRoot.lookupType('Hello'); // can be some_namespace.Hello
...
let message = Hello.decode(buffer);
Most (if not all) datatypes and encoding/decoding is supported. Check out protobuf project page.

How to use functions from different part of my code in jest testing?

I'm trying to write a test in jest.
I have 2 functions in a different js file that i need to use in order to pass
data to the function im testing.
i tried to use:
import {func} from './funcfile' gives:
SyntaxError: Cannot use import statement outside a module
const {func} = require('./funcfile') gives:
SyntaxError: Unexpected token 'export'
looking at other topics and google, tried every dependency installation and added configurations to package.json, jest.config.js, .babelrc, babel.config.js.
the only thing that happened is getting an error around type ErrorHandler = ...
where it says a syntax error again excepted ";"
i reverted everything therefore i don't have the files with the changes, willing to try any solution you may seem fit.
it crashes on export const phone_number and never event get to the getSubCategory export line....
Edit:
Been asked to add some more code so others could understand better,
Thing is there is not much more code.
I have a file with lots of export const = ;
(as described in photo)
and eventually the function export const (as described in photo)
on my jest file i just have the import/ require line I added and the test fails there.
the error i get when using the suggested answer :
You can import your utils class and use constants as properties of this exported module, e.g.
import * as UTILS from './utils';
...
UTILS.getSubCategoryId('return input')
where utils is
export const getSubCategoryId = (category) => category;
Please check example
https://stackblitz.com/edit/typescript-rujqvm?file=index.ts
Combined with VadimB solution had to add these lines to .babelrc on root directory
{
"env": {
"test": {
"plugins": ["#babel/plugin-transform-modules-commonjs"]
}
}
}
Now its all up and working

Node.js - Unable to load from module

Using a JS sdk of Icon a blockchain. Trying to using the SDK API calls and I'm having issues import or require
When I use Import an error is thrown SyntaxError: Cannot use import statement outside a module
When I use require an error is thrown ReferenceError: HttpProvider is not defined
Below is the link to Icon Icx Github
Icon GitHub
const IconService = require('icon-sdk-js');
//import IconService from 'icon-sdk-js';
const provider = new HttpProvider('https://bicon.net.solidwallet.io/api/v3');
const iconService = new IconService(provider);
const totalSupply = iconService.getTotalSupply().execute();
console.log(totalSupply);
In NodeJS you use require to "import" node modules and dependencies to your project
const IconService = require('icon-sdk-js');
Regarding this line const provider = new HttpProvider('https://bicon.net.solidwallet.io/api/v3');
Where are you importing HttpProvider from? HttpProvider is not built in Javascript library.
If it is a node module, you have to do something similar
const HttpProvider = require('HttpProvider'); (in your question you don't specify what HttpProvider is)
I think you might use IconService.HttpProvider('the url'); to use the constructor

Import nodejs module with version number into typescript

So I have a node module which seems to use a versioning system. Using nodejs I simply used
const Package = require('package-name').V1;
which worked without issues. Typescript however does not like the .V1 so I use
import { Package } from 'package-name';
which complies fine but the typescript output to javascript is
const package_name_1 = require("package-name");
Which means that any function or properties of package_name_1 are undefined since the module doesn't seem to load V1.js file (i assume that is how it works..)
So I tried
import * as Package from 'package-name';
But it outputs the same javascript as before..
The actual folder structure of the package I am using is
-node_modules
--package-name
---client
----v1
----v1.js
with the v1.js file looking like
var PackageV1 = {}
PackageV1.CONSTANTS = require('./v1/constants');
PackageV1.Request = require('./v1/request');
PackageV1.Session = require('./v1/session');
...
module.exports = PackageV1;
Of course things like
const Package = require('package-name.V1');
do not work
Error: Cannot find module 'package-name.V1'
How can I require this V1.js file / directory using the typescript method?
As was hinted at in the comments
import * as Package from 'package-name';
is fine but when using the package I had to use
Package.V1.Request()
rather than
Package.Request()

Categories