Skip to content

Commit

Permalink
Modifies Fetcher to return something else than a stream, writes helpe…
Browse files Browse the repository at this point in the history
…r for generate function
  • Loading branch information
pierredge committed May 26, 2024
1 parent e5c9c74 commit 0817cbf
Show file tree
Hide file tree
Showing 10 changed files with 606 additions and 419 deletions.
4 changes: 3 additions & 1 deletion .fernignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Specify files that shouldn't be modified by Fern

src/core/form-data-utils/FormDataWrapper.ts
src/core/helper.ts
src/core/fetcher/Fetcher.ts
src/core/form-data-utils/FormData.ts
src/core/form-data-utils/index.ts
src/core/index.ts
README.md
Expand Down
Binary file modified output.pdf
Binary file not shown.
Binary file added output_helper.pdf
Binary file not shown.
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 11 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,26 @@
"test": "jest"
},
"dependencies": {
"url-join": "4.0.1",
"form-data": "4.0.0",
"form-data-encoder": "^4.0.2",
"formdata-node": "^6.0.3",
"js-base64": "3.7.2",
"mime-types": "^2.1.35",
"node-fetch": "2.7.0",
"qs": "6.11.2",
"formdata-node": "^6.0.3",
"form-data-encoder": "^4.0.2",
"js-base64": "3.7.2"
"url-join": "4.0.1"
},
"devDependencies": {
"@types/url-join": "4.0.1",
"@types/qs": "6.9.8",
"@types/jest": "29.5.5",
"@types/mime-types": "^2.1.4",
"@types/node": "17.0.33",
"@types/node-fetch": "2.6.9",
"@types/qs": "6.9.8",
"@types/url-join": "4.0.1",
"jest": "29.7.0",
"@types/jest": "29.5.5",
"ts-jest": "29.1.1",
"jest-environment-jsdom": "29.7.0",
"@types/node": "17.0.33",
"prettier": "2.7.1",
"ts-jest": "29.1.1",
"typescript": "4.6.4"
}
}
2 changes: 1 addition & 1 deletion src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class FileForgeClient {
files: File[] | fs.ReadStream[],
request: FileForge.GenerateRequest,
requestOptions?: FileForgeClient.RequestOptions
): Promise<stream.Readable>{
): Promise<any>{
const _request = core.newFormData();
const options = await serializers.GenerateRequestOptions.jsonOrThrow(request.options, {
unrecognizedObjectKeys: "passthrough",
Expand Down
47 changes: 46 additions & 1 deletion src/core/fetcher/Fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,29 @@ export declare namespace Fetcher {
}
}

async function* readableStreamAsyncIterator(stream: ReadableStream<Uint8Array>) {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
yield value;
}
} finally {
reader.releaseLock();
}
}

function isStringifiedJSON(str: string): boolean {
try {
JSON.parse(str);
return true;
} catch (e) {
return false;
}
}


const INITIAL_RETRY_DELAY = 1;
const MAX_RETRY_DELAY = 60;
const DEFAULT_MAX_RETRIES = 2;
Expand Down Expand Up @@ -127,10 +150,32 @@ async function fetcherImpl<R = unknown>(args: Fetcher.Args): Promise<APIResponse

