fs.readFileSync is not a function - node.js

I am using rn-nodeify for enabling the use of pdf2json in React Native. pdf2json uses fs for loading files using the method readFileSync. I am getting this error when I try to use the library:
fs.readFileSync is not a function. (In 'fs.readFileSync(_basePath + fieldName, 'utf8')', 'fs.readFileSync' is undefined)
I cannot find any support for this issue. Any pointers appreciated.
Edit: Please note that I am not trying to run this in a browser. This pertains to react-native i.e. it runs on a device, and the code should have access to the file system.

FWIW, I came across this problem while writing tests in ES6/latest JS - fixed this by changing the import from:
import { fs } from 'fs';
to
import fs from 'fs';
Notice the unnecessary {} - fs is the default export from the fs node module and should be imported in the latter way
For a better explanation on default & named exports please see this SO discussion

Related

Create own class

created a new project in expressjs. I want to create my own class. So I created a file MyClass.js in /routes/.
class MyClass {
constructor() {
}
}
export default MyClass;
And in /routes/index.js i added:
import MyClass from './MyClass';
And I have an error:
import MyClass from './MyClass;
^^^^^^
SyntaxError: Cannot use import statement outside a module
[...]
What I'm doing wrong?
Your project is not set up properly to interpret the file that has the error as an ESM module file. It is, instead, being interpreted as a CommonJS module (where you use require(), not import) which is the nodejs default.
There are a number of ways to tell nodejs that your file is supposed to be an ESM module.
You can give it a file extension of .mjs.
You can add "type": "module" to your package.json file.
You can use the --input-type=module command line argument when starting node.js if this file is your top level file you're executing.
See nodejs doc here on this subject.
FYI, you could just switch to the CommonJS syntax of using require() and module.exports instead of import and export, but I assume what you really want to do is to tell nodejs that you want to use ESM modules so you can use the more modern import and export syntax.
Well first of all to export your class you suppose to use exports or module.export
and to import it you suppose to use require('') not import.
Those features are only available with .mjs or if you will setup babel though soome es6 features are yet to land in

nodejs import url from string

I am new to nodejs REST api creation. I am using ES6 format. I have decided to create an environment based configurations and stored in different files.
So the issue I came across was
const myUrl = path.resolve(`lib/${process.env.NODE_ENV}.js`);
import { myVar } from myUrl;
I try importing files like shown above, but it doesnt work. I understand it can be easily solved by using
const myVar = require(myUrl)
But I want to know if there is any way to continue using import itself instead of require?
MDN has all ways of importing, but i could not find a way on how to import from a constructed url like above
The ES6 import format only allows imports from static string literals, as it is being evaluated at load time (before executing any code).
If you really want to load the module dynamically based on your environment, use the dynamic form of import (not require):
var promise = import("module-name");
However, maybe you would like to use the more standard way: store your environment configurations in .env files, use the dotenv library to load the configuration dynamically from the correct location - while the code that loads it is static and is the same for all environments, in a dedicated module, and then it can be statically imported by your app code.

How can I automatically 'audit' or 'rationalise' my imports in a NodeJS project?

I'd like to be able to go through my project and automatically change all instances in which an entire library is imported when only one export of that library is needed to only import the export(s) needed. Thus
import R from 'ramda'
const sillyValue = R.add(2,3)
const moreSilly = R.always('foo')
would be changed to
import {add, always} from 'ramda'
const sillyValue = add(2,3)
const moreSilly = always('foo')
Is there any sort of utility that I can run to do this automatically for all the modules in my project at once? I have WebStorm, but so far I haven't found any way to do it using the IDE ('Optimize Imports', while nice, doesn't seem to do what I want).
WebStorm doesn't have such inspection; you can try using ESLint for this, see eslint-plugin-import plugin, no-named-as-default-member rule

Importing node modules once for whole project

