fix: Emitter should not extend EventEmitter

This change modifies Emitter so that it does not directly extend the Node.js
EventEmitter class. Instead, it holds a singleton instance of an EventEmitter
but is not an instance of EventEmitter itself.

This commit also updates the typescript example to use a modern version of
@types/node and typescript.

Finally there are a few minor formatting changes picked up by eslint.

Fixes: https://github.com/cloudevents/sdk-javascript/issues/385

Signed-off-by: Lance Ball <lball@redhat.com>
This commit is contained in:
Lance Ball 2021-02-25 09:55:56 -05:00
parent 6be3b27514
commit 1af3d43341
5 changed files with 22 additions and 31 deletions

View File

@ -23,9 +23,9 @@
"posttest": "npm run check" "posttest": "npm run check"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^8.9.0", "@types/node": "^14.14.10",
"gts": "^1.1.0", "gts": "^1.1.0",
"typescript": "~3.9.5" "typescript": "~4.1.3"
}, },
"dependencies": { "dependencies": {
"cloudevents": "~4.0.0" "cloudevents": "~4.0.0"

View File

@ -1,14 +1,15 @@
import { CloudEvent, CloudEventV1, HTTP } from "cloudevents"; /* eslint-disable no-console */
import { CloudEvent, HTTP } from "cloudevents";
export function doSomeStuff(): void { export function doSomeStuff(): void {
const myevent: CloudEventV1 = new CloudEvent({ const myevent: CloudEvent = new CloudEvent({
source: "/source", source: "/source",
type: "type", type: "type",
datacontenttype: "text/plain", datacontenttype: "text/plain",
dataschema: "https://d.schema.com/my.json", dataschema: "https://d.schema.com/my.json",
subject: "cha.json", subject: "cha.json",
data: "my-data", data: "my-data",
extension1: "some extension data" extension1: "some extension data",
}); });
console.log("My structured event:", myevent); console.log("My structured event:", myevent);
@ -40,7 +41,6 @@ export function doSomeStuff(): void {
console.log("My binary event:", HTTP.toEvent({ headers: attributes, body: data })); console.log("My binary event:", HTTP.toEvent({ headers: attributes, body: data }));
console.log("My binary event extensions:", HTTP.toEvent({ headers: attributes, body: data })); console.log("My binary event extensions:", HTTP.toEvent({ headers: attributes, body: data }));
} }
doSomeStuff(); doSomeStuff();

6
package-lock.json generated
View File

@ -775,9 +775,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "13.13.30", "version": "14.14.31",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.30.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz",
"integrity": "sha512-HmqFpNzp3TSELxU/bUuRK+xzarVOAsR00hzcvM0TXrMlt/+wcSLa5q6YhTb6/cA6wqDCZLDcfd8fSL95x5h7AA==", "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==",
"dev": true "dev": true
}, },
"@types/normalize-package-data": { "@types/normalize-package-data": {

View File

@ -108,7 +108,7 @@
"@types/cucumber": "^6.0.1", "@types/cucumber": "^6.0.1",
"@types/got": "^9.6.11", "@types/got": "^9.6.11",
"@types/mocha": "^7.0.2", "@types/mocha": "^7.0.2",
"@types/node": "^13.13.9", "@types/node": "^14.14.10",
"@types/superagent": "^4.1.10", "@types/superagent": "^4.1.10",
"@types/uuid": "^8.0.0", "@types/uuid": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^3.4.0", "@typescript-eslint/eslint-plugin": "^3.4.0",

View File

@ -46,14 +46,14 @@ export function emitterFor(fn: TransportFunction, options = { binding: HTTP, mod
throw new TypeError("A TransportFunction is required"); throw new TypeError("A TransportFunction is required");
} }
const { binding, mode } = options; const { binding, mode } = options;
return function emit(event: CloudEvent, options?: Options): Promise<unknown> { return function emit(event: CloudEvent, opts?: Options): Promise<unknown> {
options = options || {}; opts = opts || {};
switch (mode) { switch (mode) {
case Mode.BINARY: case Mode.BINARY:
return fn(binding.binary(event), options); return fn(binding.binary(event), opts);
case Mode.STRUCTURED: case Mode.STRUCTURED:
return fn(binding.structured(event), options); return fn(binding.structured(event), opts);
default: default:
throw new TypeError(`Unexpected transport mode: ${mode}`); throw new TypeError(`Unexpected transport mode: ${mode}`);
} }
@ -63,29 +63,20 @@ export function emitterFor(fn: TransportFunction, options = { binding: HTTP, mod
/** /**
* A static class to emit CloudEvents within an application * A static class to emit CloudEvents within an application
*/ */
export class Emitter extends EventEmitter { export class Emitter {
/** /**
* Singleton store * Singleton store
*/ */
static instance: Emitter | undefined = undefined; static instance: EventEmitter | undefined = undefined;
/**
* Create an Emitter
* On v4.0.0 this class will only remains as Singleton to allow using the
* EventEmitter of NodeJS
*/
private constructor() {
super();
}
/** /**
* Return or create the Emitter singleton * Return or create the Emitter singleton
* *
* @return {Emitter} return Emitter singleton * @return {Emitter} return Emitter singleton
*/ */
static getInstance(): Emitter { static getInstance(): EventEmitter {
if (!Emitter.instance) { if (!Emitter.instance) {
Emitter.instance = new Emitter(); Emitter.instance = new EventEmitter();
} }
return Emitter.instance; return Emitter.instance;
} }
@ -97,7 +88,7 @@ export class Emitter extends EventEmitter {
* @param {Function} listener to call on event * @param {Function} listener to call on event
* @return {void} * @return {void}
*/ */
static on(event: "cloudevent" | "newListener" | "removeListener", listener: (...args: any[]) => void): void { static on(event: string, listener: (...args: any[]) => void): void {
this.getInstance().on(event, listener); this.getInstance().on(event, listener);
} }