refactor: wip to nestjs

This commit is contained in:
Ahmed Bouhuolia
2024-12-25 00:43:55 +02:00
parent 336171081e
commit a6932d76f3
249 changed files with 21314 additions and 1616 deletions

View File

@@ -0,0 +1,26 @@
import { ChromiumRoute, LibreOfficeRoute, PdfEngineRoute } from './_types';
export class Chromiumly {
public static readonly GOTENBERG_ENDPOINT = process.env.GOTENBERG_URL || '';
public static readonly CHROMIUM_PATH = 'forms/chromium/convert';
public static readonly PDF_ENGINES_PATH = 'forms/pdfengines';
public static readonly LIBRE_OFFICE_PATH = 'forms/libreoffice';
public static readonly GOTENBERG_DOCS_ENDPOINT =
process.env.GOTENBERG_DOCS_URL || '';
public static readonly CHROMIUM_ROUTES = {
url: ChromiumRoute.URL,
html: ChromiumRoute.HTML,
markdown: ChromiumRoute.MARKDOWN,
};
public static readonly PDF_ENGINE_ROUTES = {
merge: PdfEngineRoute.MERGE,
};
public static readonly LIBRE_OFFICE_ROUTES = {
convert: LibreOfficeRoute.CONVERT,
};
}

View File

@@ -0,0 +1,66 @@
import FormData from 'form-data';
import { GotenbergUtils } from './GotenbergUtils';
import { PageProperties } from './_types';
export class ConverterUtils {
public static injectPageProperties(
data: FormData,
pageProperties: PageProperties
): void {
if (pageProperties.size) {
GotenbergUtils.assert(
pageProperties.size.width >= 1.0 && pageProperties.size.height >= 1.5,
'size is smaller than the minimum printing requirements (i.e. 1.0 x 1.5 in)'
);
data.append('paperWidth', pageProperties.size.width);
data.append('paperHeight', pageProperties.size.height);
}
if (pageProperties.margins) {
GotenbergUtils.assert(
pageProperties.margins.top >= 0 &&
pageProperties.margins.bottom >= 0 &&
pageProperties.margins.left >= 0 &&
pageProperties.margins.left >= 0,
'negative margins are not allowed'
);
data.append('marginTop', pageProperties.margins.top);
data.append('marginBottom', pageProperties.margins.bottom);
data.append('marginLeft', pageProperties.margins.left);
data.append('marginRight', pageProperties.margins.right);
}
if (pageProperties.preferCssPageSize) {
data.append(
'preferCssPageSize',
String(pageProperties.preferCssPageSize)
);
}
if (pageProperties.printBackground) {
data.append('printBackground', String(pageProperties.printBackground));
}
if (pageProperties.landscape) {
data.append('landscape', String(pageProperties.landscape));
}
if (pageProperties.scale) {
GotenbergUtils.assert(
pageProperties.scale >= 0.1 && pageProperties.scale <= 2.0,
'scale is outside of [0.1 - 2] range'
);
data.append('scale', pageProperties.scale);
}
if (pageProperties.nativePageRanges) {
GotenbergUtils.assert(
pageProperties.nativePageRanges.from > 0 &&
pageProperties.nativePageRanges.to > 0 &&
pageProperties.nativePageRanges.to >=
pageProperties.nativePageRanges.from,
'page ranges syntax error'
);
data.append(
'nativePageRanges',
`${pageProperties.nativePageRanges.from}-${pageProperties.nativePageRanges.to}`
);
}
}
}

View File

@@ -0,0 +1,10 @@
import { Chromiumly } from './Chromiumly';
import { ChromiumRoute } from './_types';
export abstract class Converter {
readonly endpoint: string;
constructor(route: ChromiumRoute) {
this.endpoint = `${Chromiumly.GOTENBERG_ENDPOINT}/${Chromiumly.CHROMIUM_PATH}/${Chromiumly.CHROMIUM_ROUTES[route]}`;
}
}

View File

