Repository: twentyhq/twenty
File: packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToPdf.ts (TypeScript)

Code before:
    return registrationPromise;
  };
})();

export const exportBlockNoteEditorToPdf = async (
  parsedBody: PartialBlock[],
  filename: string,
) => {
  await registerInterFonts();

  const editor = BlockNoteEditor.create({
    initialContent: parsedBody,
  });

  const exporter = new PDFExporter(editor.schema, pdfDefaultSchemaMappings, {
    resolveFileUrl: async (url: string) => {
      const response = await fetch(url, {
        mode: 'cors',
        credentials: 'omit',
      });

      if (!response.ok) {
        throw new Error(`Failed to fetch asset at ${url}`);
      }

      return await response.blob();
    },
  });

  const pdfDocument = await exporter.toReactPDFDocument(editor.document);

  const blob = await pdf(pdfDocument).toBlob();
  saveAs(blob, `${filename}.pdf`);
};


Review comment (bug):
The `resolveFileUrl` function should have better error handling for network failures and blob conversion errors. Currently, errors from `fetch()` or `response.blob()` will propagate without context about which URL failed. Consider adding a try-catch block:
```typescript
resolveFileUrl: async (url: string) => {
  try {
    const response = await fetch(url, {
      mode: 'cors',
      credentials: 'omit',
    });

    if (!response.ok) {
      throw new Error(`Failed to fetch asset at ${url}: ${response.status} ${response.statusText}`);
    }

    return await response.blob();
  } catch (error) {
    if (error instanceof Error && error.message.includes('Failed to fetch asset')) {
      throw error; // Re-throw our own errors
    }
    throw new Error(`Failed to fetch asset at ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`);
  }
},
```
```suggestion
      try {
        const response = await fetch(url, {
          mode: 'cors',
          credentials: 'omit',
        });

        if (!response.ok) {
          throw new Error(`Failed to fetch asset at ${url}: ${response.status} ${response.statusText}`);
        }

        return await response.blob();
      } catch (error) {
        if (error instanceof Error && error.message.includes('Failed to fetch asset')) {
          throw error; // Re-throw our own errors
        }
        throw new Error(`Failed to fetch asset at ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`);
      }
```

Code after:
    return registrationPromise;
  };
})();

export const exportBlockNoteEditorToPdf = async (
  parsedBody: PartialBlock[],
  filename: string,
) => {
  await registerInterFonts();

  const editor = BlockNoteEditor.create({
    initialContent: parsedBody,
  });

  const exporter = new PDFExporter(editor.schema, pdfDefaultSchemaMappings, {
    resolveFileUrl: async (url: string) => {
      try {
        const response = await fetch(url, {
          mode: 'cors',
          credentials: 'omit',
        });

        if (!response.ok) {
          throw new Error(
            `Failed to fetch asset at ${url}: ${response.status} ${response.statusText}`,
          );
        }

        return await response.blob();
      } catch (error) {
        if (
          error instanceof Error &&
          error.message.includes('Failed to fetch asset')
        ) {
          throw error;
        }
        throw new Error(
          `Failed to fetch asset at ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`,
        );
      }
    },
  });

  const pdfDocument = await exporter.toReactPDFDocument(editor.document);

  const blob = await pdf(pdfDocument).toBlob();
  saveAs(blob, `${filename}.pdf`);
};