I'm working with a MySql database and a web application; I use Firebase Functions (Google Cloud Functions) to retrieve data from tables and send it to the web app. When the record's create_dt and update_dt fields make it to the web application, they're an object that doesn't have any accessible properties.
I'm trying to display the create and update date values in my application, but whenever I try to display one of the values, the web application displays [object Object]. Looking at the object in the console, it looks like an empty object with nothing but prototype properties
I've looked around here and other places on the Internet and found a bunch of articles that show how to manipulate a MySql Timestamp (as a time string) in JavaScript, but none that shows how to actually access the timestamp value.
My goal right now is just to display the time/date value in my app, but ultimately I want to get it as a JavaScript Date object so I can format the output the way I want in my app. Can someone please show me how to do this? I don't get why the timestamp shows up in the browser as an object with no accessible properties.
My function looks like this:
export const get = functions
.runWith({
vpcConnector: 'myapp-connector',
vpcConnectorEgressSettings: 'PRIVATE_RANGES_ONLY'
})
.https.onCall((data, context) => {
// Checking that the user is authenticated.
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(AUTHCODE, AUTHMSG);
}
const idx = data.idx;
if (idx) {
let cmd = `SELECT * FROM companies WHERE id=${idx}`;
return sqlStuff.executeQuery(cmd)
.then(result => {
functions.logger.log('Query result', result);
return { result: result };
}).catch(err => {
functions.logger.log('ERROR', err);
return { err: err };
});
} else {
functions.logger.log('Missing index');
return { result: {} };
}
});
The query code looks like this:
export async function executeQuery(cmd: string) {
const mySQLConfig = {
connectionLimit: 10,
host: functions.config().sql.prodhost,
user: functions.config().sql.produser,
password: functions.config().sql.prodpswd,
database: functions.config().sql.proddatabase,
}
var pool: any;
if (!pool) {
pool = mysql.createPool(mySQLConfig);
}
return new Promise(function (resolve, reject) {
pool.query(cmd, function (error, results) {
if (error) {
return reject(error);
}
resolve(results);
});
});
}
On the client, I'm using AngularFireFunctions since this is an Angular (Ionic) app.
getCompany(idx: number) {
const companyGet = this.fireFunc.httpsCallable('companyGet');
companyGet({ idx }).subscribe(
data => {
if (data.result && data.result.length > 0) {
this.company = Object.assign({}, data.result[0]);
} else {
this.alertController.create({
header: 'Company Lookup',
message: `The specified company record (${idx}) does not exist`,
buttons: ['OK']
}).then(alert => {
alert.present();
this.router.navigate(['/companies']);
});
}
},
err => {
this.alertController.create({
header: 'Company Refresh',
message: `The process reported the following error: ${err.message}`,
buttons: ['OK']
}).then(alert => alert.present());
},
() => {
console.log('CompanyPage: Company request completed');
}
);
});
}
Related
I need to load and interpret Parquet files from an S3 bucket using node.js. I've already tried parquetjs-lite and other npm libraries I could find, but none of them seems to interpret date-time fields correctly. So I'm trying to AWS's own SDK instead, in the believe that is should be able to deserialize its own Parquet format correctly -- the objects were originally written from SageMaker.
The way to go about it, apparently, is to use the JS version of
https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectObjectContent.html
but the documentation for that is horrifically out of date (it's referring to the 2006 API, https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#selectObjectContent-property). Likewise, the example they show in their blog post doesn't work either (data.Payload is neither a ReadableStream not iterable).
I've already tried the response in
Javascript - Read parquet data (with snappy compression) from AWS s3 bucket. Neither of them work: the first uses
node-parquet, which doesn't currently compile, and the second uses parquetjs-lite (which doesn't work, see above).
So my question is, how is SelectObjectContent supposed to work nowadays, i.e., using aws-sdk v3?
import { S3Client, ListBucketsCommand, GetObjectCommand,
SelectObjectContentCommand } from "#aws-sdk/client-s3";
const REGION = "us-west-2";
const s3Client = new S3Client({ region: REGION });
const params = {
Bucket: "my-bucket-name",
Key: "mykey",
ExpressionType: 'SQL',
Expression: 'SELECT created_at FROM S3Object',
InputSerialization: {
Parquet: {}
},
OutputSerialization: {
CSV: {}
}
};
const run = async () => {
try {
const data = await s3Client.send(new SelectObjectContentCommand(params));
console.log("Success", data);
const events = data.Payload;
const eventStream = data.Payload;
// Read events as they are available
eventStream.on('data', (event) => { // <--- This fails
if (event.Records) {
// event.Records.Payload is a buffer containing
// a single record, partial records, or multiple records
process.stdout.write(event.Records.Payload.toString());
} else if (event.Stats) {
console.log(`Processed ${event.Stats.Details.BytesProcessed} bytes`);
} else if (event.End) {
console.log('SelectObjectContent completed');
}
});
// Handle errors encountered during the API call
eventStream.on('error', (err) => {
switch (err.name) {
// Check against specific error codes that need custom handling
}
});
eventStream.on('end', () => {
// Finished receiving events from S3
});
} catch (err) {
console.log("Error", err);
}
};
run();
The console.log shows data.Payload as:
Payload: {
[Symbol(Symbol.asyncIterator)]: [AsyncGeneratorFunction: [Symbol.asyncIterator]]
}
what should I do with that?
I was stuck on this exact same issue for quite some time. It looks like the best option now is to append a promise() to it.
So far, I've made progress using the following (sorry, this is incomplete but should at least enable you to read data):
try {
const s3Data = await s3.selectObjectContent(params3).promise();
// using 'any' here temporarily, but will need to address type issues
const events: any = s3Data.Payload;
for await (const event of events) {
try {
if(event?.Records) {
if (event?.Records?.Payload) {
const record = decodeURIComponent(event.Records.Payload.toString().replace(/\+|\t/g, ' '));
records.push(record);
} else {
console.log('skipped event, payload: ', event?.Records?.Payload);
}
}
else if (event.Stats) {
console.log(`Processed ${event.Stats.Details.BytesProcessed} bytes`);
} else if (event.End) {
console.log('SelectObjectContent completed');
}
}
catch (err) {
if (err instanceof TypeError) {
console.log('error in events: ', err);
throw err;
}
}
}
}
catch (err) {
console.log('error fetching data: ', err);
throw err;
}
console.log("final records: ", records);
return records;
}
I'm adding the claim to a user's profile that he or she paid for something, though, after the payment this attribute isn't visible. I'm running the functions on an emulator on a local host.
This is the code I'm using:
If the paypal function has been handled succesfully through paypalHandleOrder, then the function addPaidClaim is invoked.
onApprove: (data, actions) => {
paypalHandleOrder({ orderId: data.orderID }).then(
addPaidClaim(currentUser).then(
alert("THANKS FOR ORDERING!"),
// currentUser.getIdTokenResult().then(idTokenResult => {
// console.log(idTokenResult.claims)
// })
)
.catch((err) => {
return err;
})
);}
addPaidClaim is a firebase cloud function, which goes as follows:
exports.addPaidClaim = functions.https.onCall((data, context) => {
// get user and add custom claim (paid)
return admin.auth().setCustomUserClaims(data.uid, {
paid: true,
}).then(() => {
return {
message: `Success! ${data.email} has paid the course`,
};
}).catch((err) => {
return err;
});
});
I've refreshed the page and checked the user attributes afterwards through console.log on the user to see if the attribute had been added, but this is not the case. I can't find attribute paid inside the idTokenResult object. What should I do? I also find it hard to make sense of what's happening inside the function addPaidClaim. It's not returning an error when I look at the logs on my firebase console, and not much information is given, besides that the function has been invoked.
Okay, I know this question is pretty old. But I found a way just yesterday after 3 days searching over the solution. After we set up a new claim for a new user using, we need to refresh the client's getIdTokenResult(true) in the app. These are the ways I did it in Flutter Dart until a new user with updated claim managed to use it:
FirebaseAuth auth = FirebaseAuth.instance;
Future<Map<String, dynamic>> signInWithGoogle() async {
Map<String, dynamic> output = {};
final googleUser = await googleSignIn.signIn();
if (googleUser == null) {
log("Firebase => Gmail account doesn't exist");
} else {
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken,
);
await auth.signInWithCredential(credential).then((values) async {
await userAuth(credential).then((value) =>
value.addAll(output));
});
}
return output;
}
Future<Map<String, dynamic> userAuth (OAuthCredential credential) async {
Map<String, dynamic> output = {};
await auth.currentUser!.reauthenticateWithCredential(credential);
await auth.currentUser!.reload();
await auth.currentUser!.getIdTokenResult().then((result) => {
if(result.claims!.isNotEmpty){
//check your claim here
} else {
//assign log here
}
});
return output;
}
needing a guide for how to layout functionality for a React Native app that's pairing with an ESP32 that will eventually feed back weight readings using read Characteristic, and be able to toggle a DI via write to a characteristic.
i can currently scan and connect to the ESP32 and show the values from the ESP32 (random changing values for now) and also toggle the LED via changing a hardcoded value. But i want to be able to do this via a button in the app.
const scanDevices = () => {
//set isLoading to true to show activity Indicator
setIsLoading(true);
//scan for devices, (UUIDs, ScanOptions(error, device))
manager.startDeviceScan(null, null, (error, device) => {
if (error) {
console.log("Error in scanning", error.message)
return;
}
if (device) {
//if a device is scanned, add the name & id details into the scannedDevice object via reducer
dispatch({type: 'DEVICE_ADD', payload: {name: device.name, id: device.id}});
}
});
//end scan after 3 seconds, stop the activity indicator swirly thing
setTimeout(() => {
console.log("Scan timeout after 5 seconds");
manager.stopDeviceScan();
setIsLoading(false);
}, 5000);
};
const deviceConnect = (device) => {
console.log("Connecting to:", device.name, device.id);
setIsConnected(true);
setConnectedDevice(device);
manager.connectToDevice(device.id)
.then((device) => {
console.log("Discovering all services & chars");
return device.discoverAllServicesAndCharacteristics()
}).then((device) => {
// console.log("Write Value inside deviceConnect:", writeValue)
console.log("Device:", device.name, "has been connected.");
return deviceNotifications(device, writeValue);
}).catch((error) => {
console.log("device connect error:", device.name, error)
//JSON.stringify(error)
});
};
const deviceNotifications = async (device, writeValue) => {
const service = "af493e2a-f002-11eb-9a03-0242ac130003";
const characteristicTX = "af49423a-f002-11eb-9a03-0242ac130003";
const characteristicRX = "af49414a-f002-11eb-9a03-0242ac130003";
if (device) {
try {
device.monitorCharacteristicForService(service, characteristicTX, (error, characteristic) => {
if (error) {
console.log(error);
} else {
setCharacteristicValue(() => {
return [{id: uuid.v4(), value: (base64.decode(characteristic.value))}];
})}
});
device.writeCharacteristicWithResponseForService(service, characteristicRX, base64.encode(writeValue));
console.log("Writing to RX:", writeValue);
}
catch (err) {
console.log("deviceNotification catch error:", err);
}
};
}
I'm getting pretty confused trying to sort through the [ble-plx documentation][1] ([github wiki][2])
Currently the only way i can get the LED to turn on/off, is i have the LED toggle section inside the deviceNotifications async function and have to manually change the value that's being encoded and written in the code itself, rather than from the App UI using an useState value.
I tried using the useState toggle off a button (which toggled the value and logged out OK), and then re-calling the deviceConnect function, but the commented out console.log in the .then promise section didn't work past the first one, returning which turned the LED on (writing 'A' to the characteristic).
thanks for any help in advance, i know a lot of these ble-plx questions go unanswered.
//this is at a top level inside the main function
const [writeValue, setWriteValue] = useState('A');
const toggleLED = () => {
if (writeValue == 'B') {
setWriteValue('A');
console.log("Toggling write value:", writeValue);
} else {
setWriteValue('B')
console.log("Toggling write value", writeValue)
};
};
[1]: https://dotintent.github.io/react-native-ble-plx/
[2]: https://github.com/dotintent/react-native-ble-plx/wiki
[3]: https://www.polidea.com/blog/ReactNative_and_Bluetooth_to_An_Other_level/
I'm having a problem with a firebase function, using admin api to read then write to firestore.
See the code below:
I've commented by 2 console logs, which takes between 2-5 minutes to execute. The dataset in firestore is small (only a few records). Any advise on what I'm clearly doing wrong please?
Thanks
(edited as requested with rest of code. This is taken direct from Stripe's github examples)
const processTheOrderApp = express();
processTheOrderApp.post(
'/',
bodyParser.raw({ type: 'application/json' }),
(
request: { headers: { [x: string]: any }; rawBody: any },
response: {
status: (
arg0: number
) => { (): any; new (): any; send: { (arg0: string): any; new (): any } };
json: (arg0: { received: boolean }) => void;
}
) => {
const sig = request.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(request.rawBody, sig, endpointSecret);
} catch (err) {
console.log(err);
return response.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the checkout.session.completed event
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
addPaymentDataToOrder(session); // Here we can proccess the order data after successfull payment
// (e.g. change payment status in Firebase Database and call another function)
}
// Return a response to acknowledge receipt of the event
response.json({ received: true });
}
);
// Exporting our http function
exports.processTheOrder = functions.https.onRequest(processTheOrderApp);
function addPaymentDataToOrder(session: any) {
console.log('adding payment'); ////between this console log
admin
.firestore()
.collection('orders')
.where('paymentSessionId', '==', session.id)
.limit(1)
.get() // getting the order which matches the session id, should be only one so limited to one result
.then((query: any) => {
console.log('found item'); ////and this console log
const thing = query.docs[0];
var orderDoc = thing.data();
thing.ref.update({
checkedOut: true,
payment: session,
});
});
}
It's slow because if a function in the firebase cloud functions is not called/invoked in 2 minutes, it goes into a cold start. Check out this reference.
https://medium.com/#siriwatknp/cold-start-workaround-in-firebase-cloud-functions-8e9db1426bd3
I am trying to write a back-end in NodeJS for a newsreader app. The idea is to check a number of RSS feeds every few minutes, save new items to a database, and emit an event to connected users when a new item is added to the database.
I am having trouble writing a module which saves to the database. The desired behaviour is as follows:
Take the parsed RSS feeds, which are ordered in an array from newest to oldest, as input
For each item, starting with the newest, attempt to save it in the database
If the save was successful, log 'Save successful' to the console and attempt the next item
If the save fails, because the item already exists in the database, stop running the module.
The database model is already configured so the database does reject it when I try to save an item which already exists. However, the code below never logs the successful saves, and if I drop the database, it only saves the first document and then gives me a duplicate key error.
Any idea what I am doing wrong?
// Module
var { mongoose } = require('../db/mongoose');
var { Item } = require('../models/item');
var { scrape } = require('./scrape')
var { parse } = require('./parse')
var updateNewsDatabase = function() {
return new Promise((resolve, reject) => {
console.log('Scraping now')
scrape().then((rssFeeds) => {
var output = parse(rssFeeds);
saveEachNewsItem(output)
.catch((e) => {
console.log('Error:', e);
resolve()
})
})
});
}
async function saveEachNewsItem(newsItems) {
for (let item of newsItems) {
console.log('Attempting to save document')
var itemToSave = new Item(item);
await itemToSave.save()
.then((err, docs) => {
if (docs) {
console.log('Saved document to database')
}
if (err) {
throw new Error(err)
}
});
}
}
module.exports = { updateNewsDatabase }
In this part of your code, you are throwing exception and it makes it stop the for loop.
await itemToSave.save()
.then((err, docs) => {
if (docs) {
console.log('Saved document to database')
}
if (err) {
throw new Error(err)
}
});