diff --git a/.changeset/thick-moons-begin.md b/.changeset/thick-moons-begin.md new file mode 100644 index 00000000..d3378b30 --- /dev/null +++ b/.changeset/thick-moons-begin.md @@ -0,0 +1,5 @@ +--- +"@nodesecure/server": minor +--- + +Improve report test and implementation diff --git a/package.json b/package.json index 44692b20..43edef69 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "@nodesecure/npm-registry-sdk": "4.5.2", "@nodesecure/ossf-scorecard-sdk": "4.0.1", "@nodesecure/rc": "5.5.0", - "@nodesecure/report": "4.2.1", + "@nodesecure/report": "4.2.2", "@nodesecure/scanner": "10.7.0", "@nodesecure/server": "1.0.0", "@nodesecure/utils": "^2.2.0", diff --git a/public/components/views/home/report/report.js b/public/components/views/home/report/report.js index f28ea122..cd529031 100644 --- a/public/components/views/home/report/report.js +++ b/public/components/views/home/report/report.js @@ -252,12 +252,8 @@ class PopupReport extends LitElement { "Content-Type": "application/json" } }).then(async(response) => { - const { data: json } = await response.json(); - const url = window.URL.createObjectURL( - new Blob( - [new Uint8Array(json.data).buffer], { type: "application/pdf" } - ) - ); + const blob = await response.blob(); + const url = window.URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.target = "_blank"; diff --git a/workspaces/server/src/ALS.ts b/workspaces/server/src/ALS.ts index 52e2dac7..1c028b1f 100644 --- a/workspaces/server/src/ALS.ts +++ b/workspaces/server/src/ALS.ts @@ -3,6 +3,7 @@ import { AsyncLocalStorage } from "node:async_hooks"; // Import Third-party Dependencies import type { PayloadCache } from "@nodesecure/cache"; +import type { report } from "@nodesecure/report"; // Import Internal Dependencies import type { ViewBuilder } from "./ViewBuilder.class.ts"; @@ -18,6 +19,7 @@ export interface AsyncStoreContext { french: NestedStringRecord; }; viewBuilder: ViewBuilder; + reporter?: typeof report; } export const context = new AsyncLocalStorage(); diff --git a/workspaces/server/src/endpoints/report.ts b/workspaces/server/src/endpoints/report.ts index e83f65f2..c6ac145f 100644 --- a/workspaces/server/src/endpoints/report.ts +++ b/workspaces/server/src/endpoints/report.ts @@ -61,7 +61,7 @@ export async function post( const body = await bodyParser(req); const { title, includesAllDeps, theme } = body; - const { cache } = context.getStore()!; + const { cache, reporter: reportFn = report } = context.getStore()!; const currentSpec = cache.getCurrentSpec(); if (currentSpec === null) { @@ -87,10 +87,12 @@ export async function post( const reportPayload = structuredClone({ ...kReportPayload, title, - npm: repo === undefined ? undefined : { - organizationPrefix, - packages: [repo] - }, + npm: repo === undefined ? + undefined : + { + organizationPrefix, + packages: [repo] + }, theme }); @@ -101,14 +103,12 @@ export async function post( [name]: scannerPayload.dependencies[name] } satisfies Dependencies; - const data = await report( + const data = await reportFn( dependencies, reportPayload ); - return send(res, { - data - }, { + return send(res, data, { headers: { "content-type": "application/pdf" } diff --git a/workspaces/server/src/endpoints/util/send.ts b/workspaces/server/src/endpoints/util/send.ts index a93cc646..98427737 100644 --- a/workspaces/server/src/endpoints/util/send.ts +++ b/workspaces/server/src/endpoints/util/send.ts @@ -10,7 +10,7 @@ export interface SendOptions { headers?: OutgoingHttpHeaders; } -type SendData = string | object; +type SendData = string | object | Buffer; export function send( res: ServerResponse, @@ -21,9 +21,12 @@ export function send( let contentType = headers["content-type"] as string | undefined ?? res.getHeader("content-type") as string | undefined; - - let body: string; - if (typeof data === "object") { + let body: string | Buffer; + if (Buffer.isBuffer(data)) { + body = data; + contentType ??= "application/octet-stream"; + } + else if (typeof data === "object") { body = JSON.stringify(data); contentType ??= "application/json;charset=utf-8"; } diff --git a/workspaces/server/src/index.ts b/workspaces/server/src/index.ts index f8d20c91..466efa29 100644 --- a/workspaces/server/src/index.ts +++ b/workspaces/server/src/index.ts @@ -7,6 +7,7 @@ import http from "node:http"; import sirv from "sirv"; import { PayloadCache } from "@nodesecure/cache"; import type { Payload } from "@nodesecure/scanner"; +import type { report } from "@nodesecure/report"; // Import Internal Dependencies import { getApiRouter } from "./endpoints/index.ts"; @@ -32,6 +33,7 @@ export interface BuildServerOptions { res: http.ServerResponse, next: () => void ) => void; + reporter?: typeof report; } export async function buildServer( @@ -47,7 +49,8 @@ export async function buildServer( scanType = "from", projectRootDir, componentsDir, - i18n + i18n, + reporter } = options; const cache = await new PayloadCache().load(); @@ -58,7 +61,8 @@ export async function buildServer( const store: AsyncStoreContext = { i18n, viewBuilder, - cache + cache, + reporter }; if (runFromPayload && dataFilePath !== undefined) { const payloadStr = await fs.readFile(dataFilePath, "utf-8"); diff --git a/workspaces/server/test/httpServer.test.ts b/workspaces/server/test/httpServer.test.ts index 03281f89..9095eb69 100644 --- a/workspaces/server/test/httpServer.test.ts +++ b/workspaces/server/test/httpServer.test.ts @@ -41,6 +41,7 @@ describe("httpServer", () => { ({ httpServer } = await buildServer(JSON_PATH, { projectRootDir: kProjectRootDir, componentsDir: kComponentsDir, + reporter: async() => Buffer.from("fake-pdf-data"), i18n: { english: { ui: {} @@ -282,7 +283,7 @@ describe("httpServer", () => { }); }); - test.skip("'/report' should return a Buffer", async() => { + test("'/report' should return a Buffer", async() => { const result = await post( new URL("/report", kHttpURL), {