Node.js Module in Typescript - javascript

What must the module code (writen in typescript) look like to be able to use it like this:
/// <reference path="./onoff.ts" />
//import * as onoff from "./onoff";
var onoff = require("./onoff");
var app = onoff();
var computers: Onoff.Computer[] = [];
app.start(computers);
I was sure it must be this, but it does not work:
import * as express from "express";
export module Onoff {
export class Computer {
}
export class OnoffApp {
start(computers:Computer[], port:number = 3489) {
...
}
}
export default function() {
return new OnoffApp();
}
}
Typescript complains:
service/example.ts(5,11): error TS2349: Cannot invoke an expression whose type lacks a call signature.
service/example.ts(7,16): error TS2503: Cannot find namespace 'Onoff'.
service/example.ts(8,21): error TS2503: Cannot find namespace 'Onoff'.
typings/express/express.d.ts(14,1): error TS6053: File 'typings/serve-static/serve-static.d.ts' not found.
typings/express/express.d.ts(28,34): error TS2307: Cannot find module 'serve-static'.
thank you very much! I have no Idea what I've done wrong...

Judging from the error description, moving the import outside of your module should fix your problem:
import * as express from "express";
export module Onoff {
...
}
You import your module as onoff but are trying to use Onoff
var onoff = require("./onoff");
^
var computers: Onoff.Computer[] = [];
^

Related

Undefined cryptojs when importing crypto-js in Nest Js

I am importing crypto-js in a Nestjs service, and I run into this error
TypeError: Cannot read properties of undefined (reading 'enc')
at CryptoUtilsService.decryptAESHex
The code:
import { Injectable, Logger } from '#nestjs/common';
import { CmacDto, Crc32Dto } from './dto';
import CryptoJS from 'crypto-js';
import { AesDecryptDto } from './dto/aesDecrypt.dto';
#Injectable()
export class CryptoUtilsService {
private readonly logger = new Logger(CryptoUtilsService.name);
decryptAESHex(data: AesDecryptDto) {
let keyHex = CryptoJS.enc.Hex.parse(data.key);
let ivHex = CryptoJS.enc.Hex.parse(data.iv);
let encryptedWordArray = CryptoJS.enc.Hex.parse(
data.encryptedData.toUpperCase(),
);
let encString = CryptoJS.enc.Base64.stringify(encryptedWordArray);
// console.log("before decryption: ", encryptedString.toUpperCase(), encString);
let decryptedResp = CryptoJS.AES.decrypt(encString, keyHex, {
iv: ivHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.NoPadding,
});
// console.log("after decryption:: ", decryptedResp)
return CryptoJS.enc.Hex.stringify(decryptedResp).toUpperCase();
}
}
I have installed crypto-js and #types/crypto-js module. Also tried deleting the node_modules and installing again.
It seems to work fine on other node projects without typescript. I cannot figure out what is going wrong here.
crypto-js doesn't use default exports for its base package, use import * as CryptoJS from 'crypto-js' to import the package correctly

Getting exported cache into a module

I'm trying to access a exported Cache into another file, but not having success.
Basically I've got two files:
cache.ts I'll expose only the part that meter
import Cache = require('node-cache');
const narrativeCache: Cache = New Cache();
protected setNarrativeCache(): void {
narrativeCache.set(123,'abc',0);
}
module.exports.narrativeCache = narrativeCache;
I want use this narrative in this other file:
module.ts
import { narrativeCache } from '../transport/cache.ts';
function test1(): void {
narrativeCache.get(123); //Error in here, it doesn't find this
}
Files tree:
src\transport\cache.ts
src\reader\module.ts
The error is because it doesn't find this narrativeCache.
The error was becausing of typescript export type:
Here's the solution
export const narrativeCache: Cache = new Cache();

Can't use ES6 import syntax

