Iterate items in array through NodeJS script - javascript

I am trying to find a solution to creating multiple assets in Contentful using the contentful-management API.
The nodeJS script to achieve a single creation of an asset is
const client = contentful.createClient({
accessToken: '<content_management_api_key>'
})
client.getSpace('<space_id>')
.then((space) => space.getEnvironment('<environment-id>'))
.then((environment) => environment.createAssetWithId('<asset_id>', {
title: {
'en-US': 'Example 1'
},
file: {
'en-US': {
contentType: 'image/jpeg',
fileName: 'example1.jpeg',
upload: 'https://example.com/example1.jpg'
}
}
}))
.then((asset) => asset.processForAllLocales())
.then((asset) => asset.publish())
.then((asset) => console.log(asset))
.catch(console.error)
Which is quite simple and easily implemented. However, when wanting to create multiple assets, this does not work.
After many hours looking for a documented way to achieve this, with no avail, I came to
const contentful = require('contentful-management');
const assets = require('./assetObject.js');
async () => {
const client = contentful.createClient({
accessToken: '<content_management_api_key>'
});
const space = await client.getSpace('<space_id>');
const environment = await space.getEnvironment('<environment-id>');
const createdAssets = await Promise.all(
assets.map(
asset =>
new Promise(async () => {
let cmsAsset;
try {
cmsAsset = await environment.createAssetWithId(asset.postId, {
fields: {
title: {
'en-US': asset.title
},
description: {
'en-US': asset.description
},
file: {
'en-US': {
contentType: 'image/jpeg',
fileName: asset.filename,
upload: asset.link
}
}
}
});
} catch (e) {
throw Error(e);
}
try {
await cmsAsset.processForAllLocales();
} catch (e) {
throw Error(e);
}
try {
await cmsAsset.publish();
} catch (e) {
throw Error(e);
}
})
)
);
return createdAssets;
};
assetObject.js
[
{
link: 'https://example.com/example1.jpg',
title: 'Example 1',
description: 'Description of example 1',
postId: '1234567890',
filename: 'example1.jpeg'
}, ... // Many more
]
This, when running, produces no errors, nor does it do anything. What have I done wrong? Is this the method I should use?

A new promise need to be "resolved" and "rejected" so for me the code should look like
const createdAssets = await Promise.all(
assets.map(
asset =>
new Promise(async (resolve, reject) => {
try {
const cmsAsset = await environment.createAssetWithId(asset.postId, {
fields: {
title: {
'en-US': asset.title
},
description: {
'en-US': asset.description
},
file: {
'en-US': {
contentType: 'image/jpeg',
fileName: asset.filename,
upload: asset.link
}
}
}
});
await cmsAsset.processForAllLocales();
await cmsAsset.publish();
resolve(cmsAsset);
} catch (e) {
reject(e);
}
})
)
);
return createdAssets;
Hop it can help

Related

calling an api inside map function In node Js

const processInboundEmailAttachment = async (files: any[]): Promise<any[]> => {
const attachments = []
await Promise.all(
files.map(async (file) => {
try {
let response = null
response = await axios.get(file.url, {
headers: {
Accept: "message/rfc2822"
},
auth: {
username: "api",
password: "api-key"
},
responseType: "stream"
})
if (response && response.data) {
response.data.pipe(concat(async data => {
try {
const mediaUrl = await uploadToFirestore(file["content-type"], data, file.name)
attachments.push({
name: file.name,
url: mediaUrl,
id : uuidv4()
})
} catch (error) {
console.log("err", error);
}
}));
}
} catch (err) {
log.error(err)
}
})
)
return attachments // from here this return initial attachments [] array
}
const uploadAttachment = async () => {
const attachment = await processInboundEmailAttachment(JSON.parse(attach))
console.log("attachment",attachment);
// I want updated pushed attachment array here but I got [] initial decalare value
}
app.get("/uploadAttachment", uploadAttachment)
In attachment console log I got [] array , It's return initial assign values of array.
It's not wait for API response and newly pushed array.
I think There Is an some issue in Promise , It's not wait for updated array , It's
return directly initialy attachment array
Thank you for Help In advnace
Looks like it is not waiting for uploadFirestore response. You can cut down your function something like below and wrap it custom promise.
const processInboundEmailAttachment = async (files: any[]): Promise<any[]> => {
const getFileUploadedResult = function(file) {
return new Promise(async (resolve, reject) => {
try {
let response = null
response = await axios.get(file.url, {
headers: {
Accept: "message/rfc2822"
},
auth: {
username: "api",
password: "api-key"
},
responseType: "stream"
})
if (response && response.data) {
response.data.pipe(concat(async data => {
try {
const mediaUrl = await uploadToFirestore(file["content-type"], data, file.name)
resolve({
name: file.name,
url: mediaUrl,
id : uuidv4()
})
} catch (error) {
reject(err)
}
}));
}
} catch (err) {
log.error(err)
reject(err)
}
})
}
return Promise.all(
files.map(async (file) => {
return getFileUploadedResult(file)
})
)
}
const uploadAttachment = async () => {
const attachment = await processInboundEmailAttachment(JSON.parse(attach))
console.log("attachment",attachment);
// I want updated pushed attachment array here but I got [] initial decalare value
}
app.get("/uploadAttachment", uploadAttachment)

