Firebase: TypeError: Cannot read property 'getApplicationDefault' of undefined (Cloud ML Engine) - firebase

I am new to Firebase, and am testing a Google ML Engine model which I recently deployed. I was trying to follow instructions from this repo: https://github.com/sararob/tswift-detection and was able to deploy the firebase solution as recommended. But when I run the function on Firebase (I upload an image to images folder in Firebase storage), I get an error which states:
Error occurred: TypeError: Cannot read property 'getApplicationDefault' of undefined
at Promise (/user_code/index.js:24:20)
at cmlePredict (/user_code/index.js:23:12)
at file.download.then.then.then (/user_code/index.js:110:20)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
Here is the firebase function for reference:
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });
'use strict';
const functions = require('firebase-functions');
const gcs = require('#google-cloud/storage');
const admin = require('firebase-admin');
const exec = require('child_process').exec;
const path = require('path');
const fs = require('fs');
const google = require('googleapis');
const sizeOf = require('image-size');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
function cmlePredict(b64img) {
return new Promise((resolve, reject) => {
google.auth.getApplicationDefault(function (err, authClient) {
if (err) {
reject(err);
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/cloud-platform'
]);
}
var ml = google.ml({
version: 'v1'
});
const params = {
auth: authClient,
name: 'projects/xx/models/xx',
resource: {
instances: [
{
"inputs": {
"b64": b64img
}
}
]
}
};
ml.projects.predict(params, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
});
}
function resizeImg(filepath) {
return new Promise((resolve, reject) => {
exec(`convert ${filepath} -resize 600x ${filepath}`, (err) => {
if (err) {
console.error('Failed to resize image', err);
reject(err);
} else {
console.log('resized image successfully');
resolve(filepath);
}
});
});
}
exports.runPrediction = functions.storage.object().onChange((event) => {
fs.rmdir('./tmp/', (err) => {
if (err) {
console.log('error deleting tmp/ dir');
}
});
const object = event.data;
const fileBucket = object.bucket;
const filePath = object.name;
const bucket = gcs().bucket(fileBucket);
const fileName = path.basename(filePath);
const file = bucket.file(filePath);
if (filePath.startsWith('images/')) {
const destination = '/tmp/' + fileName;
console.log('got a new image', filePath);
return file.download({
destination: destination
}).then(() => {
if(sizeOf(destination).width > 600) {
console.log('scaling image down...');
return resizeImg(destination);
} else {
return destination;
}
}).then(() => {
console.log('base64 encoding image...');
let bitmap = fs.readFileSync(destination);
return new Buffer(bitmap).toString('base64');
}).then((b64string) => {
console.log('sending image to CMLE...');
return cmlePredict(b64string);
}).then((result) => {
let boxes = result.predictions[0].detection_boxes;
let scores = result.predictions[0].detection_scores;
console.log('got prediction with confidence: ',scores[0]);
// Only output predictions with confidence > 70%
if (scores[0] >= 0.7) {
let dimensions = sizeOf(destination);
let box = boxes[0];
let x0 = box[1] * dimensions.width;
let y0 = box[0] * dimensions.height;
let x1 = box[3] * dimensions.width;
let y1 = box[2] * dimensions.height;
// Draw a box on the image around the predicted bounding box
return new Promise((resolve, reject) => {
console.log(destination);
exec(`convert ${destination} -stroke "#39ff14" -strokewidth 10 -fill none -draw "rectangle ${x0},${y0},${x1},${y1}" ${destination}`, (err) => {
if (err) {
console.error('Failed to draw rect.', err);
reject(err);
} else {
console.log('drew the rect');
bucket.upload(destination, {destination: 'test2.jpg'})
resolve(scores[0]);
}
});
});
} else {
return scores[0];
}
})
.then((confidence) => {
let outlinedImgPath = '';
let imageRef = db.collection('predicted_images').doc(filePath.slice(7));
if (confidence > 0.7) {
outlinedImgPath = `outlined_img/${filePath.slice(7)}`;
imageRef.set({
image_path: outlinedImgPath,
confidence: confidence
});
return bucket.upload(destination, {destination: outlinedImgPath});
} else {
imageRef.set({
image_path: outlinedImgPath,
confidence: confidence
});
console.log('No tswift found');
return confidence;
}
})
.catch(err => {
console.log('Error occurred: ',err);
});
} else {
return 'not a new image';
}
});
These are the libraries I am using:
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase experimental:functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"firebase-admin": "5.8.1",
"firebase-functions": "0.8.1",
"googleapis": "^27.0.0",
"image-size": "^0.6.1",
"#google-cloud/storage": "^1.5.1"
},
"devDependencies": {
"eslint": "^4.12.0",
"eslint-plugin-promise": "^3.6.0"
},
"private": true
}
While deploying, I received this warning:
24:43 warning Unexpected function expression prefer-arrow-callback

