Skip to content

Commit dbc2562

Browse files
ErwanRauloRaulo Erwan
andauthored
feat(extractor): Extends eventTarget instead of eventEmitter for browser compatibility (#562)
Co-authored-by: Raulo Erwan <[email protected]>
1 parent 3b653ee commit dbc2562

File tree

3 files changed

+71
-49
lines changed

3 files changed

+71
-49
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nodesecure/scanner": minor
3+
---
4+
5+
feat(extractor): Extends eventTarget instead of eventEmitter for browser compatibility

workspaces/scanner/src/extractors/payload.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// Import Node.js Dependencies
2-
import { EventEmitter } from "node:events";
3-
41
// Import Third-party Dependencies
52
import type { Simplify } from "type-fest";
63
// @ts-ignore
@@ -53,7 +50,7 @@ export interface ManifestProbeExtractor<Defs> extends ProbeExtractor<Defs> {
5350
next: ManifestProbeNextCallback;
5451
}
5552

56-
export class Payload<T extends ProbeExtractor<any>[]> extends EventEmitter {
53+
export class Payload<T extends ProbeExtractor<any>[]> extends EventTarget {
5754
private dependencies: Scanner.Payload["dependencies"];
5855
private probes: Record<ProbeExtractorLevel, T>;
5956
private cachedResult: ExtractProbeResult<T>;
@@ -82,6 +79,7 @@ export class Payload<T extends ProbeExtractor<any>[]> extends EventEmitter {
8279
for (const [name, dependency] of Object.entries(this.dependencies)) {
8380
this.probes.packument.forEach((probe) => probe.next(name, dependency));
8481
this.emit("packument", name, dependency);
82+
8583
if (this.probes.manifest.length > 0) {
8684
for (const [spec, depVersion] of Object.entries(dependency.versions)) {
8785
this.probes.manifest.forEach((probe) => probe.next(spec, depVersion, { name, dependency }));
@@ -103,6 +101,29 @@ export class Payload<T extends ProbeExtractor<any>[]> extends EventEmitter {
103101
...this.extract()
104102
) as unknown as MergedExtractProbeResult<T>;
105103
}
104+
105+
emit<T extends ProbeExtractorLevel>(
106+
event: T,
107+
...extractionDetails: unknown[]
108+
) {
109+
const customEvent = new CustomEvent(event, {
110+
detail: extractionDetails
111+
});
112+
this.dispatchEvent(customEvent);
113+
}
114+
115+
on<T extends ProbeExtractorLevel>(
116+
e: T,
117+
listener: ExtractorListener<T>
118+
): this {
119+
function wrappedListener(event: Event) {
120+
const customEvent = event as CustomEvent<ExtractorCallbackParams<T>>;
121+
listener(...customEvent.detail);
122+
}
123+
this.addEventListener(e, wrappedListener);
124+
125+
return this;
126+
}
106127
}
107128

108129
export const Callbacks = {
@@ -126,6 +147,18 @@ export const Callbacks = {
126147
}
127148
} as const;
128149

150+
type ExtractorCallback<T extends ProbeExtractorLevel> = Parameters<
151+
(typeof Callbacks)[T]
152+
>[0];
153+
154+
export type ExtractorCallbackParams<T extends ProbeExtractorLevel> = Parameters<
155+
ExtractorCallback<T>
156+
>;
157+
158+
export type ExtractorListener<T extends ProbeExtractorLevel> = (
159+
...events: CustomEvent<ExtractorCallbackParams<T>>["detail"]
160+
) => void;
161+
129162
function noop() {
130163
return void 0;
131164
}

workspaces/scanner/test/extractors/payload.spec.ts

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
// Import Node.js Dependencies
2-
import { describe, it } from "node:test";
32
import assert from "node:assert";
4-
import path from "node:path";
53
import fs from "node:fs";
4+
import path from "node:path";
5+
import { describe, it } from "node:test";
66

77
// Import Internal Dependencies
8-
import {
9-
Extractors,
10-
type ManifestProbeNextCallback,
11-
type PackumentProbeNextCallback,
12-
type Payload
13-
} from "../../src/index.js";
8+
import { type ExtractorCallbackParams } from "../../src/extractors/payload.js";
9+
import { Extractors, type Payload } from "../../src/index.js";
1410

1511
// CONSTANTS
1612
const kFixturePath = path.join("fixtures", "extractors");
@@ -220,30 +216,23 @@ describe("Extractors.Probes", () => {
220216
}
221217
};
222218

223-
const extractor = new Extractors.Payload(
224-
fakePayload,
225-
[
226-
new Extractors.Probes.Vulnerabilities()
227-
]
228-
);
219+
const extractor = new Extractors.Payload(fakePayload, [
220+
new Extractors.Probes.Vulnerabilities()
221+
]);
229222

230-
const {
231-
vulnerabilities
232-
} = extractor.extractAndMerge();
223+
const { vulnerabilities } = extractor.extractAndMerge();
233224

234225
assert.strictEqual(vulnerabilities.length, 2);
235226
assert.deepEqual(vulnerabilities, ["foo", "bar"]);
236227
});
237228
});
238229

239230
it("should extract data with multiple extractors in once", () => {
240-
const extractor = new Extractors.Payload(
241-
expressNodesecurePayload,
242-
[
243-
new Extractors.Probes.Size(),
244-
new Extractors.Probes.Contacts(),
245-
new Extractors.Probes.Licenses()
246-
]
231+
const extractor = new Extractors.Payload(expressNodesecurePayload, [
232+
new Extractors.Probes.Size(),
233+
new Extractors.Probes.Contacts(),
234+
new Extractors.Probes.Licenses()
235+
]
247236
);
248237

249238
const arrResult = extractor.extract();
@@ -258,9 +247,6 @@ describe("Extractors.Probes", () => {
258247
});
259248

260249
describe("Extractors.Payload events", () => {
261-
type ManifestEvent = Parameters<ManifestProbeNextCallback>;
262-
type PackumentEvent = Parameters<PackumentProbeNextCallback>;
263-
264250
it("should emits packument and manifest events", () => {
265251
const extractor = new Extractors.Payload(
266252
expressNodesecurePayload,
@@ -270,14 +256,14 @@ describe("Extractors.Payload events", () => {
270256
]
271257
);
272258

273-
const manifestEvents: ManifestEvent[] = [];
274-
const packumentEvents: PackumentEvent[] = [];
259+
const manifestEvents: ExtractorCallbackParams<"manifest">[] = [];
260+
const packumentEvents: ExtractorCallbackParams<"packument">[] = [];
275261

276-
extractor.on("manifest", (...event: ManifestEvent) => {
262+
extractor.on("manifest", (...event) => {
277263
manifestEvents.push(event);
278264
});
279265

280-
extractor.on("packument", (...event: PackumentEvent) => {
266+
extractor.on("packument", (...event) => {
281267
packumentEvents.push(event);
282268
});
283269

@@ -301,20 +287,18 @@ describe("Extractors.Callbacks", () => {
301287
it("should extract name and versions for all packages", () => {
302288
const packages = new Map<string, string[]>();
303289

304-
const extractor = new Extractors.Payload(
305-
expressNodesecurePayload,
306-
[
307-
Extractors.Callbacks.packument((name) => {
308-
if (!packages.has(name)) {
309-
packages.set(name, []);
310-
}
311-
}),
312-
Extractors.Callbacks.manifest((spec, _, parent) => {
313-
if (packages.has(parent.name)) {
314-
packages.get(parent.name)!.push(spec);
315-
}
316-
})
317-
]
290+
const extractor = new Extractors.Payload(expressNodesecurePayload, [
291+
Extractors.Callbacks.packument((name) => {
292+
if (!packages.has(name)) {
293+
packages.set(name, []);
294+
}
295+
}),
296+
Extractors.Callbacks.manifest((spec, _, parent) => {
297+
if (packages.has(parent.name)) {
298+
packages.get(parent.name)!.push(spec);
299+
}
300+
})
301+
]
318302
);
319303

320304
extractor.extract();

0 commit comments

Comments
 (0)