Scenario
So, I have initialised a Node project with npm. I have setup my package.json accordingly. I am using typescript, so I have also setup tsconfig.json.
I have a few dependencies (npm packages) that I will need to use multiple times in multiple files of my project.
index.ts is the root of my project. I can import these libraries in index.js and other files also.
Problem
Is there any way to include or import these libraries in the project only once so that I can use them in any file of the project without having to import a single thing anywhere.
I tried searching for various ways to do this using -
CommonJS module syntax, NodeJS module syntax, global modules - but none of it can provide me the way I want it.
For Ex -
Most of the answers or solutions I got were like this
Export all the libraries through a single file
import abc from 'abc';
import xyz from 'xyz';
module.exports = {
abc, xyz
};
Use these libraries in other files like
import modules from 'src/modules.ts'
var wantSome = modules.abc.getSome();
But, this still has an overhead of importing modules file and accessing it like modules.abc.
Do we have any way to make these imports available globally through out the project.
P.S. - This scenario is somewhat similar to ngModules in Angular 2+, where we can import whatever we want inside ngModules and it is then available to all the components under that module.
Doing this is going to cause you all sorts of problems in the long run.
you'll end up with one monolithic file containing all your exports, which will become onerous to maintain
if you decide to modularise your code, it will be more difficult since you won't explicitly know which modules a file uses
if you were able to include to the point where you simply use the modules with no reference, code clarity will suffer
name clashes might occur
The best I believe you'll get in node is to declare all the includes in a single module, and then destructure within your own file.
import abc from 'abc';
import xyz from 'xyz';
module.exports = {
abc, xyz
};
Then
import modules from 'src/modules.ts'
{ abc: { getSome } } = modules
But I strongly suggest using the standard patterns for importing. It will make your code much cleaner and easier to maintain
N/B - Thats a bad way to design your app.
In node, you can set global variables via the "global" or "GLOBAL" object:
You could import all your dependencies in your app entry file, and store them in a Global variable
index.js
import abc from 'abc';
import xyz from 'xyz';
global.abc = abc
global.xyz = xyz
someotherfile.js
//access abc import
global.abc
Export all the libraries through a single file
import abc from 'abc';
import xyz from 'xyz';
module.exports = {
abc, xyz
};
Use these libraries in other files like
import {abc, xyz} from 'src/modules.ts'
var wantSome = abc.getSome();

NodeJS - reading macOS .plist files

I have a .plist file on my mac that I would like to read. I can easily open it using Xcode but would like to do it using NodeJS.
I found plist package and I'm trying to use it like this:
import fs from 'fs';
import plist from 'plist';
fs.readFile('/my/path/here.plist', 'utf-8', (err, data) => {
console.log('#data', data);
const obj = plist.parse(data);
console.log('#obj', obj);
});
What I'm getting as data is looking like this (a part from that file)
dataYdisplayasZfile-label]file-mod-date[arrangement_preferreditemsize��- O(book(0$Usersnyc Downloads �i(� +� HXhA���L� file:///Macintosh
plist package is throwing errors as I guess it expects string in XML format.
How can I read a .plist file like this?
Ok, found the solution. Guess posting to SO gives me more luck in googling...
macOS .plist files are mostly in binary. There is a command plutil that allows you to convert to binary to xml, so to do this in node you have to:
import { exec } from 'child_process';
const command = 'plutil -convert xml1 ./path/to/binary/file.plist';
exec(command, callback); // Here you gonna convert this file to plain `xml`.
Then you just have to repeat my steps from above - read the file using fs.readFile and then convert it using plist package so you get a nice JS object.
Hope this helps someone!
I’d recommend using an appropriate library such as bplist-parser (read-only) or simple-plist (read-write, wraps bplist-parser and bplist-creator, also handles plain text plist) instead of using the child_process module. Don’t forget that exec needs special care (e.g. arguments escaping) and it’s easy to shoot yourself in the foot using it!
import { parseFile } from 'bplist-parser';
parseFile('./path/to/binary/file.plist', callback);

Resources