pdfme / pdfme

Open-source PDF generation library built with TypeScript and React. Features a WYSIWYG template designer, PDF viewer, and powerful generation capabilities. Create custom PDFs effortlessly in both browser and Node.js environments.

Home Page:http://pdfme.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problem building project in NodeJS

mitcheljimenez opened this issue · comments

Describe the bug

I have a google cloud function project and I installed packages @pdfme/generator and @pdfme/common to generate PDFs inside our google cloud functions. When building the project, an error occurs because it cannot find namespace 'React' on packages like:

  • antd
  • @ant-design
  • rc-picker
  • form-render
  • And others related to pdfme.

The weird thing is that I only installed those two packages and did not installed other packages like for designing pdf's, pdf viewer or pdf form.

Captura de pantalla 2024-04-26 a la(s) 09 00 50

To Reproduce

I created a template, installed @pdfme/common and @pdfme/generator and tried to generate pdf with some inputs.

Captura de pantalla 2024-04-26 a la(s) 09 41 22

Expected behavior

I would expect the packages to not need React on backend.

Your Environment

- pdfme package: @pdfme/generator & @pdfme/common
- pdfme version:
    "@pdfme/common": "^4.0.0",
    "@pdfme/generator": "^4.0.0",
- Operating system: MacOs
- Node.js version or Browser name & version: 20

Your Error Log

node_modules/rc-virtual-list/lib/Filler.d.ts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/mitcheljimenez/innovatech/insurance-carrier/functions/node_modules/react/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`

1 import * as React from 'react';
                         ~~~~~~~

node_modules/rc-virtual-list/lib/hooks/useScrollTo.d.ts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/mitcheljimenez/innovatech/insurance-carrier/functions/node_modules/react/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`

1 import * as React from 'react';
                         ~~~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:1:23 - error TS2688: Cannot find type definition file for 'react'.

1 /// <reference types="react" />
                        ~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:3:13 - error TS2503: Cannot find namespace 'React'.

3     style?: React.CSSProperties;
              ~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:4:7 - error TS2503: Cannot find namespace 'React'.

4 }) => React.ReactNode;
        ~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:6:26 - error TS2503: Cannot find namespace 'React'.

6     getKey: (item: T) => React.Key;
                           ~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:8:38 - error TS2503: Cannot find namespace 'React'.

8 export type GetKey<T> = (item: T) => React.Key;
                                       ~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:9:34 - error TS2503: Cannot find namespace 'React'.