@@ -0,0 +1,24 @@
import FormData from 'form-data';
import Axios from 'axios';
export class GotenbergUtils {
public static assert(condition: boolean, message: string): asserts condition {
if (!condition) {
throw new Error(message);
}
}
public static async fetch(endpoint: string, data: FormData): Promise<Buffer> {
try {
const response = await Axios.post(endpoint, data, {
headers: {
...data.getHeaders(),
},
responseType: 'arraybuffer', // This ensures you get a Buffer bac
});
return response.data;
} catch (error) {
console.error(error);
}
}
}

View File

@@ -0,0 +1,38 @@
import { constants, createReadStream, PathLike, promises } from 'fs';
import FormData from 'form-data';
import { GotenbergUtils } from './GotenbergUtils';
import { IConverter, PageProperties } from './_types';
import { PdfFormat, ChromiumRoute } from './_types';
import { ConverterUtils } from './ConvertUtils';
import { Converter } from './Converter';
export class HtmlConverter extends Converter implements IConverter {
constructor() {
super(ChromiumRoute.HTML);
}
async convert({
html,
properties,
pdfFormat,
}: {
html: PathLike;
properties?: PageProperties;
pdfFormat?: PdfFormat;
}): Promise<Buffer> {
try {
await promises.access(html, constants.R_OK);
const data = new FormData();
if (pdfFormat) {
data.append('pdfFormat', pdfFormat);
}
data.append('index.html', createReadStream(html));
if (properties) {
ConverterUtils.injectPageProperties(data, properties);
}
return GotenbergUtils.fetch(this.endpoint, data);
} catch (error) {
throw error;
}
}
}

View File

@@ -0,0 +1,38 @@
import FormData from 'form-data';
import { IConverter, PageProperties, PdfFormat, ChromiumRoute } from './_types';
import { ConverterUtils } from './ConvertUtils';
import { Converter } from './Converter';
import { GotenbergUtils } from './GotenbergUtils';
export class UrlConverter extends Converter implements IConverter {
constructor() {
super(ChromiumRoute.URL);
}
async convert({
url,
properties,
pdfFormat,
}: {
url: string;
properties?: PageProperties;
pdfFormat?: PdfFormat;
}): Promise<Buffer> {
try {
const _url = new URL(url);
const data = new FormData();
if (pdfFormat) {
data.append('pdfFormat', pdfFormat);
}
data.append('url', _url.href);
if (properties) {
ConverterUtils.injectPageProperties(data, properties);
}
return GotenbergUtils.fetch(this.endpoint, data);
} catch (error) {
throw error;
}
}
}

View File

@@ -0,0 +1,51 @@
import { PathLike } from 'fs';
export type PageSize = {
width: number; // Paper width, in inches (default 8.5)
height: number; //Paper height, in inches (default 11)
};
export type PageMargins = {
top: number; // Top margin, in inches (default 0.39)
bottom: number; // Bottom margin, in inches (default 0.39)
left: number; // Left margin, in inches (default 0.39)
right: number; // Right margin, in inches (default 0.39)
};
export type PageProperties = {
size?: PageSize;
margins?: PageMargins;
preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
printBackground?: boolean; // Print the background graphics (default false)
landscape?: boolean; // Set the paper orientation to landscape (default false)
scale?: number; // The scale of the page rendering (default 1.0)
nativePageRanges?: { from: number; to: number }; // Page ranges to print
};
export interface IConverter {
convert({
...args
}: {
[x: string]: string | PathLike | PageProperties | PdfFormat;
}): Promise<Buffer>;
}
export enum PdfFormat {
A_1a = 'PDF/A-1a',
A_2b = 'PDF/A-2b',
A_3b = 'PDF/A-3b',
}
export enum ChromiumRoute {
URL = 'url',
HTML = 'html',
MARKDOWN = 'markdown',
}
export enum PdfEngineRoute {
MERGE = 'merge',
}
export enum LibreOfficeRoute {
CONVERT = 'convert',
}