let body: unknown;
if (response.body != null && args.responseType === "blob") {
console.log("BLOB")
body = await response.blob();
} else if (response.body != null && args.responseType === "streaming") {
body = response.body;

const chunks: any[] = [];

for await (let chunk of readableStreamAsyncIterator(response.body)) {
chunks.push(chunk);
}

const buffer: Buffer = Buffer.concat(chunks);
const bufferString = buffer.toString();

if (bufferString.includes("%%EOF")){
body = {"file":buffer};

}else if (isStringifiedJSON(bufferString)){
body = JSON.parse(bufferString)

}else{
body = bufferString

}

} else if (response.body != null && args.responseType === "text") {
console.log("TEXT")
body = await response.text();
} else {
const text = await response.text();
Expand Down
86 changes: 86 additions & 0 deletions src/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as environments from "./environments";
import * as core from "./core";
import urlJoin from "url-join";
import * as errors from "./errors/index";
import * as fs from "fs";
import * as FileForge from "./api/index";
import * as stream from "stream";
import { default as FormData } from "form-data";
import * as serializers from "./serialization/index";
import mime from "mime-types";
import { FileForgeClient } from "Client";

export interface Asset {
path: string;
content: string;
}
export interface PathBuffer {
path: string;
content: Buffer;
}

type AssetOrPathBuffer = Asset | PathBuffer;


export interface DocumentInput {
html: string;
fileName?: string;
test?: boolean;
host?: boolean;
expiresAt?: Date;
files?: AssetOrPathBuffer[];
}


/**
* Generates a PDF document from web assets.
* @throws {@link FileForge.BadRequestError}
* @throws {@link FileForge.UnauthorizedError}
* @throws {@link FileForge.InternalServerError}
* @throws {@link FileForge.BadGatewayError}
*/
export async function generate_from_html(
client: FileForgeClient,
document: DocumentInput
):Promise<any>{

const files: AssetOrPathBuffer[] = document.files ?? [];
files.push({ path: "/index.html", content: document.html });

const test: boolean = document.test ?? true;
const save: boolean = document.host ?? false;


const optionsToUpload: FileForge.GenerateRequestOptions = {
test: test,
host: save,
expiresAt: document.expiresAt ?? new Date(Date.now() + 24 * 60 * 60 * 1000),
fileName: document.fileName ?? "document"
}

const htmlBlob = new Blob([document.html],{ type: "text/html" })
const htmlFile = new File([htmlBlob], "index.html", { type: "text/html" });

let filesToUpload = [htmlFile];

files.forEach((asset) => {

if (asset.content) {

const assetType = mime.lookup(asset.path) || "application/octet-stream";

const fileBlob = new Blob([asset.content],{ type: assetType })
const file = new File([fileBlob], asset.path, { type: assetType });
filesToUpload.push(file);

}
});

return await client.generate(
filesToUpload,
{
options: optionsToUpload
}
)

}
76 changes: 60 additions & 16 deletions tests/custom.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import stream from "stream";
import * as core from "../src/core";
import { FileForgeClient } from "../src";
import { generate_from_html } from "../src/Helper";
import * as error from "../src/errors/index";
import fs from "fs";
import { writeFile } from "fs/promises";
Expand Down Expand Up @@ -53,15 +54,8 @@ describe("test", () => {
}
);

const chunks: any[] = [];

for await (let chunk of pdf) {
chunks.push(chunk);
}

const buffer: Buffer = Buffer.concat(chunks);

await writeFile("output.pdf", buffer.toString()!);
await writeFile("output.pdf", pdf.file);
}, 10_000_000);


Expand All @@ -87,15 +81,9 @@ describe("test", () => {
}
}
);
const chunks: any[] = [];

for await (let chunk of pdf) {
chunks.push(chunk);
}

const buffer: Buffer = Buffer.concat(chunks);

expect(JSON.parse(buffer.toString()).url).not.toBeNull();

expect(pdf.url).not.toBeNull();

}, 10_000_000);

Expand Down Expand Up @@ -132,4 +120,60 @@ describe("test", () => {
}, 10_000_000);


it("should generate a PDF buffer from helper", async () => {
const htmlBlob = new Blob([HTML], {
type: "text/html",
});
const cssBlob = new Blob([CSS], {
type: "text/css",
});
const htmlFile = new File([htmlBlob], "index.html", { type: "text/html" });
const cssFile = new File([cssBlob], "style.css", { type: "text/css" });

const ff = new FileForgeClient({
apiKey: FILEFORGE_API_KEY
});

const pdf = await generate_from_html(
ff,
{
html:HTML,
fileName:"test",
host:false,
test:false
}

);

await writeFile("output_helper.pdf", pdf.file!);
}, 10_000_000);

it("should generate a PDF url from helper", async () => {
const htmlBlob = new Blob([HTML], {
type: "text/html",
});
const cssBlob = new Blob([CSS], {
type: "text/css",
});
const htmlFile = new File([htmlBlob], "index.html", { type: "text/html" });
const cssFile = new File([cssBlob], "style.css", { type: "text/css" });

const ff = new FileForgeClient({
apiKey: FILEFORGE_API_KEY
});

const pdf = await generate_from_html(
ff,
{
html:HTML,
fileName:"test",
host:true,
}

);

expect(pdf.url).not.toBeNull();
}, 10_000_000);


});
Loading

0 comments on commit 0817cbf

Please sign in to comment.