9 export type GetSize = (startKey: React.Key, endKey?: React.Key) => {
                                   ~~~~~

node_modules/rc-virtual-list/lib/interface.d.ts:9:54 - error TS2503: Cannot find namespace 'React'.

9 export type GetSize = (startKey: React.Key, endKey?: React.Key) => {
                                                       ~~~~~

node_modules/rc-virtual-list/lib/List.d.ts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/mitcheljimenez/innovatech/insurance-carrier/functions/node_modules/react/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`

1 import * as React from 'react';
                         ~~~~~~~

node_modules/rc-virtual-list/lib/ScrollBar.d.ts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/mitcheljimenez/innovatech/insurance-carrier/functions/node_modules/react/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`

1 import * as React from 'react';
                         ~~~~~~~

node_modules/rc-virtual-list/lib/utils/CacheMap.d.ts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/mitcheljimenez/innovatech/insurance-carrier/functions/node_modules/react/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`

Additional context

There's another comparable issue, but the error and @pdfme versiones are not the same:

#447

When installing @types/react as a dev dependency, then these errors appeared.

Captura de pantalla 2024-04-26 a la(s) 09 53 19

Installed fontkit types and then only these two errors appeared:

Captura de pantalla 2024-04-26 a la(s) 09 54 02

Tried installing pdfjs-dist but it didn't work solving them. Then there's the rc-picker error. Any recommendations?

Hi @mitcheljimenez !

Can you give me the full code of what you are trying?
Also Please try this comment code.

I guess Template should be imported as type.

Oh hi! Sorry for the late reply.

I downgraded to version 2.0.2 and it works now.

I tried the solution you referenced but after upgrading it again to 4.0.0 but the same error appears, I even tried not importing Template type and just cast the JSON file imported as any so typescript linter don't complain.

This is the complete file (I did not remove my code so sorry for the

import { Quotation } from '@common/entities/quotation.entity';
import summaryPdfTemplate from './summary-pdf.template.json';
import { generate } from '@pdfme/generator';
import type { Template } from '@pdfme/common';

import { formatDocumentNumber } from '@common/helpers/format-document-number';
import { DateTime } from 'luxon';
import { getProposalsByProductName } from './helpers/get-proposals-by-product-name';

const mapPaymentManagementNumberToName = (
  paymentManagement: Quotation['conditions']['paymentManagement']
): string => { ... };

const getProposalConditionsText = (
  proposal: Quotation['proposals'][number]
): string => { ... }

export const createSummaryPdf = async ({
  quotation,
  ufRate,
}: {
  quotation: Omit<Quotation, 'id'>;
  ufRate: number;
}): Promise<Buffer> => {
  const solucionMovilEstandarProposals = getProposalsByProductName({
    proposals: quotation.proposals,
    productName: 'SOLUCION MOVIL ESTANDAR',
  });

  const solucionMovilDosProposals = getProposalsByProductName({
    proposals: quotation.proposals,
    productName: 'SOLUCION MOVIL 2.0',
  });

  const solucionMovilMasDosProposals = getProposalsByProductName({
    proposals: quotation.proposals,
    productName: 'SOLUCION MOVIL MAS 2.0',
  });

  const inputs = [
    {
      executiveName: quotation.executiveName,
      policyholderName: `${quotation.policyholder.name} ${quotation.policyholder.firstLastName} ${quotation.policyholder.secondLastName}`,
      policyholderDocumentNumber: formatDocumentNumber(
        quotation.policyholder.documentNumber
      ),
      policyholderEmail: quotation.policyholder.email ?? '',
      policyholderPhoneNumber: quotation.policyholder.mobileNumber ?? '',
      vehicleType: '',
      vehicleBrandName: quotation.vehicle.brandName,
      vehicleModelName: quotation.vehicle.modelName,
      vehicleYear: quotation.vehicle.year.toString(),
      vehicleUse: quotation.vehicle.useType,
      vehicleState: quotation.vehicle.state,
      vehicleSpecificUse: quotation.vehicle.useType,
      proposalsTableTitle: `OPCIONES DE PRODUCTOS ${mapPaymentManagementNumberToName(
        quotation.conditions.paymentManagement
      )} ${quotation.conditions.paymentFeesCount ?? 0} CUOTAS`,
      quotationId: quotation.externalQuotationId,
      quotationExtraData: `Valor referencial a la UF del día: $ ${ufRate.toLocaleString(
        'es-CL'
      )} - Fecha de Cotización: ${DateTime.fromJSDate(quotation.createdAt, {
        zone: 'America/Santiago',
      }).toFormat('dd-MM-yyyy HH:mm:ss')} - Vigencia de Cotización: ${Math.ceil(
        DateTime.fromJSDate(quotation.expiresAt).diff(
          DateTime.fromJSDate(quotation.createdAt),
          'days'
        ).days
      )} Días`,
      noDeductibleSM2Data: getProposalConditionsText(
        solucionMovilDosProposals['Sin Deducible']
      ),
      '3UFDeductibleSM2Data': getProposalConditionsText(
        solucionMovilDosProposals['Deducible 3 UF']
      ),
      '5UFDeductibleSM2Data': getProposalConditionsText(
        solucionMovilDosProposals['Deducible 5 UF']
      ),
      '10UFDeductibleSM2Data': getProposalConditionsText(
        solucionMovilDosProposals['Deducible 10 UF']
      ),
      '15UFDeductibleSM2Data': getProposalConditionsText(
        solucionMovilDosProposals['Deducible 15 UF']
      ),
      '20UFDeductibleSM2Data': getProposalConditionsText(
        solucionMovilDosProposals['Deducible 20 UF']
      ),

      noDeductibleSMEData: getProposalConditionsText(
        solucionMovilEstandarProposals['Sin Deducible']
      ),
      '3UFDeductibleSMEData': getProposalConditionsText(
        solucionMovilEstandarProposals['Deducible 3 UF']
      ),
      '5UFDeductibleSMEData': getProposalConditionsText(
        solucionMovilEstandarProposals['Deducible 5 UF']
      ),
      '10UFDeductibleSMEData': getProposalConditionsText(
        solucionMovilEstandarProposals['Deducible 10 UF']
      ),
      '15UFDeductibleSMEData': getProposalConditionsText(
        solucionMovilEstandarProposals['Deducible 15 UF']
      ),
      '20UFDeductibleSMEData': getProposalConditionsText(
        solucionMovilEstandarProposals['Deducible 20 UF']
      ),
      noDeductibleSMM2Data: getProposalConditionsText(
        solucionMovilMasDosProposals['Sin Deducible']
      ),
      '3UFDeductibleSMM2Data': getProposalConditionsText(
        solucionMovilMasDosProposals['Deducible 3 UF']
      ),
      '5UFDeductibleSMM2Data': getProposalConditionsText(
        solucionMovilMasDosProposals['Deducible 5 UF']
      ),
      '10UFDeductibleSMM2Data': getProposalConditionsText(
        solucionMovilMasDosProposals['Deducible 10 UF']
      ),
      '15UFDeductibleSMM2Data': getProposalConditionsText(
        solucionMovilMasDosProposals['Deducible 15 UF']
      ),
      '20UFDeductibleSMM2Data': getProposalConditionsText(
        solucionMovilMasDosProposals['Deducible 20 UF']
      ),
    },
  ];

  const pdf = await generate({
    template: summaryPdfTemplate as unknown as Template,
    inputs,
  });

  return Buffer.from(pdf.buffer);
};

Hey @mitcheljimenez
This issue may have been fixed in this PR

It has been released as V4.0.2, so could you please try again with the latest version?

I am getting the same issue on 4.0.2

I had the same problem, was able to fix it using this tsconfig

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "commonjs",
    "skipLibCheck": true,
    
    /* Linting */
    "strict": false,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,

    "esModuleInterop": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist"
  },
  "include": ["src"]
}

and no need to add type:module to your package.json
Although I still have to add //@ts-ignore to the generate method

Sample code

import {Template} from '@pdfme/common';
import {generate} from '@pdfme/generator';
import * as fs from "fs";
import * as path from "node:path";
import {
    barcodes,
    ellipse,
    image,
    line,
    readOnlyImage,
    readOnlySvg,
    readOnlyText,
    rectangle,
    svg,
    tableBeta,
    text,
} from '@pdfme/schemas';

const readJsonFile = async (filePath: string): Promise<Template> => {
    const fileContent = fs.readFileSync(filePath, 'utf8');
    return JSON.parse(fileContent);
}

export const getPlugins = () => {
    return {
        Text: text,
        ReadOnlyText: readOnlyText,
        Table: tableBeta,
        Line: line,
        Rectangle: rectangle,
        Ellipse: ellipse,
        Image: image,
        ReadOnlyImage: readOnlyImage,
        SVG: svg,
        ReadOnlySvg: readOnlySvg,
        QR: barcodes.qrcode,
        Code128: barcodes.code128,
    };
};

readJsonFile('./template.json').then(async (template) => {

    let body = JSON.stringify([["sample"]]);
    const inputs = [{
        "name": "James Akinniranye",
        "title": "Software Engineer",
        "contactInfo": "+123-456-7890\nhello@reallygreatsite.com\n123 Anywhere St., Any City",
        "date": "15th August 2026",
        "recipientInfo": "Helene Paquet\nHiring Manager, Really Great Place\n\n+123-456-7890\nhello@reallygreatsite.com\n123 Anywhere St., Any City",
        "jobReference": "JOB REFERENCE: SENIOR ACCOUNT MANAGER",
        "salutation": "Dear James",
        "letterBody": body,
        "closing": "Yours faithfully",
        "printedName": "James Akinniranye"
    }];

    //@ts-ignore
    const pdf = await generate({template: template, inputs: inputs, plugins: getPlugins()});
    fs.writeFileSync(path.join(__dirname, `test.pdf`), pdf);
})