Using promises with PDFMake on Firebase Cloud Functions
Asked Answered
I

2

7

I am using PDFMake (a variant of PDFKit) to generate PDFs on Firebase Cloud Functions using a realtime database trigger. The function gets all relevant data from the database and then passes it to the function that is supposed to generate the PDF.

All this is done using Promises. Everything works fine until the point where the PDF is actually generated.

Here's the code in my main event listener:

exports.handler = (admin, event, storage) => {
  const quotationData = event.data.val();
  // We must return a Promise when performing async tasks inside Functions
  // Eg: Writing to realtime db
  const companyId = event.params.companyId;
  settings.getCompanyProfile(admin, companyId)
  .then((profile) => {
    return quotPdfHelper.generatePDF(fonts, profile, quotationData, storage);
  })
  .then(() => {
    console.log('Generation Successful. Pass for email');
  })
  .catch((err) => {
    console.log(`Error: ${err}`);
  });
};

To generate the PDF, here's my code:

exports.generatePDF = (fonts, companyInfo, quotationData, storage) => {
  const printer = new PdfPrinter(fonts);
  const docDefinition = {
    content: [
      {
        text: [
          {
            text: `${companyInfo.title}\n`,
            style: 'companyHeader',
          },
          `${companyInfo.addr_line1}, ${companyInfo.addr_line2}\n`,
          `${companyInfo.city} (${companyInfo.state}) - INDIA\n`,
          `Email: ${companyInfo.email} • Web: ${companyInfo.website}\n`,
          `Phone: ${companyInfo.phone}\n`,
          `GSTIN: ${companyInfo.gst_registration_number}  • PAN: AARFK6552G\n`,
        ],
        style: 'body',
         //absolutePosition: {x: 20, y: 45}
      },
    ],
    styles: {
      companyHeader: {
        fontSize: 18,
        bold: true,
      },
      body: {
        fontSize: 10,
      },
    },
    pageMargins: 20,
  };
  return new Promise((resolve, reject) => {
    // const bucket = storage.bucket(`${PROJECT_ID}.appspot.com`);
    // const filename = `${Date.now()}-quotation.pdf`;
    // const file = bucket.file(filename);
    // const stream = file.createWriteStream({ resumable: false });
    const pdfDoc = printer.createPdfKitDocument(docDefinition);
    // pdfDoc.pipe(stream);

    const chunks = [];
    let result = null;

    pdfDoc.on('data', (chunk) => {
      chunks.push(chunk);
    });
    pdfDoc.on('error', (err) => {
      reject(err);
    });
    pdfDoc.on('end', () => {
      result = Buffer.concat(chunks);
      resolve(result);
    });
    pdfDoc.end();
  });
};

What could be wrong here that is preventing the promise and thereby the quotation code to be executed as intended?

On firebase log, all I see is Function execution took 3288 ms, finished with status: 'ok'

Introversion answered 6/11, 2017 at 18:13 Comment(0)
C
4

Based on the execution time and lack of errors, it looks like you're successfully creating the buffer for the PDF but you're not actually returning it from the function.

.then((profile) => {
  return quotPdfHelper.generatePDF(fonts, profile, quotationData, storage);
})
.then(() => {
  console.log('Generation Successful. Pass for email');
})

In the code above, you're passing the result to the next then block, but then returning undefined from that block. The end result of this Promise chain will be undefined. To pass the result through, you'd want to return it at the end of the Promise chain:

.then((profile) => {
  return quotPdfHelper.generatePDF(fonts, profile, quotationData, storage);
})
.then(buffer => {
  console.log('Generation Successful. Pass for email');
  return buffer;
})
Calaverite answered 16/11, 2017 at 21:59 Comment(0)
A
0

I'm trying to experiment generating pdf using firebase cloud function but I am blocked about defining fonts parameter. Here's my definition:

var fonts = {
    Roboto: {
        normal: './fonts/Roboto-Regular.ttf',
        bold: './fonts/Roboto-Bold.ttf',
        italics: './fonts/Roboto-Italic.ttf',
        bolditalics: './fonts/Roboto-BoldItalic.ttf'
    }
};

I've created a fonts folder which contain the for above files. However wherever I set the fonts folder (in root, in functions folder or in node_modules folder), I get the error 'no such file or directory' when deploying functions. Any advice would be very much appreciated.

Applied answered 9/11, 2018 at 16:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.