I'm using onUpdate function to retrieve a before state, but before and after are returning the same value:
exports.subscriptionDowngradeHandler = async (change, context) => {
const before = change.before.data().product;
console.log("product before: ", before);
const after = change.after.data().product;
console.log("product after: ", after);
await change.after.ref.set({
before: before.id,
after: after.id
}, { merge: true });
}
Value before.data().product is expected to be the other id, but instead is the actual one as after.data().product
EDIT
index.js is just calling subscriptionDowngradeHandler as a handler for the function:
const authModule = require("./auth");
const admin = require("firebase-admin");
const creditsModule = require("./credits");
const functions = require("firebase-functions");
const subscriptionsModule = require("./subscriptions");
admin.initializeApp();
exports.subscriptionDowngrade =
functions.firestore
.document("/customers/{userId}/subscriptions/{pushId}")
.onUpdate(subscriptionsModule.subscriptionDowngradeHandler);
exports.subspriptionPeriodEnd = functions.firestore
.document("/customers/{userId}/subscriptions/{pushId}")
.onWrite(subscriptionsModule.subscriptionPeriodEndHandler);
subscriptions.js is as follows:
const admin = require("firebase-admin");
exports.subscriptionPeriodEndHandler = async (change, context) => {
const periodEndBefore = change.before.data().current_period_end;
const periodEndAfter = change.after.data().current_period_end;
console.log(periodEndBefore);
console.log(periodEndAfter);
}
exports.subscriptionDowngradeHandler = async (change, context) => {
const before = change.before.data().product;
const after = change.after.data().product;
await change.after.ref.set({
before: before.id,
after: after.id
}, { merge: true });
}
In both functions before and after shows exactly the same data.
Related
I'm totally new to Jest and typescript. my 2nd test case to be honest.
I want in my jest test - when s3.getObject is called in the actual class, it should return the mocked value.
my handler code:
var aws = require("aws-sdk");
var s3 = new aws.S3({apiVersion: '2006-03-01'});
exports.handler = async function (event, context, callback) {
const bucket = 'event.s3.bucket.name';
const filename = 'fileName';
const inputBucketParams = {
Bucket: bucket,
Key: filename,
};
let result;
try {
**//I want the result to be the mocked value in my test case.**
result = await s3.getObject(inputBucketParams).promise();
const fileContent = getFileContents(result.Body.toString("utf-8"));
my test case:
import {getFileContent} from "../../utils/FileContent";
import anything = jasmine.anything;
const lambdaHandler = require('../lambda/myLambda');
const AWSMock = require('aws-sdk-mock');
const AWS = require("aws-sdk");
describe('Test getS3Object', () => {
beforeEach(() => AWSMock.setSDKInstance(AWS));
})
let s3Object = {
"bucket": {
},
"object": {
}
};
let event = {Records: [
{
s3: s3Object --> from above.
}
]
}
var aws = require("aws-sdk");
var s3 = new aws.S3({apiVersion: '2006-03-01'});
describe('my handler test', async function () {
const s3GetObject = AWSMock.mock('S3', 'getObject', getFileContent('fileName.csv'));
const s3mock = jest.fn();
const getObjectMock = jest.fn(() => getFileContent('fileName.csv'));
const params = {
Bucket: 'bucketName',
Key: 'filename'
}
var returnValue = s3mock.mockReturnValue({
Body: getFileContent('fileName.csv')
});
test('s3 getObject response mock', async () => {
//jest.spyOn(s3, "getObject")
const getObjectMockValue = s3.spyOn('S3', 'getObject').mockReturnValue({
Body: getFileContent('fileName.csv')
})
// my handler is called from this, and when it get to s3.getObject, it fails.
const handlerResponse = await lambdaHandler.handler(event, anything(), anything());
});
});
I want in my jest test - when s3.getObject is called in the actual class, it should return the mocked value.
Trying to test "locally" a firebase function with
firebase emulators:start --inspect-functions on http:// 127 .0.0.1:5000.
When debugging it step by step, the snapshot doesn't exist...but it's not. What I can possibly do wrong ?
const BotDetector = require("device-detector-js/dist/parsers/bot");
const fs = require("fs");
const DEBUG_BOT = true;
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
// Main firebase function called on firebase.json rewrites rules
exports.dynamicMetaTagsUpdate = functions.https.onRequest(async (request, response) => {
let html = fs.readFileSync("../web/index.html", "utf8");
const botDetector = new BotDetector();
const userAgent = request.headers["user-agent"].toString();
const bot = botDetector.parse(userAgent);
if (bot || DEBUG_BOT) {
try {
const { postID } = request.query;
const postUrl = 'http://localhost:5000/blog/post?postID=' + postID;
const docRef = db.collection("posts").doc(postID);
const postData = docRef.get().then((snapshot) => {
if (snapshot.exists()) {
const object = {
postUrl: postUrl,```
I am working on lex and I am trying to store user data in DynamoDB while using NodeJS
Here is my code:
'use strict';
const uuidV1 = require('uuid/v1');
const AWS = require('aws-sdk');
const promisify = require('es6-promisify');
const dynamo = new AWS.DynamoDB.DocumentClient();
module.exports.saveBookingToDatabase = function(Arrival_city, Departure_city, Flight_type, Phone_number){
console.log('saveBookingToDatabase');
const item = {};
item.bookingId = uuidV1();
item.arrivalCity = Arrival_city;
item.departureCity = Departure_city;
item.classType = Flight_type;
item.phone = Phone_number;
const params = {
TableName: 'airstallion',
Item: item
};
const putAsync = promisify(dynamo.put, dynamo);
return putAsync(params).then(() => {
console.log(`Saving ticket ${JSON.stringify(item)}`);
return item;
})
.catch(error => {
Promise.reject(error);
});
}
When i run the program is returning the following error
Since aws-sdk library supports promise, its not necessary to use es6-promisify library. Using node.js async/await we shall achieve the same use case.
'use strict';
const uuidV1 = require('uuid/v1');
const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();
module.exports.saveBookingToDatabase = async function(Arrival_city, Departure_city, Flight_type, Phone_number){
console.log('saveBookingToDatabase');
const item = {};
item.bookingId = uuidV1();
item.arrivalCity = Arrival_city;
item.departureCity = Departure_city;
item.classType = Flight_type;
item.phone = Phone_number;
const params = {
TableName: 'airstallion',
Item: item
};
try {
let result = await dynamo.put(params)
console.log(`Saving ticket ${JSON.stringify(item)}`);
return item;
} catch(e) {
throw (e)
}
}
I am trying to run the next code in firebase functions, and it gives an error of not recognizing datasnapshot. what can cause it?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.updateVotes = functions.database.ref('travels/{travelId}/locations/{locationId}/voting/users')
.onUpdate((userVotes, context) => {
var travelId = context.params.travelId;
var locationId = context.params.locationId
var sumVotes = 0;
userVotes.forEach((userVote) => {
sumVotes += userVote.val().userVote;
})
// var votes = userVotes.val();
// for (var vote in votes) {
// if (votes.hasOwnProperty(vote)) {
// sumVotes += votes[vote].userVote;
// }
// }
return admin.database()
.ref('travels/' + travelId + '/locations/' + locationId + '/voting')
.update({ votes: sumVotes })
})
The error is:
TypeError: userVotes.forEach is not a function at exports.updateVotes.functions.database.ref.onUpdate
onUpdate doesn't return a DataSnapshot it returns a Change object.
You need to select the after or before property - do you want the information before the write, or after the write (Usually it's after - this is the new data in Firebase).
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.updateVotes = functions.database.ref('travels/{travelId}/locations/{locationId}/voting/users')
.onUpdate((change, context) => {
var travelId = context.params.travelId;
var locationId = context.params.locationId
var sumVotes = 0;
var userVotes = change.after;
userVotes.forEach((userVote) => {
sumVotes += userVote.val().userVote;
})
return admin.database()
.ref('travels/' + travelId + '/locations/' + locationId + '/voting')
.update({ votes: sumVotes })
})
I am trying to get Stripe server code working using Firestore. I found example server code that uses Firebase RTDB and am having trouble converting this code to use Firestore.
Original Firebase Function code using Real Time Database:
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase);
const stripe = require('stripe')(functions.config().stripe.testkey)
exports.stripeCharge = functions.database
.ref('/payments/{userId}/{paymentId}')
.onWrite(event => {
const payment = event.data.val();
const userId = event.params.userId;
const paymentId = event.params.paymentId;
// checks if payment exists or if it has already been charged
if (!payment || payment.charge) return;
return admin.database()
.ref(`/users/${userId}`)
.once('value')
.then(snapshot => {
return snapshot.val();
})
.then(customer => {
const amount = payment.amount;
const idempotency_key = paymentId; // prevent duplicate charges
const source = payment.token.id;
const currency = 'usd';
const charge = {amount, currency, source};
return stripe.charges.create(charge, { idempotency_key });
})
.then(charge => {
admin.database()
.ref(`/payments/${userId}/${paymentId}/charge`)
.set(charge)
})
});
My attempt to convert this to using Firestore:
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
const stripe = require('stripe')(functions.config().stripe.testkey)
exports.stripeCharge = functions.firestore
.document('/users/{userId}/payments/{paymentId}')
.onWrite(event => {
const payment = event.data
const userId = event.params.userId
const paymentId = event.params.paymentId
// checks if payment exists or if it has already been charged
if (!payment || payment.charge) return
return admin.firestore
.document(`/users/${userId}`)
.get()
.then(snapshot => {
return snapshot
})
.then(customer => {
const amount = payment.amount;
const idempotency_key = paymentId // prevent duplicate charges
const source = payment.token.id
const currency = 'usd'
const description = 'irl Map Fine Print'
const charge = {amount, currency, source}
return stripe.charges.create(charge, { idempotency_key })
})
.then(charge => {
admin.firestore
.fieldValue(`/users/${userId}/payments/${paymentId}/charge`)
.set(charge)
})
})
My version fails with error saying that admin.firestore.document is not a function.
This updated code will work for you! There were several issues with your code: Missing parentheses... incorrect use of fieldValue (though I am not sure how to use this correctly)... 'document' should be 'doc'
But this works:
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
const stripe = require('stripe')(functions.config().stripe.token)
exports.stripeCharge = functions.firestore
.document('/users/{userId}/payments/{paymentId}')
.onWrite(event => {
const payment = event.data.data()
const userId = event.params.userId
const paymentId = event.params.paymentId
// checks if payment exists or if it has already been charged
if (!payment || payment.charge) return
return admin.firestore()
.doc(`/users/${userId}`)
.get()
.then(snapshot => {
return snapshot
})
.then(customer => {
const amount = payment.price * 100 // amount must be in cents
const idempotency_key = paymentId // prevent duplicate charges
const source = payment.token.id
const currency = 'usd'
const description = 'irl Map Fine Print'
const charge = {amount, currency, source}
return stripe.charges.create(charge, { idempotency_key })
})
.then(charge => {
admin.firestore()
.doc(`/users/${userId}/payments/${paymentId}`)
.set({
charge: charge
}, { merge: true })
})
})