#google-cloud/speech - Error: ENOENT: no such file or directory, open 'protos.json - node.js

I'm trying to use the google cloud speech to text api.
I'm using the sample google code and when i create the client object i got this error.
{
"errno":-2,
"syscall":"open",
"code":"ENOENT",
"path":"protos.json",
"stack":"Error: ENOENT: no such file or directory, open 'protos.json'\n at Object.openSync (fs.js:440:3)\n at Object.readFileSync (fs.js:342:35)\n at fetch (transcript-server-js/node_modules/protobufjs/src/root.js:160:34)\n at Root.load (/transcript-server-js/node_modules/protobufjs/src/root.js:194:13)\n at Root.loadSync (/transcript-server-js/node_modules/protobufjs/src/root.js:235:17)\n at Object.loadSync (/transcript-server-js/node_modules/#grpc/proto-loader/build/src/index.js:221:27)\n at GrpcClient.loadFromProto /transcript-server-js/node_modules/google-gax/src/grpc.ts:165:40)\n at GrpcClient.loadProto (/transcript-server-js/node_modules/google-gax/src/grpc.ts:199:17)\n at new SpeechClient /transcript-server-js/lib/webpack:/src/v1/speech_client.ts:135:28)\n at createText$ (/transcript-server-js/lib/webpack:/src/transcriptGenerator.js:50:18)"
}
this is the code
const { Storage } = require('#google-cloud/storage');
const storage = new Storage();
const results = await storage.getBuckets();
const speech = require('#google-cloud/speech');
const client = new speech.SpeechClient();
google cloud storage api works.
can someone help me?
thanks

I ran into this with #google-cloud/firestore. Both #google-cloud/firestore and #google-cloud/speech use the same mechanism to to load protos.json, so my solution should be relevant here.
This happened to me because webpack was building the #google-cloud/firestore package into my bundle. The #google-cloud/firestore package uses __dirname to find protos.json. Since the #google-cloud/firestore code was in my bundle, the __dirname variable was set to my bundle's directory instead of to the node_modules/#google-cloud/firestore/ subdirectory that contains protos.json.
Possible fix #1
Set this in your webpack config to tell webpack to set the value of __dirname:
node: {
__dirname: true,
}
https://webpack.js.org/configuration/node/
Possible fix #2
Update your webpack config to exclude #google-cloud/speech from your bundle.
One way to do this is to use the webpack-node-externals package to exclude all dependencies from the node_modules directory:
var nodeExternals = require('webpack-node-externals')
...
module.exports = {
...
externals: [nodeExternals()],
target: 'node',
...
};
https://webpack.js.org/configuration/externals/
https://www.npmjs.com/package/webpack-node-externals

Thank you so much Gabriel Deal.
I faced the same issue like you in firestore package. I understood why this is occurring from your explanation. Unfortunately the fixes didn't help me. So I had to take an alternate. I copied the protos.json file to the path it is searching for in my dist folder.
Copy protos.json from the node_modules to a folder (I named it external_files)
In the webpack.config.js copy the protos.json file from the external_files directory to the path in which it is searching (In my case it was searching in node_modules/google-gax/protos). Use the plugin CopyWebpackPlugin to do that job as shown below.
module.exports = {
.
.
.
plugins: [
new CopyWebpackPlugin([
{ from: "external_files/protos.json", to: "dist/node_modules/google-gax/protos" }
])
]
}

Related

Node JS - no such file or directory filesystem module

