Cannot resolve native module in package when building Angular CLI project - node.js

Background
I'm creating an application that allows users to interact with basic web controls which output controller events through emulated virtual controllers (so user slides a slider, and that manifests in the system as an axis being changed on a virtual controller). I'm building this as an Electron app which contains an Angular CLI project.
To get the virtual controller functionality I'm consuming a project which wraps native virtual controller functionality and exposes it for node applications. (node-ViGEmClient)
Issue
I've created the basic project and imported the required package. However, when I build the project with ng-build I get the following errors:
./node_modules/vigemclient/lib/DS4Controller.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\deskpad\node_modules\vigemclient\lib'
Tracking these errors down, they come from files like this:
Looking further into the package's structure, it should be looking for vigemclient.node in build/Release, and that file is indeed present:
I feel like there is some configuration I need to do in Angular (something to do with webpack?) but I don't know what it is. Can anyone point me in the right direction?
In case anyone wants to poke around with my (currently barebones) project, it's located here: DeskPad
Project Details
Node: v16.17.0
Angular CLI: v14.2.3
REPRODUCING
Create a new Angular CLI project:
ng new testProj
Install ViGEmClient package:
npm install vigemclient
Note: This seems to require libraries related to building C++ code which are prompted during the initial install for Node.
Add this line to tsconfig.json to allow synthetic default imports:
"allowSyntheticDefaultImports": true,
Reference the package in the default app component so that it is used:
import { Component } from '#angular/core';
import ViGEmClient from 'vigemclient';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'vigTestAngular';
client = new ViGEmClient();
}
Attempt to build the project with the command "npm run build"
Outcome: These errors should be produced:
./node_modules/vigemclient/lib/DS4Controller.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
./node_modules/vigemclient/lib/ViGEmClient.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
./node_modules/vigemclient/lib/ViGEmTarget.js:5:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
./node_modules/vigemclient/lib/X360Controller.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'

I was experiencing the exact same error with a native package. In my case this is also an Electron app with angular ~14.2 on Windows.
A friend pointed me to the problem: I was importing the native package from the angular web app code (renderer), but apparently when using native packages in an Electron application, they can only be imported in the Electron main process (main.ts).
Hope this helps!

Related

SvelteKit and Postgres implementation solution

Has anyone successfully deployed a SvelteKit app using npm pg to Netlify/Vercel/Cloudflare? My local dev implementation works just fine with how I have it set up ( db.ts file with a query function in lib/server, and then using endpoint actions and the load function in +page.server.ts files)
My build errors are as follows:
node_modules/pg-connection-string/index.js:3:18: ERROR: Could not resolve "url" node_modules/pg-connection-string/index.js:4:17: ERROR: Could not resolve "fs" node_modules/pg-pool/index.js:2:29: ERROR: Could not resolve "events" node_modules/pg-protocol/dist/parser.js:9:41: ERROR: Could not resolve "assert" node_modules/pg/lib/client.js:3:27: ERROR: Could not resolve "events"
And many of the above display a previous log message with something along the lines of:
✘ [ERROR] Could not resolve "buffer"
node_modules/safe-buffer/index.js:3:21:
3 │ var buffer = require('buffer')
╵ ~~~~~~~~
The package "buffer" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
I've been trying to get it to just build and it seems like it isn't able to use the pg package because it isn't a true node server environment. For each adapter it attempts to build with (except the node adapter) it refuses to build anything to do with the pg npm package. I could be wrong about the why, but my question about the how remains.
My hope is to avoid something like Prisma (which hasn't been working for me either) and I am trying to do this as "intended" meaning that I want to use SvelteKit as both the front end and the true backend. So an additional express server or the like is not the solution I'm looking for.
EDIT: I have also successfully deployed the app to Azure using the node adapter, but pg AND Postgres.js both do not work.

Where do I find Angular CLI 7.3.9 default generated webpack settings file so I can build my overrides based on it?

I want to extend webpack building process for a project generated by Angular CLI v7.3.9.
I found out I have to use this tool:
https://github.com/just-jeb/angular-builders/tree/7.x.x/packages/custom-webpack
It seems a good solution, but unfortunately I can't find any example about extending existing Angular CLI config file.
I mean - I want to see what Angular CLI already generates for me, before I can think of correct overrides I should use in my custom builder override config. Being somewhat new to webpack, I need to learn what's already there to be able to figure out what I can adjust to avoid totally breaking the project.
Where do I find Angular CLI default generated webpack settings file so I can build my overrides based on it?
To be more specific, the problem is that building the project for production takes about 25 minutes. It is a large project with a few hundreds of form and grid components, and I see that current build process is spending about 20 minutes in ModuleConcatenationPlugin and 5 minutes in TerserPlugin without any serious load on the computer resources. I've heard ModuleConcatenationPlugin is being deprecated and thought that maybe I could use something better instead (UglifyJS ? optimization.concatenateModules ?), but at first I have to find out how Angular CLI uses it, so I can override it correctly.
technically in angular cli since v5 (as far as I know) you have ng eject which will give you access to webpack config.
You can use ngx-build-plus
Example:
Add ngx-build-plus: ng add ngx-build-plus
Add a file webpack.partial.js to the root of your (sub-)project:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
"VERSION": JSON.stringify("4711")
})
]
}
Use the global variable VERSION in your app.component.ts:
import { Component } from '#angular/core';
declare const VERSION: string;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Version: ' + VERSION;
}
Start your application with the --extra-webpack-config switch pointing to your partial webpack config:
ng serve --extra-webpack-config webpack.partial.js -o
If your project is a CLI based sub project, use the --project switch too:
ng serve --project getting-started -o --extra-webpack-config webpack.partial.js
Update you can take a look at their doc and here is the full config