call multiple async functions in sequential order

async function unsubscribeUserHandler() {
const unsubscribe = await fetch("/api/stripe-sessions/cancel-subscription", {
method: "PATCH",
body: JSON.stringify(),
headers: {
"Content-Type": "application/json",
},
});
const data = await unsubscribe.json();
if (!unsubscribe.ok) {
Toast.fire({
icon: "error",
title: `${data.message}`,
});
} else {
Toast.fire({
icon: "success",
title: `${data.message}`,
});
}
}
async function deleteUserHandler() {
const deleteUser = await fetch("/api/user/delete-account", {
method: "DELETE",
body: JSON.stringify(),
headers: {
"Content-Type": "application/json",
},
});
const data = await deleteUser.json();
if (!deleteUser.ok) {
Toast.fire({
icon: "error",
title: `${data.message}`,
});
} else {
Toast.fire({
icon: "success",
title: `${data.message}`,
});
}
}
const deleteAccount = async () => {
try {
await unsubscribeUserHandler();
await deleteUserHandler();
} catch (err) {
console.error('ERROR#####!!!',err);
}
}
const Settings = () => {
return <DeleteAccount onDeleteAccount={deleteAccount} />;
};
As shown here, I want to unsubscribe.. only after the unsub, then run delete handler.
I have issues where It only runs one of the handlers and not the other. Are there other ways to do this?
have tried:
.then(() => deleteUserHandler())
and
.then(deleteUserHandler)
above doesn't make call to /api/user/delete-account,
only to unsubscribe.
This is wrong:
const deleteAccount = () => unsubscribeUserHandler()
.then(deleteUserHandler())
.catch(console.error);
You aren't passing deleteUserhandler to then(), you are immediately calling it and pass the result to then().
To fix, lose the parenthesis:
const deleteAccount = () => unsubscribeUserHandler()
.then(deleteUserHandler)
.catch(console.error);
Or use an arrow function:
const deleteAccount = () => unsubscribeUserHandler()
.then(() => deleteUserHandler())
.catch(console.error);
Or better yet:
const deleteAccount = async () => {
try {
await unsubscribeUserHandler();
await deleteUserHandler();
} catch (err) {
console.error(err);
}
}

S3 Upload Failing Silently in Production

I'm struggling to debug a NextJS API that is working in development (via localhost) but is silently failing in production.
Below, the two console.log statements are not returning, so I suspect that the textToSpeech call is not executing correctly, potentially in time?
I'm not sure how to rectify, happy to debug as directed to resolve this!
const faunadb = require('faunadb')
const secret = process.env.FAUNADB_SECRET_KEY
const q = faunadb.query
const client = new faunadb.Client({ secret })
const TextToSpeechV1 = require('ibm-watson/text-to-speech/v1')
const { IamAuthenticator } = require('ibm-watson/auth')
const AWS = require('aws-sdk')
const { randomUUID } = require('crypto')
import { requireAuth } from '#clerk/nextjs/api'
module.exports = requireAuth(async (req, res) => {
try {
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
})
const textToSpeech = new TextToSpeechV1({
authenticator: new IamAuthenticator({
apikey: process.env.IBM_API_KEY
}),
serviceUrl: process.env.IBM_SERVICE_URL
})
const uuid = randomUUID()
const { echoTitle, chapterTitle, chapterText } = req.body
const synthesizeParams = {
text: chapterText,
accept: 'audio/mp3',
voice: 'en-US_KevinV3Voice'
}
textToSpeech
.synthesize(synthesizeParams)
.then(buffer => {
const s3Params = {
Bucket: 'waveforms/audioform',
Key: `${uuid}.mp3`,
Body: buffer.result,
ContentType: 'audio/mp3',
ACL: 'public-read'
}
console.log(buffer.result)
console.log(s3Params)
s3.upload(s3Params, function (s3Err, data) {
if (s3Err) throw s3Err
console.log(`File uploaded successfully at ${data.Location}`)
})
})
.catch(err => {
console.log('error:', err)
})
const dbs = await client.query(
q.Create(q.Collection('audioform'), {
data: {
title: echoTitle,
published: 2022,
leadAuthor: 'winter',
user: req.session.userId,
authors: 1,
playTime: 83,
chapters: 1,
gpt3Description: '',
likes: 20,
image:
'https://waveforms.s3.us-east-2.amazonaws.com/images/Mars.jpeg',
trackURL: `https://waveforms.s3.us-east-2.amazonaws.com/audioform/${uuid}.mp3`,
albumTracks: [
{
title: chapterTitle,
text: chapterText,
trackURL: `https://waveforms.s3.us-east-2.amazonaws.com/audioform/${uuid}.mp3`
}
]
}
})
)
res.status(200).json(dbs.data)
} catch (e) {
res.status(500).json({ error: e.message })
}
})
Replace the async fragments something like this, assuming they are meant to be executed sequentially.
try {
// code removed here for clarity
const buffer = await textToSpeech.synthesize(synthesizeParams);
const s3Params = {
Bucket: 'waveforms/audioform',
Key: `${uuid}.mp3`,
Body: buffer.result,
ContentType: 'audio/mp3',
ACL: 'public-read'
}
await s3.upload(s3Params).promise();
const dbs = await client.query(...);
res.status(200).json(dbs.data);
} catch (e) {
res.status(500).json({ error: e.message });
}

