<app-my-component #myId></app-dynamic-plot>
@ViewChild('myid', {read: MyComponent}) myComponent!: MyComponent;
<app-my-component #myId></app-dynamic-plot>
@ViewChild('myid', {read: MyComponent}) myComponent!: MyComponent;
Use [feedback]="false"
to hide the strength meter:
<p-password [feedback]="false" [(ngModel)]="value"></p-password>
On my Desktop, Angular commands such as
ng build
or
ng new
worked successfully, but they didnt stop / terminate after running the command. Instead, they just waited indefinitely without any output.
This is related to analytics being enabled, see this GitHub post.
In order to fix it, run
ng analytics disable --global
It will print
Global setting: disabled Local setting: enabled Effective status: disabled
and it won’t terminate the first time you do this. Just press Ctrl+C
to force stop it.
After that, any command will exit after finishing its task
I suspect this has something to do with IPv6 configuration since my Desktop’s IPv6 network setup is somewhat broken at the moment. However, I did not do any further research into this.
Run these shell commands on your Ubuntu computer to install NodeJS 20.x:
sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg NODE_MAJOR=20 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list sudo apt-get update sudo apt-get install nodejs -y
Instead of 20
you can also choose other versions like 18
. However, using this method, you can’t install multiple versions of NodeJS in parallel.
When opening your Angular app with a standalone component, you see the following error message:
Can't bind to 'routerLink' since it isn't a known property of 'a'
In the component where the error occurs, add
import { RouterModule } from '@angular/router';
and add
RouterModule,
to the imports
of the component. Example:
@Component({ selector: 'app-top-bar', standalone: true, imports: [ CommonModule, RouterModule ], templateUrl: './top-bar.component.html', styleUrl: './top-bar.component.sass' }) export class TopBarComponent { }
Based on our previous example How to make cell bold using xlsx / SheetJS, the following code example will set {s: {font: {bold: true}}
for every cell of the first row.
This code assumes that you know the number of columns (header.length
in this example).
Add the following code after adding the cell content to the worksheet.
// Make first row bold for(let i = 0; i < headers.length; i++) { const cell = ws[XLSX.utils.encode_cell({r: 0, c: i})]; // Create new style if cell doesnt have a style yet if(!cell.s) {cell.s = {};} if(!cell.s.font) {cell.s.font = {};} // Set bold cell.s.font.bold = true; }
First, you need to understand that stock xlsx
/ SheetJS community edition does not support cell styling as of August 2023.
Hence, you need to use the fork xlsx-js-style which you can install using
npm i --save xlsx-js-style
Now, based on our previous example, use these imports
import * as XLSX from 'xlsx-js-style'; import { saveAs } from 'file-saver';
and this code to generate a XLSX file with a bold cell:
// Create an empty workbook const wb = XLSX.utils.book_new(); // Create an empty worksheet // If this weren't a minimal example, your data would go here const ws = XLSX.utils.aoa_to_sheet([ ["Test"] ]); // Make cell bold ws["A1"].s = { font: { bold: true, } }; // Add the worksheet to the workbook XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); // Export the workbook to XLSX format const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'buffer' }); // Convert the binary data to a Blob const blob = new Blob([wbout], { type: 'application/vnd.ms-excel' }); // Download of the file using file-saver saveAs(blob, 'example.xlsx');
Depending on the minimum NodeJS version you intend to support,, you should use the following –target settings for tsc
:
es2018
es2019
es2020
es2021
es2022
es2022
es2022
es2022
Note that there are more configurations possible than just --target
when compiling for NodeJS. See the tsconfig base config examples on Github for more details.
Source: The tsconfig bases on Github.
The following Typescript example allows you to “ping” an IP address or host name not using ICMP but using TCP connection to a given port. If the TCP connection is accepted, the ping is resolved as true
. If no connection can be established, it is returned as false
. In any case, no data is exchanged and the connection is closed immediately after establishing it.
import { Socket } from "net"; /** * Basic TCP ping that returns true if the connection is successful, false if it fails * The socket is closed after the connection attempt, no data is exchanged. */ export function TCPConnectPing(ipAddress, timeout=5000, port=80): Promise<boolean> { return new Promise((resolve) => { const socket = new Socket(); let connected = false; // Set a timeout for the connection attempt const timer = setTimeout(() => { if (!connected) { socket.destroy(); resolve(false); // Connection timed out } }, timeout); socket.connect(port, ipAddress, () => { clearTimeout(timer); connected = true; socket.destroy(); resolve(true); // Connection successful }); socket.on('error', (error) => { clearTimeout(timer); if (!connected) { resolve(false); // Connection failed due to error } }); }); }
When you try to run any npm
command such as npm start
, you see an error message such as
/usr/lib/node_modules/npm/lib/es6/validate-engines.js:31 throw err ^ TypeError: Class extends value undefined is not a constructor or null at Object.<anonymous> (/usr/lib/node_modules/npm/node_modules/fs-minipass/lib/index.js:136:4) at Module._compile (node:internal/modules/cjs/loader:1233:14) at Module._extensions..js (node:internal/modules/cjs/loader:1287:10) at Module.load (node:internal/modules/cjs/loader:1091:32) at Module._load (node:internal/modules/cjs/loader:938:12) at Module.require (node:internal/modules/cjs/loader:1115:19) at require (node:internal/modules/helpers:119:18) at Object.<anonymous> (/usr/lib/node_modules/npm/node_modules/cacache/lib/content/read.js:4:13) at Module._compile (node:internal/modules/cjs/loader:1233:14) at Module._extensions..js (node:internal/modules/cjs/loader:1287:10)
This is an internal error in npm
or packages required by npm
. Typically, it is caused by an incomplete update of NodeJS and npm which leaves npm
or its dependencies in a broken state.
The solution is to reinstall NodeJS:
sudo apt remove nodejs
sudo mv /usr/lib/node_modules ~/node_modules_backup
sudo apt -y install nodejs
npm i -g @angular/cli
As of version v13.1.0
, node-ssh
does not support generating SSH keys by its own.
However, you can use the ssh2
library which is already used internally by node-ssh
.
See our post How to generate SSH public & private key in NodeJS using ssh2 library for more details.
I tested with node:20
and node:20-alpine
and can confirm that:
node:20
(i.e. debian bookworm based) has a working ssh-keygen
node:20-alpine
does not have ssh-keygen
On Alpine, you can install ssh-keygen
using apk
.
Typically, this means you have to build your own docker image based no node:20-alpine
. In your Dockerfile
, add
RUN apk update && \ apk add --no-cache \ openssh-keygen
You see the following error message while compiling your angular application:
Error: src/app/my/my.component.ts:9:4 - error TS2552: Cannot find name 'Input'. Did you mean 'oninput'?
Open your module file, e.g. my.component.ts
and add the following line at the top:
import { Input } from '@angular/core';
If you see an error message such as
Error: src/app/my-component/my-component.component.html:2:1 - error NG8002: Can't bind to 'routerLink' since it isn't a known property of 'p-button'. 1. If 'p-button' is an Angular component and it has 'routerLink' input, then verify that it is part of this module. 2. If 'p-button' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.
in your angular app, open the module file that is declaring your component (typically app.module.ts
) and add
RouterModule,
to its imports
, for example:
imports: [ CommonModule, RouterModule, ]
This example builds on our previous posts NodeJS Mikrotik API minimal example and MikroTik RouterOS: How to power-cycle PoE using the terminal.
The following code will print the PoE status on Port ether5
on the given MikroTik device using the MikroTik API.
import * as MikroNode from 'mikrotik' ; const host = "192.168.88.1"; const username = "admin"; const password = "admin1234"; // Hope that's not your real password ;) const connection = MikroNode.getConnection(host, username, password, { closeOnDone : true }); connection.getConnectPromise().then(function(conn) { conn.getCommandPromise(['/interface/ethernet/poe/print', '?name=ether5']).then(values => { console.log(values); }, reason => { console.log('Error while running command: ' + JSON.stringify(reason)); }); }).catch(reason => { console.log('Error while connecting: ' + JSON.stringify(reason)); });
[ { '.id': '*5', name: 'ether5', 'poe-out': 'forced-on', 'poe-priority': '10', 'poe-lldp-enabled': 'false', 'power-cycle-ping-enabled': 'false', 'power-cycle-interval': 'none', '.about': 'poe-out status: power_reset' } ]
If the PoE is currently being power-cycled, this will print:
[ { '.id': '*5', name: 'ether5', 'poe-out': 'forced-on', 'poe-priority': '10', 'poe-lldp-enabled': 'false', 'power-cycle-ping-enabled': 'false', 'power-cycle-interval': 'none', '.about': 'poe-out status: power_reset' } ]
This is an example of access the Mikrotik API using NodeJS and the mikrotik
package.
First, install the package
npm i --save mikrotik
Also, in order to enable import
statement, set
"type": "module"
in package.json
.
import * as MikroNode from 'mikrotik' ; const host = "10.56.23.4"; const username = "admin"; const password = "N@CdVTz8y@D$KwVS5TTo"; // Hope that's not your real password ;) const connection = MikroNode.getConnection(host, username, password, { closeOnDone : true }); connection.getConnectPromise().then(function(conn) { conn.getCommandPromise('/ip/address/print').then(addresses => { for(const address of addresses) { console.info(`Address: ${address.address} on ${address.interface}`); } }, reason => { console.log('Error while running command: ' + JSON.stringify(reason)); }); }).catch(reason => { console.log('Error while connecting: ' + JSON.stringify(reason)); });
This will output, for example:
Address: 192.168.88.1/24 on bridge Address: 10.1.2.3/24 on bridge
In case of bad username/password credentials, it will print:
Error while connecting: {"errors":[{"category":"","message":"invalid user name or password (6)"}],"channelId":"login","channel":{"id":"login","running":true,"closing":true,"closed":true,"clearEvents":false,"saveBuffer":true,"closeOnDone":false,"lastCommand":["/login","=name=admin","=password=admin1234",".tag=login"],"_events":{},"_eventsCount":0}}
The following code is a Promise
based wrapper around ssh2’s utils.generateKeyPair()
:
const { utils: { generateKeyPair } } = require('ssh2'); const {writeFile} = require('fs/promises'); /** * ssh2's generateKeyPair as promise */ function SSHGenerateKeyPairPromise(keytype="ed25519", opts = {}) { return new Promise((resolve, reject) => { generateKeyPair( keytype, opts, (err, keys) => { if (err) { return reject(err) }; return resolve(keys); } ); }); } /** * Run SSHGenerateKeyPairPromise() and save the keys to * opts.privateKeyPath and opts.publicKeyPath * @returns The generated keys */ async function SSHGenerateAndSaveKeyPairPromise(keytype="ed25519", opts = {}) { // Check if opts.privateKeyPath and opts.publicKeyPath are set if (!opts.privateKeyPath || !opts.publicKeyPath) { throw new Error("opts.privateKeyPath and opts.publicKeyPath must be set"); } const keys = await SSHGenerateKeyPairPromise(keytype, opts); //Save keys to opts.privateKeyPath and opts.publicKeyPath using fs.promise await writeFile(opts.privateKeyPath, keys.private); await writeFile(opts.publicKeyPath, keys.public); return keys; }
ed25519
keys:SSHGenerateAndSaveKeyPairPromise('ed25519', { privateKeyPath: 'id_ed25519', publicKeyPath: 'id_ed25519.pub' }).then(keys => { console.log("Successfully generated ed25519 keys"); }).catch(err => { console.log(err); });
rsa
keys:SSHGenerateAndSaveKeyPairPromise('rsa', { bits: 8192, privateKeyPath: 'id_rsa', publicKeyPath: 'id_rsa.pub' }).then(keys => { console.log("Successfully generated RSA keys"); }).catch(err => { console.log(err); });
My NodeJS app using the argon2
library crashed within my docker container (the process just exited without an error message) every time I used argon2
funtions, even though it worked fine on my Desktop.
This error occured with argon2==0.30.3
. I fixed it by downgrading it to 0.26.2
using the following statement in package.json
:
"argon2": "^0.26.2",
With the correct version installed (don’t forget to npm install
after changing package.json
), the issue disappeared entirely. I did not try any other versions of argon2
.
Whereas in Python you would use
if name == "__main__": # TODO Your code goes here
in NodeJS you can simply use
if (require.main === module) { // TODO Your code goes here }
In order to set the HTTP response code using Koa, use ctx.status = ...
ctx.status = 403;
const Koa = require("koa"); const app = new Koa(); app.use(async (ctx, next) => { ctx.status = 403; ctx.body = "Forbidden"; }); app.listen(3000);