How to check if a file exist in nuxt - vue.js

I'm on Nuxt 2.15.4 and i wanna check in my store codes if a file exist in nuxt directory by fs-extra package.
it is simple in modules because i can get files path by this code:
const path = require('path')
const fse = require('fs-extra');
const FilePath = path.join(this.options.rootDir, './static/myfile.json')
const fse = require('fs-extra');
fse.pathExists(FilePath, (err, exists) => {
console.log(err) // => null
console.log(exists) // => true
})
but in vuex store i dont have access to this.options.rootDir and this code is always return false:
export const actions = {
async nuxtServerInit({dispatch, commit}) {
if(process.server){
const fse = require('fs-extra');
fse.pathExists('~/static/myfile.json', (err, exists) => {
console.log(err) // => null
console.log(exists) // => false
})
}
}
}
how can i get files fullpath or check if it exits??
#UPDATE
It looks like I had a little mistake in my file path so used ./static/myfile.json and the check is done!!
but got another problem!! I have another json file, when I'm trying to use Object.assign(mainfile, myfile) it won't work!!
here is a sample:
async nuxtServerInit({dispatch, commit}) {
let mainfile = require('../assets/mainfile.json')
// if i use assign here it works and merge them together
// let myfile = require('../assets/myfile.json')
// Object.assign(mainfile, myfile)
if(process.server){
const fse = require('fs-extra');
fse.pathExists('./static/myfile.json', (err, exists) => {
if(exists){
Object.assign(mainfile, myfile)
commit('SET_FILE', mainfile); // this send the unmerged file to mutation
console.log(mainfile); // but get the merged json here
}
})
console.log(mainfile); // it is unmerged
}
console.log(mainfile); // it is unmerged
}

For your updated question, be sure that exists is truthy, that you're entering in the loop and that mainfile is in the format that you're expecting.
Then, you could do
mainfile = {...mainfile, ...myfile} // rather than Object.assign

Ok, thanks to #kissu I found out the problem. As kissu mentioned in his answer's comment, commit is synchronous; I tried await action but didn't get the result; so I used pathExistsSync instead and done!!
async nuxtServerInit({dispatch, commit}) {
let myfile = {}
let mainfile = require('../assets/mainfile.json')
if(process.server){
const fse = require('fs-extra');
if(fse.pathExistsSync('./static/myfile.json')){
myfile = require('../assets/myfile.json')
Object.assign(mainfile, myfile)
}
}
await dispatch('setMyFile', mainfile)
}
#Update
require('../assets/mainfile.json') still throw error if file doesn't exist even with if(fse.pathExistsSync('./static/myfile.json')) statement so:
async nuxtServerInit({dispatch, commit}) {
let myfile = {}
let mainfile = require('../assets/mainfile.json')
if(process.server){
const fse = require('fs-extra');
if(fse.pathExistsSync('./static/myfile.json')){
myfile = readJsonSync('./static/myfile.json')
Object.assign(mainfile, myfile)
}
}
await dispatch('setMyFile', mainfile)
}

Related

How can I specify the name of pdf print for react native project for iOS

I'm using both expo-print and expo-sharing to save file.
const { uri } = await Print.printToFileAsync({html});
await shareAsync(uri, { UTI: ".pdf", mimeType: "application/pdf" });
by default it is using UUID, I want to specify the file eg, abc.pdf, but I don't see the doc has any option to setup the file name.
I found the answer here
import * as Print from 'expo-print'
import * as Sharing from 'expo-sharing'
import * as FileSystem from 'expo-file-system'
const printToPdf = async () => {
const response = await Print.printToFileAsync({
html: createHtmlStringForPdf(),
})
// this changes the bit after the last slash of the uri (the document's name) to "invoice_<date of transaction"
const pdfName = `${response.uri.slice(
0,
response.uri.lastIndexOf('/') + 1
)}invoice_${readableDate.getTime()}.pdf`
await FileSystem.moveAsync({
from: response.uri,
to: pdfName,
})
sharePdf(pdfName)
}
const sharePdf = (url) => {
Sharing.shareAsync(url)
}

handling error trying to set key of immutable and frozen object