I'm trying to use the ES6 import syntax and keep running into errors.
This is my data type,
class UnionFind{
constructor(n){
this.items = n;
}
union(p, q){
}
connected(p, q){
}
find(p){
}
count(){
}
}
export default UnionFind
Saved in a file UnionFind.js
This the calling client,
import { UnionFind } from './unionFind';
const readline = require('readline');
const rl = readline.createInterface({
input:process.stdin,
output:process.stdout,
terminal:false
});
uf = new UnionFind(10)
rl.on('numbers', function (line) {
arr = number.split(' ')
console.log(arr);
});
This is saved in a file client.mjs
This is how I'm running it,
node --experimental-modules union-find/client.mjs
I get the following error,
(node:13465) ExperimentalWarning: The ESM module loader is experimental.
file:///Users/mstewart/Dropbox/data-structures-algorithms-princeton/union-find/client.mjs:1
import { UnionFind } from './unionFind';
^^^^^^^^^
SyntaxError: The requested module does not provide an export named 'UnionFind'
at ModuleJob._instantiate (internal/modules/esm/ModuleJob.js:89:21)
at <anonymous>
What am I doing wrong here?
In this case, use
import UnionFind from './UnionFind.js';
if you declared
export class UnionFind{ ....
then you use
import { UnionFind } from './UnionFind.js';
Also take a look at the file name: UnionFind.js . You are using './unionFind'. This is case sensitive

How to construct new class using ES6 syntax from library module?

index.js of imported npm module myLib
const Mod1 = require('./mod1');
const Mod2 = require('./mod2');
const Mod3 = require('./mod3');
module.exports = {
Mod1,
Mod2,
Mod3,
};
mod1.js
class Mod1 {
constructor(url) {
}
}
file using the above npm module
const Mod1 = require('myLib');
const instance = new Mod1();
This is throwing the following error when trying to run it:
const instance = new Mod1();
^
TypeError: Mod1 is not a constructor
How should I reference the class from a single import index.js so that I may be able to create an instance of the class?
There seems to be a slight mistake in your import, the actual import will be like:
const {Mod1} = require('myLib');
which will pull the class from the file and give it to you (ES6 feature)
you can also do it like:
const Mod1 = require('myLib').Mod1;
hope this helps.

Correctly writing and importing custom node modules

EDIT
This is NOT a TypeScript question but rather a best-practices one. The example in TypeScript but really, the question here is how do I, correctly, expose multiple exports from multiple files that compose a module, and how to correctly import them.
EDIT 2
There's still something not right
So, on my Module2's index I have this:
export * from "./queryFilter";
On Module1 user.ts I import it by using
import { queryFilter as QueryFilter } from "Module2";
(...)
var User = {...}
User.getById = (userId: string) => {
...
}
export { User }
And my Module1's index.ts I export it as
export * from "./model/user";
Then, on my main project I import it using
import * as Schema from "Module1";
var User = Schema.User;
However, this throws an error whenever I try to call User.getById:
Debug: internal, implementation, error
TypeError: Uncaught error: Cannot read property 'getByEmail' of undefined
From this approach, what am I doing wrong???
I'm writing a couple of node modules for the first time ever and I do have some questions regarding proper declaration/usage of this.
So I'm creating a module that will require another custom module, let's call them Module1 and Module2.
So, Module1 is required by the main application, but Module1 also requires Module2.
Now on Module2 I have a bunch of files and on each one I export what I need. Here's a sample:
Module2 - Utils.ts:
"use strict"
const RandomString = require("randomstring");
let randomString = (numCharacters: number) => {
return RandomString.generate({
length: numCharacters,
capitalization: 'uppercase',
charset: 'alphanumeric'
});
}
module.exports.randomString = randomString;
Module2 - queryFilter.ts:
"use strict"
export default class QueryFilter {
name: string;
op: string;
value: any;
scope: string;
constructor(name: string, op: string, value: any, scope: string) {
this.name = name;
this.op = op;
this.value = value;
this.scope = scope;
}
public static GetConditionQuery(filters: QueryFilter[], params: string[]) {
(...)
}
public static queryComparator(value1: any, value2: any, operator: string): any {
(...)
}
}
On Module1, I added Module2 to package.json so when I want to use QueryFilter, for instance, I require it like this:
Module1 - Class.ts:
import { QueryFilter } = require("Module2").queryFilter;
Now my question is, is it enough to export individual items from each file in my Module2 and use it in this fashion? Or should I have a index that would export every file from Module2 so that Module1 can see them?
Something along the lines of:
Module2 - index.ts:
export "./utils"
export "./queryFilter"
(...)
What is the correct way of doing this? I'm a total newb to this and the docs I've read didn't shed any light on this..
Best Regards
Following your last comment, this the 'typescript solution' for creating a module/library. The solution would be similar for "pure" ES6; typings in Typescript just add a small layer of difficulty.
Assuming you write a module/library with multiple files:
func1.ts
export func1(param1: number): string { ... }
func2.ts
export func2(): number { ....}
Create an index.ts which re-exports the interesting parts of your module/lib
export * from './func1'
export * from './func2'
....
Obviously you can choose to (re)export and make public only part of the code e.g. export { thisFunc, thatClass } from './anotheFile'
Compile the module with declarations and commonjs flags, and make sure that the package.json main points to index.js, while the typings entry points to the generated index.d.ts
This module/library can now be used from Javascript or Typescript using an ES6 style import syntax
import { func1, func2 } from 'mymodule'
If this is Typescript, the typings of the 2 functions will automatically be imported too.

Categories

Resources