Error: Identifier 'Reader' has already been declared while bundling fstream with rollup.js

I'm new with configuring stuff with Rollup, I'm trying to configure a node CLI app to be bundled in a single cli.bundle.js file that would be executable with a simple node cli.bundle.js without needing to npm install anything before.
On a side note, we already have succeed in doing so with zeit/pkg, but we would rather note have all the nodejs executable bundled inside, so we are trying work with rollup instead of pkg.
The problem we encounter is that when going through the different node_modules of the application, rollup.js crash with error:
[!] Error: Identifier 'Reader' has already been declared
../../common/js-common/node_modules/fstream/lib/file-reader.js (7:4)
5: var fs = require("graceful-fs")
6: , fstream = require("../fstream.js")
7: , Reader = fstream.Reader
^
8: , inherits = require("inherits")
9: , mkdir = require("mkdirp")
Error: Identifier 'Reader' has already been declared
at error (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:5400:30)
at Module.error (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:9820:16)
at tryParse (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:9713:23)
at Module.setSource (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:10076:33)
at Promise.resolve.catch.then.then.then (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:12362:20)
While looking for this error with rollup, it seems people were having it more at execution time than at bundle time, so I have no clue of what I can do. This duplicated identifier is in a 3rd party code I don't control :(
Here is my rollup.config.js
Edit: I tried with the new #rollup/plugins to see if there were a fix in them, but I have still the same issue.
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import json from '#rollup/plugin-json';
export default {
input: 'dist/index.js',
output: {
format: 'cjs',
file: './cli.bundle.js'
},
plugins: [
commonjs(),
resolve(),
json() // asked and added when parsing 'got' package imported by 'download' package
]
};
And our building process is :
transpile from typescript (src) to js (dist) with tsc
bundle (dist) app into single runnable file
We would rather not include babel or typescript plugin to transpile, to stay independant, and certainly the (dist) app is enough (as it was enough for zeit/pkg).
Is there something we are doing wrong ?
The Problem is your dependency it is not coded in the right way you will need to correct the code error they did.

Angular 6 :: Cannot find name 'require'

My project is created using angular cli [ version - 6.1.3 ].
I installed npm module - is-reachable and used it in my code as -
const isReachable = require('is-reachable');
appDetailsFromJson.forEach(app => {
isReachable(app.server).then(reachable => {
console.log('Hey --> ',reachable);
//=> true
});
However, on running the project it throws the exception - error TS2304: Cannot find name 'require'.
What is the root cause for this & what is the correct way to import a library in angular 6 ?
From the NPM page of isReachable it says (my emphasis):
Works in Node.js and the browser (with browserify).
This means that it is unlikely to work natively in an Angular application as the Angular CLI uses webpack and the standard typescript compiler (rather than browserify) to resolve imports and package dependencies.
In general, imports in Angular are standard ES6-style 'import' statements, e.g.:
import { isReachable } from 'is-reachable';
... or ...
import * as isReachable from 'is-reachable';
If is-reachable itself does not use any further require() statements, this may work, but if it uses require within its own code to bring in its dependencies, you would be in for a lot of difficulty in getting it to work at all - and it would almost certainly be better to find a different way to meet your requirement.

How to use Native Node Modules in angular running in electron

Problem description:
This is not a duplicate of this Question. I'm not trying to access the electron module (I use a electron wrapper for angular to do this), I'm trying to use a npm native module in angular while running angular inside electron.
Original description:
I have an angular app which I run with electron (A new app, doesn't do anything yet).
To access Bluetooth I use noble and bleno but while they are working from within electron (to test this I added, noble = require('noble') to index.js in the electron folder) they do not work when I add for example noble to the app.compoents.js in angular.
This is my app.component.ts
import { Component } from '#angular/core';
import {ElectronService} from 'ngx-electron';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title: String = 'Colaboration room';
noble = require('noble')
}
I get this error:
WARNING in ./node_modules/bindings/bindings.js 76:43-53 Critical
dependency: the request of a dependency is an expression
While this is only a warning, the angular initial page is no longer displayed ( its empty).
Question:
How can I access node native modules in Angular (when running in electron)?
Additional Information:
Im using angulars default compiler webpack
The native modules are build against the node version from electron
with electron-rebuild.
I use the ngx-electron module to access the electron api from within angular, thus my guessing that I cant just access noble from within angular without some modification.
Folder structure
Solution attempt: (Since I'm new to node and Angular, I'm happy for code improvements !)
Since I use a wrapper to access electrons apis I had no problem with the electron module.
My real problem was that I didn't know how to access native node modules in angular.
One possible solution is to add the native npm module to webpacks script part (I did not test this yet).
The other solution is to use require in electrons main.js and set it as a
global variable.
const noble = require('noble');
global.sharedObj = noble;
You can then access this global variable using electrons api with the angular electron wrapper.
getBluetoothCentralPulgin(){
var es = new ElectronService();
return es.remote.getGlobal('sharedObj');
}

Resources