Using FileTransfer plugin pass data to next request in for loop

I have a image upload Request with a param. I want to send response from 1st request to all next requests inside for loop.
Page.page.ts
//function to take Photos
takePhoto() {
this.camera.takePhoto().then((res: any) => {
res.map((v) => {
this.uploadMedia(v.fullPath, v.fullPath.split('/').pop())
})
})
}
// function to upload Photos
uploadMedia(path, type) {
this.imgLoader = true;
this.camera.uploadFileMedia(path, 'UploadImage', type, this.postId).then((res: any) => {
if (res.status == true) {
this.postId = res.data.post_id; // I want to pass this postId to All other Requests.
this.userImages.push({ img: res.data});
}
})
}
Camera Service .ts
uploadFileMedia(path: string, url: string, fileType: string, post_id): Promise<any> {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'images',
fileName: fileType,
params: {post_id: post_id }
}
return new Promise(resolve => {
fileTransfer.upload(path, url, options).then((data) => {
resolve(res)
}, (err) => {
})
})
}
Solved it by Converting my UploadFileMedia() from Promise to Observable in my camera.service.ts
UploadFileMedia(path: string, url: string, fileType: string, post_id): Observable<any> {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: "images",
fileName: fileType,
chunkedMode: false,
params: { post_id: post_id }
};
return new Observable(result => {
fileTransfer.upload(path, url, options).then((data) => {
let res = JSON.parse(data.response);
result.next(res);
}, err => {
result.error(err);
});
});
}
and inside my page.ts:
takePhoto = async () => {
this.camera.takePhoto().then(async (res: any) => {
for (let v = 0; v < res.length; v++) {
await new Promise((resolve, reject) => {
this.camera.UploadFileMedia(res[v].fullPath, 'UploadImage', res[v].fullPath.split('/').pop(), this.postId).subscribe((res: any) => {
console.log(res);
if (res.status == true) {
this.postId = res.data.post_id;
this.userImages.push({ img: res.data});
resolve(true)
} else {
reject();
}
})
})
}
})
}
Idea taken From:
Another Answer for Same Problem

Realm does not return exception on React native

I'm using Realm Database on React native. In my Model Schema id field is required. When id field is undefined Realm does return an exception and adding data is not done. Why Realm does not return an exception in try catch??
Model Schema:
export default class ServicesModule {
cache = {};
}
ServicesModule.schema = {
name: "ServicesModule",
primaryKey: "id",
properties: {
id: "int",
title: "string?"
}
};
Insert data:
try {
return new Promise((resolve, reject) => {
realm().write(() => {
resolve(realm().create("ServicesModule", {title: 'Test exception'}, true));
});
});
} catch(e) {
console.error(e.message);
}
Probably because your promise does not reject. Try with:
try {
return new Promise((resolve, reject) => {
try{
realm().write(() => {
resolve(realm().create("ServicesModule", {title: 'Test exception'}, true));
});
}catch(error){
reject(error);
}
});
} catch(e) {
console.error(e.message);
}

Categories

Resources