How to dynamically import data in a nodejs app? - node.js

I would like to use require in a node/express app with typescript to import a json. I tried it like this:
const url = `./data/${resource}.json`;
const data = require(url);
but I get the error Cannot find module './data/my-data.json'.
I'd like to use require instead of an import in order to create the data variable dynamically depending on the value of the resource variable.

const path = require('path');
const url = path.resolve(__dirname, `./data/${resource}.json`);
const data = require(url);

The require keyword is a special keyword in nodejs. It is used to load modules, and since your json file is not a module, hence the error. Try this, this way you can dynamically load your json.
import fs from 'fs';
const file = fs.readFileSync(`./data/${resource}.json`).toString();
const data = JSON.parse(file);
There may be better ways to write this function, read mode about the fs module here.
Edit: As someone had alredy pointed out, it is actually possible to dynamicallyrequire json file. Here's how,
import path from 'path';
const uri = path.resolve(__dirname, `<path_to_json_file>`);
const data = require(uri);
However, as a standard practice, use the fs module to load static assets to your project.

import fs from 'fs';
const file = fs.readFileSync(`./data/${resource}.json`).toString();
const data = JSON.parse(file);

Related

How can i transpile a jsx file imported dynamically in nodejs?

I am currently working on a nodejs command-line package that should dynamically import a React component basing on the path of the component passed as parameter. My code is the following:
const path = require('path')
const pathArg = process.argv[2]
const componentPath = path.join(filePath, '../../../', pathArg)
const {default} = await import(componentPath)
The component i want to import would be something like
// src/components/Button/index.jsx
function Button () {
return <button>Click me!</button>
}
module.exports = Button
However, when i run my script passing src/components/Button/index.jsx as param, i receive unexpected token "<" while reading <button>, since the file is in jsx.
How can i transpile the React file dynamically (e.g. with Babel) and get rid of the error?

Best practice use of import instead of require with functions and reused variables

What is the best practice of using import instead of require of called functions and reused variables - For example how should these require-lines look like as import?
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
One possible way is to import the required functions and modules and use them in a next step:
import express from 'express';
import {createServer} from 'http';
import socketIo from 'socket.io';
const app = express();
const server = createServer(app);
const io = socketIo(server);
import and require both of them are good to use. But by convention in node almost use require over than import.
If you are very fond of ES6, then you can use import and other es6 features. But one thing should bear in mind that, when you are using es6, it is a good practice to bundle your code with bundeller (like webpack,babel)

Unable to import handlebar file in nodejs

I am unable to import handlebars file in nodejs. Although it is importing the file but not compiling properly with given data.
here is my test.handlebars file code
<div>Hey {{firstname}} {{lastname}}</div>
and this is my index.js file code
const Handlebars = require("handlebars");
const testEmailTemplate = require("./email-templates/test.handlebars")
const template = Handlebars.compile(testEmailTemplate());
console.log(template({ firstname: "Nils", lastname: "Test" }));
And I am getting below output in console
<div>Hey</div>
expected output
<div>Hey Nils Test</div>
Note: - I don't want to use express-handlebar so please suggest some solution only with handlebars.
The require() method expects to get a Node.js module. But in your case, the target file is HTML, and you need to get the content of the file as plain text to use it further. Use for that fs module and it's method fs.readFile() or fs.readFileSync()
The result code should look like:
const fs = require("fs");
const Handlebars = require("handlebars");
const testEmailTemplate = fs.readFileSync("./email-templates/test.handlebars", "utf-8")
const template = Handlebars.compile(testEmailTemplate);
console.log(template({ firstname: "Nils", lastname: "Test" }));
Info: What is require?

Error: Cannot find module, for a third party library in controller.js

I am having controller.js , where I am writing a post request that uses a third party library.
But when I am importing file like
const EmailValidator = require('/email-deep-validator');
I get the error, "Error: Cannot find module".
You need it to be
const EmailValidator = require("./email-deep-validator")
You should omit the dot there only for node modules like
fs = require('fs')

Do not see the reason I am getting a NOENT returned when I can see the file at the exact spot I am calling for it to be

I know this is very similar to other questions that have been asked on the same error. In the case I have seen though, the file name had been left off of the url. In my case (as far as I know) the url is specified as it should be and I can see the file on my localhost using other tools.
I have a need in a node.js app to perform I/O on json files without the benefit of using express routing. This is an API that has only one route (processor.js). It is accessed by a menu selection on the GUI by selecting 'Process'. From that point on everything happens within that route including multiple GETs/PUTs to json (for ids to data and then using the ids to get the data) and the building of SQL rows for populating SQL-Server Tables from the parsed json data. That, at least is the concept I am testing now. It is the hand I have been dealt, so I don't have other options.
I am using fs-extra rather than request or axios etc., because they all seem to expect express routes to accomplish the I/O. I appear to be able to directly read and write the json using fs-extra. I am using sequelize (or will be) for the SQL side.
That's the background.
Here is my processor.js (I am merely validating that I can in fact get idsList returned to me at this point):
'use strict';
// node_modules
const express = require('express');
const router = express.Router();
const fse = require('fs-extra')
// local modules
const idsList = require('../functions/getIds');
router.get('/', (req, res) => {
console.log(idsList);
});
module.exports = router;
Here is my getIds function:
'use strict';
// library modules
const express = require('express');
const router = express.Router();
const fse = require('fs-extra');
const uri = require('../uri');
// initialize general variables
let baseURL = `http://localhost:5000${uri}/`;
let idsID = 'ids.json';
const getIds = async () => {
let url = `${baseURL}${idsID}`;
try {
const idsList = await fse.readJson(url);
console.log('fse.readJson',idsList);
} catch (err) {
console.error(err);
}
}
module.exports = getIds();
And, here is my error, output to the console (it didn't format very well):
Listening on port 5000...
{ [Error: ENOENT: no such file or directory, open
'http://localhost:5000/Users/doug5solas/sandbox/libertyMutual/playground/api/ids.json']
errno: -2,
code: 'ENOENT',
syscall: 'open',
path:
'http://localhost:5000/Users/doug5solas/sandbox/libertyMutual/playground/api/ids.json' }
What am I missing?
You can use fs-extra to manipulate files and directories in your local file system only.
If you want to read files hosted on other machine over http, try using an http client like: axios.
I moved away from fs-extra to fs.readFileSync and solved the problem. It is not my preference. But it does work and the file is small, and only once.

Resources