i have the following object in a state:
App.js
const data = {name: 'John', status:'employeed' };
const [manager, updateManager] = useState(data);
const updateStatus = async () =>{
await service.setStatus(manager);
}
setStatus does modify the manager directly, which I think is the source of the problem
service.js
setStatus(manager){
manager.status = 'employeed';
}
so I modified the call to send a copy of the manager object and return a new object but still I get the error
you tried to modify 'status' key of an immutable object.
here is my new change
App.js
const updateStatus = async () =>{
const g = await service.setStatus({...manager});
updateManager(g);
}
service.js
setStatus(manager){
manager.status = 'employeed';
return manager;
}
Why has this function to be async?
const updateStatus = async () =>{
await service.setStatus(manager);
}
This return a new/updated object but it won‘t do any permanent changes.
setStatus(manager){
return {…manager,status: 'employeed'};
}
Does the problem after your last changes persists?
You should pass a callback like this:
const updateStatus = (manager) => {
service.setStatus(()=> updateManager({
...manager,
status: 'employeed'
}));
Service.js
setStatus(updateManager){
updateManager(manager);
}

Write files to directory error - Expo FileSystem

I am really struggling to find where I am going wrong with this. I am trying to move the picked (ImagePicker) image from cache to app scope directory folder named images/. I created a directory images/ using FileSystem.makeDirectoryAsync but while trying to move the picked image to this directory I am getting an error. Please can someone help me I am really struggling
Expected Result
The image successfully moves to the images/ directory
Actual Result
[Unhandled promise rejection: Error: File 'file:///var/mobile/Containers/Data/Application/318CFCE4-16DF-44DD-92B3-39DECA61EA14/Library/Caches/ExponentExperienceData/%2540user%252FtestApp/ImagePicker/ECD218AE-3DD3-429F-B1F5-469DA1AC661C.jpg' could not be moved to
'file:///var/mobile/Containers/Data/Application/318CFCE4-16DF-44DD-92B3-39DECA61EA14/Documents/ExponentExperienceData/%2540user%252FtestApp/images/ECD218AE-3DD3-429F-B1F5-469DA1AC661C.jpg/'.]
This is my code:
import React, { useEffect, useState } from "react";
import {Text,View,TouchableOpacity,Alert,} from "react-native";
import * as ImagePicker from "expo-image-picker";
import * as Permissions from "expo-permissions";
import * as FileSystem from "expo-file-system";
const ImageCard = (props) => {
const { handlePickedImage } = props;
const [image, setImage] = useState("");
// Create any app folders that don't already exist
export const checkAndCreateFolder = async folder_path => {
const folder_info = await FileSystem.getInfoAsync(folder_path);
if (!Boolean(folder_info.exists)) {
// Create folder
console.log("checkAndCreateFolder: Making " + folder_path);
try {
await FileSystem.makeDirectoryAsync(folder_path, {
intermediates: true
});
} catch (error) {
// Report folder creation error, include the folder existence before and now
const new_folder_info = await FileSystem.getInfoAsync(folder_path);
const debug = `checkAndCreateFolder: ${
error.message
} old:${JSON.stringify(folder_info)} new:${JSON.stringify(
new_folder_info
)}`;
console.log(debug);
}
}
};
const veryfiyPermissons = async () => {
const result = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (result.status !== "granted") {
Alert.alert(
"Insufficient permissions",
"You need to grant permissions to access Camera Roll",
[{ text: "Okay" }]
);
return false;
}
return true;
};
const selectImageHandler = async () => {
const hasPermisson = await veryfiyPermissons();
if (!hasPermisson) {
return;
}
const image = await ImagePicker.launchImageLibraryAsync({
quality: 0.5,
});
if (image.cancelled) {
randomImage;
} else {
let localUri = image.uri;
let localUriNamePart = localUri.split("/");
const fileName = localUriNamePart[localUriNamePart.length - 1];
const images_folder = `${FileSystem.documentDirectory + 'images/'}`
checkAndCreateFolder(images_folder);
const setTheFile = `${images_folder + `${fileName}/`}`
await FileSystem.moveAsync({
from: localUri,
to: newLocation
}).then((i) => {
setImage(setTheFile);
handlePickedImage(setTheFile);
})
}
};
return (
<View>
<TouchableOpacity onPress={selectImageHandler}>
<Text>Add Photo</Text>
</TouchableOpacity>
</View>
);
};
export default ImageCard;

store sql queries as string in node server to get them as a response(express)

I am trying to do something may or may not be possible.
I have a SQL file called "travel.sql" that I am trying to make an api out of, so I thought the simplest thing to do is to save the queries as strings in an array and then save the array of strings as a response for a node server(express.js)
so simply here's the code till now but this is returning nothing in postman and I don't know what's missing or not
I checked all the packages and they are installed properly
const express = require('express')
const fse = require( "fs-extra" );
const { join } = require( "path" );
const app = express()
const port = 3000
app.get('/sqlfile', (req, res) => {
const loadSqlQueries = async folderName => {
// determine the file path for the folder
const filePath = join( process.cwd(), travel );
// get a list of all the files in the folder
const files = await fse.readdir( filePath );
// only files that have the .sql extension
const sqlFiles = files.filter( f => f.endsWith( ".sql" ) );
// loop over the files and read in their contents
const queries = {};
for ( let i = 0; i < sqlFiles.length; i++ ) {
const query = fse.readFileSync( join( filePath, sqlFiles[ i ] ), { encoding: "UTF-8" } );
queries[ sqlFiles[ i ].replace( ".sql", "" ) ] = query;
console.log(queries)
}
return queries;
res.send(queries);
};
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
I'm not quite sure of what you are trying to achieve, But anyway You have multiple parts of your code need to be enhanced:
As a first proposal I suggest to add a "try and catch" to your code so you can know the errors you are facing.
You are creating a function expression "loadSqlQueries" which I think is not needed and it never runs as you are just creating it but you never used it.
As the function expression is not needed then also the "return" is not needed.
To be able to use "await" like here: const files = await fse.readdir( filePath ); You need to use it inside "async" function.
You are using "travel" here const filePath = join( process.cwd(), travel ); as a variable, you need to use it as a string like this const filePath = join( process.cwd(), "travel" );
I've applied the above mentioned changes, kindly read the comments I added to your code to catch the changes and here is the final code:
const express = require('express')
const fse = require("fs-extra");
const { join } = require("path");
const app = express()
const port = 3000
app.get('/sqlfile',
// add async to be able to use await
async (req, res) => {
// add try and catch block to your code to catch the errors
try {
// no need for the function expression which is never used
// const loadSqlQueries = async folderName => {
// determine the file path for the folder
//use travel as a string not a variable
const filePath = join(process.cwd(), "travel");
// get a list of all the files in the folder
const files = await fse.readdir(filePath);
// only files that have the .sql extension
const sqlFiles = files.filter(f => f.endsWith(".sql"));
// loop over the files and read in their contents
const queries = {};
for (let i = 0; i < sqlFiles.length; i++) {
const query = fse.readFileSync(join(filePath, sqlFiles[i]), { encoding: "UTF-8" });
queries[sqlFiles[i].replace(".sql", "")] = query;
console.log(queries)
}
// As the function expression is not used we will comment return
// return queries;
res.send(queries);
// }
} catch (error) {
console.log(error);
}
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

How to exit a while loop depending of the result of an Axios call?

In order to make sure a user-entered word exists, I need to keep prompting (while loop) for a word until the word API finds the word.
My question is: how can I exit the while loop depending of Axios call result?
Below is my code so far.
const wordApiBaseUrl = 'https://www.dictionaryapi.com/api/v1/references/sd4/xml'
while (true) {
const wordToGuess = prompt('Enter a word:').toLowerCase()
const endPointUrl = `${wordApiBaseUrl}/${wordToGuess}?key=${wordApiKey}`
this.axios.get(endPointUrl).then(res => {
if (res.data.includes('def')) {
break
}
})
}
Try this:
const wordApiBaseUrl = 'https://www.dictionaryapi.com/api/v1/references/sd4/xml'
const vm = this; // <--- assuming this is the Vue instance
const dispatcher = {
execute: function() {
const wordToGuess = prompt('Enter a word:').toLowerCase()
const endPointUrl = `${wordApiBaseUrl}/${wordToGuess}?key=${wordApiKey}`
const dispatcher = this;
vm.axios.get(endPointUrl).then(res => {
if (!res.data.includes('def')) {
dispatcher.execute();
}
})
}
}
dispatcher.execute();
Rather than using a while loop or using an async/await you can use recursion in our promise. If the result is not satisfied, re-run the AJAX call.