am trying to write json data from a file contained in model folder to another file inside data folder and the two folders are contained in server folder. but i keep on getting the error message that there is no such file directory. the code below is inside model/model.ts file and the file i want to write to is in data/databases.json and both are inside server folder. i have tried using the following path ./data/databases.json, ../data/databases.json but still not working. the folder is server/models/model.ts
let Products = require("../data/product.json") // i was able to import from the same file can't write to it using the same path
const fs = require("fs")
const creat = (newInfo:any) => {
return new Promise((resolve,reject)=>{
let id = companyInfo.length+1
let value = {...newInfo,"id":id}
companyInfo.push(value)
fs.writeFileSync('../data/databases.json',JSON.stringify(companyInfo, null, 2))
resolve(value)
})
}
export {creat}
i have another file where i call the above function and the folder path is server/controller/controller.ts and below is the code
import {creat} from "../models/model" // importing the function here
import http, { IncomingMessage, Server, ServerResponse } from "http";
const creatCompanyinfo = async (req:IncomingMessage,res:ServerResponse)=>{
let body =""
req.on("data",(chunk)=>{
body += chunk.toString()
})
req.on("end",async ()=>{
let newInfo = JSON.parse(body)
let result = await creat(newInfo)
res.setHeader("Content-Type","application/json")
res.end(JSON.stringify(result))
})
}
export {creatCompanyinfo}
and finally the last file that handles the routing and the path is server/app.ts.
below is the code
import http, { IncomingMessage, Server, ServerResponse } from "http";
import {creatCompanyinfo} from "./controller/controller" //importing the function here
const server: Server = http.createServer((req: IncomingMessage, res: ServerResponse) => {
if(req.url === "/companies" && req.method==="POST"){
creatCompanyinfo(req,res)
}
}
this is the path to the json file am writting to server/data/databases.json
below is the file structure
`server/`
`controller/controller.ts`
`data/databases.json`
`model/model.ts`
`app.ts`
below is the error message am getting
Server Running at Port 4000.....
node:fs:585
handleErrorFromBinding(ctx);
^
Error: ENOENT: no such file or directory, open './data/databases.json'
at Object.openSync (node:fs:585:3)
at Object.writeFileSync (node:fs:2170:35)
at /Users/dec/Challenges/week-5-task-stanzealot/server/lib/models/model.js:28:12
at new Promise (<anonymous>)
at Object.creat (/Users/dec/Challenges/week-5-task-stanzealot/server/lib/models/model.js:24:12)
at IncomingMessage.<anonymous> (/Users/dec/Challenges/week-5-task-stanzealot/server/lib/controller/controller.js:44:36)
at IncomingMessage.emit (node:events:539:35)
Behavior of relative path in import() is different from relative path in fs methods.
import path is relative to source file, but fs path is relative to working directory.
Try converting your path to an absolute path:
const path = require("path");
const aPath = path.resolve(__dirname, '../data/databases.json')
fs.writeFileSync(aPath ,JSON.stringify(companyInfo, null, 2))
Related
im trying to use google text to speech api . And node js looking for wrong directory.
Error: The file at /home/user/Downloads/service-account-file.json does not exist, or it is not a file. ENOENT: no such file or directory, lstat '/System/Volumes/Data/home/user'
it says your .json not exist in this directory which is correct. But there is nothing that i can provide path for this. Also when i try to move my json to path that error specified. It is still saying same thing.
//and this is my code
const textToSpeech = require('#google-cloud/text-to-speech');
// Import other required libraries
const fs = require('fs');
const util = require('util');
// Creates a client
const client = new textToSpeech.TextToSpeechClient();
async function quickStart() {
// The text to synthesize
const text = 'hello, world!';
// Construct the request
const request = {
input: {text: text},
// Select the language and SSML voice gender (optional)
voice: {languageCode: 'en-US', ssmlGender: 'NEUTRAL'},
// select the type of audio encoding
audioConfig: {audioEncoding: 'MP3'},
};
// Performs the text-to-speech request
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile('/Applications/development/gmvoice/output.mp3', response.audioContent, 'binary',function (err) {
if (err) throw err; console.log('Results Received');
});
console.log('Audio content written to file: output.mp3');
}
quickStart();
I've been working through creating this bot using discord.js and I just can't for the life of me figure out how to use the command and event handler with ESM.
https://discordjs.guide/creating-your-bot/command-handling.html#reading-command-files
https://discordjs.guide/creating-your-bot/event-handling.html#individual-event-files
EDIT:
So I made a few changes to my code.
This is the code in my index.js
import { Client, GatewayIntentBits, Collection } from 'discord.js';
import 'dotenv/config';
import fs from 'fs';
import path from 'path';
import url from 'url';
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
client.commands = new Collection();
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const commandsPath = path.dirname(__dirname, 'commands');
const commandFiles = fs
.readdirSync(commandsPath)
.filter((file) => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.dirname(commandsPath, file);
const { default: command } = await import(filePath);
client.commands.set(command.data.name, command);
}
client.login(process.env.TOKEN);
client.on('ready', () => {
console.log(`${client.user.tag} has logged in!`);
});
This is the code in my deployCommand.js file
import { REST } from '#discordjs/rest';
import { Routes } from 'discord.js';
import 'dotenv/config';
import fs from 'fs';
import path from 'path';
import url from 'url';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const commands = [];
const commandsPath = path.dirname(__dirname, 'commands');
const commandFiles = fs
.readdirSync(commandsPath)
.filter((file) => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.dirname(commandsPath, file);
const { default: command } = await import(filePath);
commands.push(command.data.toJSON());
}
const rest = new REST({ version: '10' }).setToken(process.env.TOKEN);
rest
.put(
Routes.applicationGuildCommands(
process.env.CLIENT_ID,
process.env.GUILD_ID
),
{ body: commands }
)
.then(() => console.log('Successfully registered application commands.'))
.catch(console.error);
I am no longer receiving any errors. However, the problem I am running into is - I don't believe my deployCommand.js code is running at all.
console.log('Successfully registered application commands.'))
This part of the code is not showing up. I only get notified that the bot was logged in.
EDIT 2
I definitely narrowed it down to my use of path.dirname
If I console.log(__dirname); I get the correct path, but whenever I try to search for the commands folder I receive an error.
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in:
file, data are supported by the default ESM loader. On Windows,
absolute paths must be valid file:// URLs. Received protocol 'c:'
I've tried path.join join by itself path.normalize and __dirname + 'commands'
You cannot mix using require() and import.
If you are wanting to use import you will need to edit your code to remove all instances of require and replace it with import statements and edit your package.json to include
{
"type": "module
}
If you're only changing it because VSC is showing this notice - check this answer to disable it.
if you want to use import in node,you must change the value of the typeoption in package.json to module
I am working on a piece where I am basically refactoring existing code. I have two files: index and server. My index is:
const md5File = require('md5-file');
const fs = require('fs');
const path = require('path');
const ignoreStyles = require('ignore-styles');
const register = ignoreStyles.default;
const extensions = ['.gif', '.jpeg', '.jpg', '.png', '.svg'];
...
require('#babel/polyfill');
require('#babel/register')({
ignore: [/\/(build|node_modules)\//],
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-class-properties',
'dynamic-import-node',
'react-loadable/babel'
]
});
// Now that the nonsense is over... load up the server entry point
require('./server');
My server is like:
import path from 'path';
import Loadable from 'react-loadable';
...
const main = async () => {
// tell React Loadable to load all required assets
await Loadable.preloadAll();
process.on('unhandledRejection', err => {
console.error(err);
process.exit(1);
});
const server = fastify(config.fastify);
server.register(require('./routes'), config);
server.register(fastifyStatic, {
root: path.resolve(__dirname, '../build')
});
if (require.main === module) {
// called directly i.e. $ node index.js
const address = await server.listen(config.address);
// start listening - ROCK AND ROLL!
server.log.info(`Server running at: ${address}`);
} else {
// required as a module => executed on aws lambda
module.exports = server;
}
};
main();
The server should run a REST service when executed locally, and export the server instance for the inject method. This way a proxy can attach to it when running under AWS Lambda.
I used the same setup before, multiple times. Only the two pieces were in the same file eg the server was inside the index. A single file version works fine - require.main comparison tells the program how it is running and module.exports exposes the server instance [server] with the needed inject method when running under Lambda and runs the REST service with a direct invocation.
However, since I need to import react-loadable this time, I split the files in two pieces.
Now, I probably need to figure out how the code is running inside index.js as server.js is not being invoked directly then pass it to the server. It is probably not too difficult.
My main problem is that when if I do console.log(require('./server')) from index, it prints {}. While the server instance is created successfully, and the inject() is present; I am somehow unable to export it from the server.js file and import into index.js correctly, and therefore [re-]export it from index.js for the proxy to attach.
Obviously, I am doing something incorrectly. To me, seems that my require does not have the server instance because the instance gets created after the require finished. Since my main() is async, it is plausible.
What is the right way to accomplish this?
First, notice that your main() function in ./server.js is async and you're defining module.exports from within that asynchronous function. Second, you're calling require('./server.js') from ./index.js without waiting for the asynchronous work to finish. Node resolves require()-d modules as a blank object immediately (that's the {} you're getting), and then extends the object when any async or cyclic material becomes available. So that's why you're seeing what you're seeing.
Which solutions will or will not fit your use case will depend on the details of how your AWS/direct invocation is supposed to work. Here's a suggestion:
const md5File = require('md5-file');
const fs = require('fs');
const path = require('path');
const ignoreStyles = require('ignore-styles');
const register = ignoreStyles.default;
const extensions = ['.gif', '.jpeg', '.jpg', '.png', '.svg'];
// ...
require('#babel/polyfill');
require('#babel/register')({
ignore: [/\/(build|node_modules)\//],
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-class-properties',
'dynamic-import-node',
'react-loadable/babel'
]
});
process.env.serverRunLocally = require.main === module;
// Now that the nonsense is over... load up the server entry point
require('./server').then(listen => listen());
import path from 'path';
import Loadable from 'react-loadable';
// ...
const main = async () => {
// tell React Loadable to load all required assets
await Loadable.preloadAll();
process.on('unhandledRejection', err => {
console.error(err);
process.exit(1);
});
const server = fastify(config.fastify);
server.register(require('./routes'), config);
server.register(fastifyStatic, {
root: path.resolve(__dirname, '../build')
});
if (process.env.serverRunLocally) {
// called directly i.e. $ node index.js
return () => {
const address = await server.listen(config.address);
// start listening - ROCK AND ROLL!
server.log.info(`Server running at: ${address}`);
}
} else {
// required as a module => executed on aws lambda
return server;
}
};
module.exports = main();
I have a distributed system and all JS files are exposed through HTTP. So a normal module would look like this:
http://example.com/path/to/main.js
import * as core from 'http://local.example.com/path/to/core.js';
import * as redux from 'http://cdn.example.com/redux.js#version';
// code
export default {
...
}
So each import will be using either a local resource to the system or possibly remotely available resources using CDN.
Thought when I run webpack, I get this error:
trying to parse a local generated file with such content:
import * as main from 'http://example.com/path/to/main.js';
ERROR in ./src/index.js Module not found: Error: Can't resolve
'http://example.com/path/to/main.js' in '/home/.../index.js'
Is it possible to tell webpack to fetch the urls and include them inside the bundle... While packaging cdn urls isn't a big deal for now, I'd be happy if I could simply ignore the ones with a certain url.
Thought being able to bundle remote all the http:// located files would be a good start.
Also, any remote resource linking to other resources should recursively load remotely linked resources too.
Here's my current webpack config (thought nothing much to see here):
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
]
},
};
Edit: after reading a bit, I started writing a resolver but now I'm stuck again:
const path = require('path');
const fetch = require('node-fetch');
const url = require('url')
const fs = require('promise-fs');
const sha1 = require('sha1')
class CustomResolver {
async download_save(request, resolveContext) {
console.log(request, resolveContext)
var target = url.parse(request.request)
var response = await fetch(request.request)
var content = await response.text()
try {
await fs.stat('_remote')
} catch(exc) {
await fs.mkdir('_remote')
}
var filename = `${sha1(request.request)}.js`
var file_path = `_remote/${filename}`
await fs.writeFile(file_path, content)
var abs_path = path.resolve(file_path)
var url_path = `${target.protocol}://${target.hostname}/`
var obj = {
path: abs_path,
request: request.request,
query: '',
}
console.log(`${request.request} saved to ${abs_path}`)
return obj
}
apply(resolver) {
var self = this
const target = resolver.ensureHook("resolved")
resolver.getHook("module")
.tapAsync("FetchResolverPlugin", (request, resolveContext, callback) => {
self.download_save(request, resolveContext)
.then((obj) => resolver.doResolve(target, obj, resolveContext, callback))
.catch((err) => {
console.log(err)
callback()
})
})
}
}
It does currently fetch urls starting with https:// but seems to be struggling to resolve urls relative to an http resource. For example
ERROR in _remote/88f978ae6c4a58e98a0a39996416d923ef9ca531.js
Module not found: Error: Can't resolve '/-/#pika/polyfill#v0.0.3/dist=es2017/polyfill.js' in '_remote/'
# _remote/88f978ae6c4a58e98a0a39996416d923ef9ca531.js 25:0-58
# _remote/f80b922b2dd42bdfaaba4e9f4fc3c84b9cc04fca.js
# ./src/index.js
It doesn't look like it tries to resolve relative path to already resolved files. Is there a way to tell the resolver to try to resolve everything?
Main point is: if you have CDN files - you don't need a bundler.
They already minified and ready to use. Just import files in root of your project and call libraries globally.
I have create react app code base in which i would like to be able to iterate over a nested structure of data to import one specific file.
I have the following structure:
root.js
-modules
-- mod1
--- index.js
-- mod2
--- index.js
In root.js I would like to go over every module in modules to import index.js so that the initialization data will be run at the start of the application. Its unclear to me what is the best way to do this preferably without using any plugins if there is a solution.
In my opinion, you should include them "manually"
// root.js
require('mod1.index')
require('mod2.index')
// ...
It's more clear and direct. Unless you have 100+ modules
EDIT for dynamic import:
No dependancies proposal (variation of https://gist.github.com/kethinov/6658166#gistcomment-1603591)
'use strict'
const fs = require('fs')
const walkSync = function (dir, filelist) {
const files = fs.readdirSync(dir)
filelist = filelist || []
files.forEach(function (file) {
if (fs.statSync(dir + '/' + file).isDirectory()) {
filelist = walkSync(dir + '/' + file, filelist)
} else {
filelist.push(dir + '/' + file)
}
})
return filelist
}
allFiles = walkSync('./src')
allFiles.filter(f => f.split('/').pop() == 'index.js').forEach(f => require(f))
One dependacie proposal: Get all files recursively in directories NodejS
Turns out this was simple:
Export everything in a modules.js files.
const req = require.context('./', true, /^\.\/[a-zA-Z0-9]+\/index.js$/);
const modules = req.keys().map(req);
module.exports = modules;
Then import the modules.js file in some root.js file.