I just struggled through this too. I seemed to get it working by using the firebase admin instead:
const credential = admin.credential.applicationDefault();

Related

Apollo Client is not working with NextJS using SSR

I'm trying to use Apollo Client/Server for my NextJS, and some pages I'm trying to SSR and staticlly generate them, but I'm faing an issue with Apollo where it fails to fetch on server but not when I use the client on the client.
Firstlly this is my package json, where my libs are configed:
{
"name": "landing",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev -p 9999",
"build": "next build",
"start": "next start -p 9999",
"lint": "next lint"
},
"dependencies": {
"#apollo/react-hooks": "^4.0.0",
"#reduxjs/toolkit": "^1.9.0",
"apollo-server-micro": "2.25.1",
"deepmerge": "^4.2.2",
"firebase": "^9.14.0",
"graphql": "^15.5.1",
"loadash": "^1.0.0",
"luxon": "^3.1.1",
"mongoose": "^5.13.15",
"next": "11.0.1",
"next-redux-wrapper": "^8.0.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-images-uploading": "^3.1.7",
"react-infinite-scroll-component": "^6.1.0",
"react-redux": "^8.0.5",
"react-tag-input-component": "^2.0.2",
"uuid": "^9.0.0"
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"eslint": "7.32.0",
"eslint-config-next": "11.0.1",
"postcss": "^8.4.19"
}
}
And here is my single API route in pages/api.jsx folder:
import { Connect } from "../utils/Connect";
import { ApolloServer, makeExecutableSchema } from "apollo-server-micro";
import { defs as typeDefs } from "../graphql/defs";
import { resolves as resolvers } from "../graphql/resolves";
Connect();
export const schema = makeExecutableSchema({ typeDefs, resolvers });
const api = { bodyParser: false };
const path = { path: "/api" };
export const config = { api };
export default new ApolloServer({ schema }).createHandler(path);
While this is my Mongo Connection that I imported earlier:
import mongoose from "mongoose";
export const Connect = async () => {
try {
await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
});
} catch (err) {
console.log(`Something went wrong trying to connect to the database);
process.exit(1);
}
};
While this is my Apollo Client which is configured for Client and Server calls:
import merge from "deepmerge";
import { useMemo } from "react";
import { ApolloClient, HttpLink, InMemoryCache, from } from "#apollo/client";
import { onError } from "#apollo/client/link/error";
import { concatPagination } from "#apollo/client/utilities";
import { isEqual } from "lodash";
export const APOLLO_STATE_PROP_NAME = "__APOLLO_STATE__";
let apolloClient;
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) graphQLErrors.forEach(({ message, locations, path }) => {
const msg = `[GraphQL error]: Message: ${message}`;
const lct = `Location: ${locations}`;
const pth = `Path: ${path}`;
console.log(`${msg}, ${lct}, ${pth}`);
});
if (networkError) {
const ntw = `[Network error]: ${networkError}`;
console.log(ntw);
}
});
const httpLink = new HttpLink({
uri: `http://localhost:9999/api`,
credentials: "same-origin",
});
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: from([errorLink, httpLink]),
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
allPosts: concatPagination(),
},
},
},
}),
});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
if (initialState) {
const existingCache = _apolloClient.extract();
const data = merge(existingCache, initialState, {
arrayMerge: (destinationArray, sourceArray) => [
...sourceArray,
...destinationArray.filter((d) =>
sourceArray.every((s) => !isEqual(d, s))
),
],
});
_apolloClient.cache.restore(data);
}
if (typeof window === "undefined") return _apolloClient;
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
export function addApolloState(client, pageProps) {
if (pageProps?.props) pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
return pageProps;
}
export function useApollo(pageProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME];
const store = useMemo(() => initializeApollo(state), [state]);
return store;
}
And lately, this is my page that is SSR-ing:
import { Category } from "../../ui/pages";
import { addApolloState, initializeApollo } from "../../config/Apollo";
import { Description, Globals, Title } from "../../config/Metas";
import { CATEGORIES, CATEGORY } from "../../graphql/queries";
export async function getStaticPaths() {
let paths = [];
const Apollo = initializeApollo();
const config = { query: CATEGORIES };
const categories = await Apollo.query(config);
paths = categories.data.Categories.map((category) => {
return {
params: {
category: category.Name.toLowerCase(),
...category,
},
};
});
return {
paths,
fallback: false,
};
}
export async function getStaticProps(context) {
const Apollo = initializeApollo();
const slug = context.params.category;
const category = await Apollo.query({
query: CATEGORY,
variables: { slug },
});
if (category) {
const data = { props: { category } };
return addApolloState(Apollo, data);
}
else return {
notFound: true,
};
}
const Route = ({ category }) => {
const { data } = category;
const { Category: Meta } = data;
return (
<>
<Globals />
<Title title={Meta.Name} />
<Description description={Meta.Description} />
<Category />
</>
);
};
export default Route;
All those queries that I call are being tested on the Apollo client on front and they are working, but when I do this and start the server with npm run dev I get a weird error:
[Network error]: TypeError: fetch failed
Error [ApolloError]: fetch failed
at new ApolloError (/Users/bfzli/Code/landdding/node_modules/#apollo/client/errors/errors.cjs:34:28)
at /Users/bf/Code/landing/node_modules/#apollo/client/core/core.cjs:1800:19
at both (/Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:997:53)
at /Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:990:72
at new Promise (<anonymous>)
at Object.then (/Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:990:24)
at Object.error (/Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:998:49)
at notifySubscription (/Users/bf/Code/landing/node_modules/zen-observable/lib/Observable.js:140:18)
at onNotify (/Users/bf/Code/landing/node_modules/zen-observable/lib/Observable.js:179:3)
at SubscriptionObserver.error (/Users/bf/Code/landing/node_modules/zen-observable/lib/Observable.js:240:7) {
type: 'ApolloError',
graphQLErrors: [],
clientErrors: [],
networkError: {
cause: {
errno: -61,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '::1',
port: 9999
}
}
}

RTK Query - update all injectedEndpoints cache with one WebSocket connection (Best Practice)

I am new to RTK query and need only one WebSocket connection for my entire application as you can see below I implemented it like an example in GitHub.
I need to somehow send my payload to this WebSocket by subscribing to it.
and then whenever the message comes in I update the other injected Endpoints' cache.
import { ApiSlice } from 'api';
import { instrumentsAdapter } from './marketSlice';
const socket = new WebSocket(process.env.REACT_APP_SOCKET_BASE_URL);
const socketConnected = new Promise((resolve, reject) => {
// Connection opened
try {
socket.addEventListener('open', (event) => {
resolve(event);
});
} catch (err) {
console.log('err', err);
reject(err);
}
});
export const socketApi = ApiSlice.injectEndpoints({
endpoints: (builder) => ({
socketChannel: builder.mutation({
async queryFn(arg) {
await socketConnected;
const { type, topic } = arg;
const sendPayload = { type, path: topic };
socket.send(JSON.stringify(sendPayload));
return { data: { messages: [] } };
},
async onCacheEntryAdded(arg, { cacheDataLoaded, cacheEntryRemoved }) {
console.log('arg', arg);
await cacheDataLoaded;
// Listen for messages
socket.onmessage = (res) => {
const message = JSON.parse(res.data);
try {
// ApiSlice.util.updateQueryData('getInstrumentByRefId', arg, (draft) => {
// console.log('arg', arg);
// draft = { ...message.value, baseVolume: 3 };
// });
} catch (err) {
console.log('err', err);
}
};
await cacheEntryRemoved;
socket.close();
}
})
})
});
export const { useSocketChannelMutation } = socketApi;
after so much reading docs and researching I finally find this solution working but I do not know if this is a best practice or not.
Here is my not-empty ApiSlice.
/* eslint-disable import/prefer-default-export */
// Or from '#reduxjs/toolkit/query' if not using the auto-generated hooks
import { createApi } from '#reduxjs/toolkit/query/react';
import axiosBaseQuery from './axiosBaseQuery';
export const socket = new WebSocket(process.env.REACT_APP_SOCKET_BASE_URL);
const socketConnected = new Promise((resolve, reject) => {
try {
socket.addEventListener('open', (event) => {
resolve(event);
});
} catch (err) {
reject(err);
}
});
// initialize an empty api service that we'll inject endpoints into later as needed
export const ApiSlice = createApi({
reducerPath: 'api',
baseQuery: axiosBaseQuery(),
endpoints: (builder) => ({
subscribeSocket: builder.mutation({
async queryFn(arg) {
await socketConnected;
const sendPayload = { type: 'SUBSCRIBE', path: arg };
socket.send(JSON.stringify(sendPayload));
return { data: { messages: [] } };
}
}),
unsubscribeSocket: builder.mutation({
async queryFn(arg) {
await socketConnected;
const sendPayload = { type: 'UNSUBSCRIBE', path: arg };
socket.send(JSON.stringify(sendPayload));
return { data: { messages: [] } };
}
}),
channel: builder.mutation({
async queryFn(onMessage) {
await socketConnected;
socket.addEventListener('message', onMessage);
return { data: { messages: [] } };
}
})
})
});
export const { useUnsubscribeSocketMutation, useSubscribeSocketMutation, useChannelMutation } =
ApiSlice;
and this is my enhanced Api slice
import { createEntityAdapter } from '#reduxjs/toolkit';
import { ApiSlice } from 'api';
export const instrumentsAdapter = createEntityAdapter({
selectId: (item) => item?.state?.symbol
});
export const marketApi = ApiSlice.injectEndpoints({
overrideExisting: false,
endpoints: (builder) => ({
getMarketMap: builder.query({
query: (type) => ({
url: `/market/map?type=${type}`,
method: 'get'
})
}),
getInstruments: builder.query({
query: (type) => ({
url: `/market/instruments?type=${type}`,
method: 'get'
})
}),
getInstrumentByRefId: builder.query({
query: (refId) => ({
url: `/market/instruments/${refId}/summary`,
method: 'get'
}),
transformResponse: (res) => {
return instrumentsAdapter.addOne(instrumentsAdapter.getInitialState(), res);
},
async onCacheEntryAdded(
arg,
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved, dispatch }
) {
await cacheDataLoaded;
const payload = `instruments.${arg}.summary`;
// subs to socket
dispatch(ApiSlice.endpoints.subscribeSocket.initiate(payload));
// Listen for messages
const onMessage = (res) => {
const message = JSON.parse(res.data);
try {
updateCachedData((draft) => {
instrumentsAdapter.setOne(draft, message.value);
});
} catch (err) {
// eslint-disable-next-line no-console
console.log('err', err);
}
};
dispatch(ApiSlice.endpoints.channel.initiate(onMessage));
await cacheEntryRemoved;
// unsubs to socket
dispatch(ApiSlice.endpoints.unsubscribeSocket.initiate(payload));
}
}),
getCandles: builder.query({
query: ({ refId, bucket, end, limit = 1 }) => ({
url: `/market/instruments/${refId}/candles?bucket=${bucket}&end=${end}&limit=${limit}`,
method: 'get'
})
})
})
});
export const {
useGetMarketMapQuery,
useGetInstrumentByRefIdQuery,
useGetInstrumentsQuery,
useGetCandlesQuery
} = marketApi;
and I try to dispatch my socket endpoints from ApiSlice inside of onCacheEntryAdded.
async onCacheEntryAdded(
arg,
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved, dispatch }
) {
await cacheDataLoaded;
const payload = `instruments.${arg}.summary`;
// subs to socket
dispatch(ApiSlice.endpoints.subscribeSocket.initiate(payload));
// Listen for messages
const onMessage = (res) => {
const message = JSON.parse(res.data);
try {
updateCachedData((draft) => {
instrumentsAdapter.setOne(draft, message.value);
});
} catch (err) {
// eslint-disable-next-line no-console
console.log('err', err);
}
};
dispatch(ApiSlice.endpoints.channel.initiate(onMessage));
await cacheEntryRemoved;
// unsubs to socket
dispatch(ApiSlice.endpoints.unsubscribeSocket.initiate(payload));
}
}),
```

Problem Using Stripe Payment In React Native App

I am using stripe in React Native App not expo and using .Net Core web api as a backend,
this is my backend code where, stripe customers creates and their ephemeral keys and setup_intent
public Customer create_customer()
{
StripeConfiguration.ApiKey =_appSettings.StripeApiSecret;
var options = new CustomerCreateOptions
{
Description = "My First Test Customer",
};
var service = new CustomerService();
return service.Create(options);
}
public EphemeralKey create_empherical_key(string customerId)
{
var options = new EphemeralKeyCreateOptions
{
StripeVersion = "2020-08-27",
Customer = customerId
};
var service = new EphemeralKeyService();
return service.Create(options);
}
public SetupIntent setup_intent(string customerId)
{
var options = new SetupIntentCreateOptions
{
Customer = customerId
};
var service = new SetupIntentService();
return service.Create(options);
}
my backend is working fine it creates all the values that stripe needs,
main problem is lying here in React Native app
function CheckoutScreen() {
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const [loading, setLoading] = useState(false);
const fetchPaymentSheetParams = async () => {
const response = await fetch(`${ environment.stripeurl +`create_customer`}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
const { setupIntent, ephemeralKey, customer } = await response.json();
return {
setupIntent,
ephemeralKey,
customer,
};
};
const initializePaymentSheet = async () => {
const {
setupIntent,
ephemeralKey,
customer,
} = await fetchPaymentSheetParams();
const { error } = await initPaymentSheet({
customerId: customer.id,
customerEphemeralKeySecret: ephemeralKey.secret,
setupIntentClientSecret: setupIntent.clientSecret,
});
if (!error) {
setLoading(true);
}
};
const openPaymentSheet = async () => {
const { error } = await presentPaymentSheet();
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else {
Alert.alert('Success', 'Your payment method is successfully set up for future payments!');
}
};
useEffect(() => {
initializePaymentSheet();
}, []);
return (
<View>
<Button
variant="primary"
disabled={!loading}
title="Set up"
onPress={openPaymentSheet}
/>
</View>
);
I receiving all the values of customer, setupintent and ephemeralkey in the front end, when it reach on the line
const { error } = await presentPaymentSheet();
the app crashes.
for refrence I am also providing link of the documentation.
https://stripe.com/docs/payments/save-and-reuse?platform=react-native&ui=payment-sheet
And these are the packages version that I am currently using in this react-native app.
{
"name": "Tookan_App",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"#stripe/stripe-react-native": "^0.12.0",
"react": "17.0.2",
"react-native": "0.68.2"
},
"devDependencies": {
"#babel/core": "^7.18.2",
"#babel/runtime": "^7.18.3",
"#react-native-community/eslint-config": "^3.0.2",
"babel-jest": "^28.1.0",
"eslint": "^8.16.0",
"jest": "^28.1.0",
"metro-react-native-babel-preset": "^0.71.0",
"react-test-renderer": "17.0.2"
},
"jest": {
"preset": "react-native"
}
}