I'm trying to use an email template while sending emails. here's my project structure.
project-name
client
server
email-templates
confirm-email.html
controllers
accounts.js (currently here)
I am reading the template file like so.
fs.readFile('../email-templates/confirm-email.html', async (error, html) => {
// do some stuff
})
I think have entered a correct path. but still I get an error.
Error: ENOENT: no such file or directory
I have checked other questions on SO. but they are using the variable __dirname because I am using ES6 modules I don't have access to that variable.
// package.json
"type": "module",
any suggestions ?
Try to use path module to resolve the absolute path the file when you are trying to access the file.
fs.readFile(path.resolve(__dirname, '../email-templates/confirm-email.html'), function(err, html) {// do some stuff})
I don't have access to __dirname because I'm using ES6 modules. I've used path.resolve() instead which fixed the error.
fs.readFile(
path.join(path.resolve(), 'email-templates', 'confirm-email.html'),
'utf8',
(error, html) => {
// do some stuff
}
);
to get access of the __dirname variable when can do:
const __dirname = path.resolve();

Is it possible to use webpack with a library that uses dependency injection?

I'm pretty new to webpack so apologies if this is an obvious answer. I'm currently trying to deploy a typescript lambda api to AWS using this library: https://www.npmjs.com/package/ts-lambda-api
The library uses Inversify for dependency injection: https://github.com/inversify/InversifyJS
The library also advises building by just using zip but I'd like to use webpack if I can.
I currently have two files for my api, a main api.ts file and then a controller.ts file. Currently the api class finds the controllers using the same lines as in the ts-lambda-api docs:
const controllersPath = [path.join(__dirname, "controllers")]
const app = new ApiLambdaApp(controllersPath, appConfig)
As a result I need the controller directory to be available to the api.ts class once it's been bundled. Currently my webpack config looks like this:
import path = require('path')
import webpack = require('webpack')
const config: webpack.Configuration = {
module: {
rules: [
{ test: /\.js\.map$/, use: "ignore-loader" },
{ test: /\.d\.ts$/, use: "ignore-loader" }
]
},
mode: 'production',
entry: {
my_api: ['./src/my-api.js'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]/main.js',
library: '[name]',
libraryTarget: 'commonjs2'
},
target: 'node',
externals: [/aws-sdk.*/, 'aws-lambda']
};
export default config
How can I add to it to allow my api access to the other classes it needs? The webpack docs have a page on multiple entry points (https://webpack.js.org/concepts/entry-points/#multi-page-application) but that doesn't seem to be what I'm looking for as it gives me multiple bundles.
I can put multiple files into one bundle by doing something like:
api: ['./src/api.js','./src/controllers/controller.js],
Although this won't then work with the Injectable annotations. Anyone have any other ideas?
I managed to get around this issue by manually loading in the controllers following the section in the ts-lambda-api docs on how to do so.

Error: Unable to read configuration file newrelic.js

I’m getting this error:
Error: Unable to read configuration file newrelic.js.
A base configuration file can be copied from 536 and renamed to in the
directory from which you will start your application.
Project is Angular 7 SPA with SSR.
There are two solutions:
The first by bj97301 on official new relic forums.
in my webpack config file, make newrelic external:
externals: ['newrelic']
in my webpack config file, use commonjs as my output library target:
output: { libraryTarget: 'commonjs'}
change newrelic.js to use exports. instead of export:
was: export const config = {
now: exports.config = {
This methods won't work if you want to deploy a whole package to remove server since you excluded the new relic package.
To solve this, you can use the second method.
As a workaround, change newrelic.js to override Environment variable instead of exporting the config.
e.g.
process.env.NEW_RELIC_NO_CONFIG_FILE = 'true';
process.env.NEW_RELIC_APP_NAME = 'YOUR APP NAME';
process.env.NEW_RELIC_LICENSE_KEY = 'YOUR_KEY';
process.env.NEW_RELIC_LOG_LEVEL = 'warn';
process.env.NEW_RELIC_ALLOW_ALL_HEADERS = 'true';
console.log('New relic has been configurated.');
And you can remove the original config that was exported:
'use strict';
exports.config = {
app_name: [],
license_key: '',
logging: {
level: 'warning'
},
allow_all_headers: true
}
Don't forget to require on your server.ts, simply add:
require('./newrelic');
I hope it would save someone some hours.

Node-Red custom node_modules location

I'm using node-red as embedded in my Express.js application like this
https://nodered.org/docs/embedding. When embedded like this node-red cant load new nodes from npm.
Issue is that when defining custom user dir in settings.js, for example userDir: 'node-red-data/' Node-red adds loaded nodes to this folder inside node_modules.
So I have two node_modules folder:
myapp/node_modules => this is containing node-red
myapp/node-red-data/node_modules => this is containing node-red extra nodes
Some how node-red can't load modules in side myapp/node-red-data/node_modules
Is there any solutions?
Issue was on the settings file.
My setting in user dir:
var settings = {
httpAdminRoot: '/admin',
httpNodeRoot: '/ap',
nodesDir: '/nodes',
flowFile: "flows.json",
userDir: './data/'
}
Right setup:
var path = require('path');
var dir = path.dirname(__filename);
var settings = {
httpAdminRoot: '/admin',
httpNodeRoot: '/ap',
nodesDir: dir + '/nodes',
flowFile: "flows.json",
userDir: dir+'/data/'
}
So adding static path to user dir and nodes dir makes it working
I have similar problem.
I used process.execPath
userdir = path.resolve(process.execPath,'..'); //better that __dirname;
Because the dir is diferent when application is compiled.
// Create the settings object - see default settings.js file for other options
var settings = {
verbose: true,
httpAdminRoot:"/admin",
httpNodeRoot: "/",
userDir: userdir, // problem with dir...
flowFile: 'flows.json',
};

nunjucks: Template not found

Trying to render a nunjucks template but getting Error: template not found: email.html.
server/
views/
email/
email.html
workers/
email.worker.js
//email.worker.js
function createMessage(articles) {
console.log(__dirname) // /<path>/server/workers
nunjucks.configure('../views/email/');
return nunjucks.render('email.html', articles);
}
No idea what's wrong here.
I had the same issue my solution was using path module:
const njk = require('nunjucks');
return njk.render(path.resolve(__dirname, '../views/email/' + 'email' + '.html'), articles);
I had same issue. I found this at the documentation:
In node, 'views' would be a path relative to the current working directory.
If you run the node server at the root directory, the template path would be server/views.
nunjucks.configure('server/views/email/');
return nunjucks.render('email.html', articles);
In my case, the server script is in public directory.
So, when i run the server from the root directory, the nunjucks configuration will look like this:
nunjucks.configure('src/templates');
return nunjucks.render('index.html', { name : 'Dian' });
It works.
But if I run the server from the public directory, the tempate will not found.
Had the same issue, try this if it helps. If you're using express and you have a views folder:
From nunjucks docs
var app = express();
nunjucks.configure('views', {
autoescape: true,
express: app
});
You can use nodejs' __dirname to resolve the path for you as
nunjucks.configure(__dirname + '/views')...
The nunjucks templates (located under src) were not included in build folder in my case.
Such a configuration in my nest-cli.json file solved my issue:
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "#nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": [
"**/*.njk"
]
}
}

Resources