NextJS Build error: package.json does not exist at /package.json

I have been working on a NextJS application that utilizes Firebase. I have everything set up and on build I get the following error: package.json does not exist at /package.json (see the image)
build error
To give more context on this:
NextJS v^9.3.0
Firebase v^7.10.0
Target: server (by default)
My next.config.js:
const path = require('path')
const resolve = require('resolve')
const withCSS = require('#zeit/next-css')
const withImages = require('next-images')
const withFonts = require('next-fonts')
const withTM = require('next-transpile-modules')([
'*************',
'*************',
'*************'
]);
if (typeof require !== "undefined") {
require.extensions[".less"] = () => {};
require.extensions[".css"] = (file) => {};
}
module.exports =
withCSS(
withImages(
withFonts(
withTM({
webpack: (config, options) => {
config.module.rules.push({
test: /\.svg$/,
use: ['#svgr/webpack'],
});
const { dir, isServer } = options
config.externals = []
if (isServer) {
config.externals.push((context, request, callback) => {
resolve(request, { basedir: dir, preserveSymlinks: true }, (err, res) => {
if (err) {
return callback()
}
if (
res.match(/node_modules[/\\].*\.css/)
&& !res.match(/node_modules[/\\]webpack/)
&& !res.match(/node_modules[/\\]#aws-amplify/)
) {
return callback(null, `commonjs ${request}`)
}
callback()
})
})
}
return config;
},
cssLoaderOptions: {
url: false
}
})
)
)
)
I have been trying many solutions, including the following:
- I should use target server, but I have also tried with "experimental-serverless-trace" but no effect, same error persists
- Tried also "webpack-asset-relocator-loader" but it doesn't work as well. When utilized, I get the following error: "gRPC binary module was not installed".
To be honest, at this point I do not have any idea where to go from this point.
Thanks!

Firebase Cloud Function connection error when bucket.upload()

When I try to upload the generated PDF file to storage bucket, the firebase logs gives me that response after log "Init upload of file...":
Function execution took 3721 ms, finished with status: 'connection
error'
Maybe the problem can be the order of Promises. But I'm beginner with Cloud Functions and Node.js to reorder that.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const pdf = require('html-pdf');
const gcs = require('#google-cloud/storage')({keyFilename: './service_account.json'});
const handlebars = require('handlebars');
const path = require('path');
const os = require('os');
const fs = require('fs');
const bucket = gcs.bucket(bucketURL);
admin.initializeApp(functions.config().firebase);
var html = null;
exports.generatePdf = functions.https.onRequest((request, response) => {
// data to apply to template file
const user = {
"date": new Date().toISOString(),
"title": "Voucher",
"body": "Voucher body"
};
const options = {
"format": 'A4',
"orientation": "portrait"
};
const localPDFFile = path.join(os.tmpdir(), 'localPDFFile.pdf');
try {
const source = fs.readFileSync(__dirname + '/voucher.html', 'utf8');
html = handlebars.compile(source)(user);
} catch (error) {
console.error(error);
}
const phantomJsCloud = require("phantomjscloud");
const browser = new phantomJsCloud.BrowserApi(phantomApiKey);
var pageRequest = { content: html, renderType: "pdf" };
// // Send our HTML to PhantomJS to convert to PDF
return browser.requestSingle(pageRequest)
.then(function (userResponse) {
if (userResponse.statusCode !== 200) {
console.log("invalid status code" + userResponse.statusCode);
} else {
console.log('Successfully generated PDF');
// Save the PDF locally
fs.writeFile(localPDFFile, userResponse.content.data, {
encoding: userResponse.content.encoding,
}, function (err) {
console.log('Init upload of file...' + localPDFFile);
// Upload the file to our cloud bucket
return bucket.upload(localPDFFile, {
destination: '/pdfs/voucher.pdf',
metadata: {
contentType: 'application/pdf'
}
}).then(() => {
console.log('bucket upload complete: ' + localPDFFile);
response.status(200).send({
message: 'PDF Gerado com sucesso!',
address: localPDFFile
});
return true;
}).catch(error => {
response.status(400).send({
message: 'Error on bucket upload!',
error: error
});
return false;
});
});
return true;
}
return true;
});
})

Resources