diff --git a/examples/getting-started/server.ts b/examples/getting-started/server.ts
index d294add..e564064 100644
--- a/examples/getting-started/server.ts
+++ b/examples/getting-started/server.ts
@@ -1,6 +1,8 @@
import path from "path";
import express from "express";
-import {createSession, Session} from "better-sse";
+import * as SSE from "better-sse/http2";
+
+console.log(SSE);
const app = express();
@@ -11,7 +13,7 @@ app.use(express.static(path.resolve(__dirname, "./public")));
*/
declare module "express-serve-static-core" {
interface Response {
- sse: Session;
+ // sse: Session;
}
}
@@ -21,9 +23,9 @@ app.get(
* Attach the session instance to the response.
*/
async (req, res, next) => {
- const session = await createSession(req, res);
+ // const session = await createSession(req, res);
- res.sse = session;
+ // res.sse = session;
next();
},
@@ -31,7 +33,7 @@ app.get(
* Push a message with the event name "ping".
*/
(_, res) => {
- res.sse.push("Hello world!", "ping");
+ // res.sse.push("Hello world!", "ping");
}
);
diff --git a/examples/http2-compat/index.ts b/examples/http2-compat/index.ts
new file mode 100644
index 0000000..7f8b957
--- /dev/null
+++ b/examples/http2-compat/index.ts
@@ -0,0 +1 @@
+import "./server";
diff --git a/examples/http2-compat/public/index.html b/examples/http2-compat/public/index.html
new file mode 100644
index 0000000..b8f8d9c
--- /dev/null
+++ b/examples/http2-compat/public/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+ HTTP/2 - Better SSE
+
+
+
+
+
diff --git a/examples/http2-compat/public/index.js b/examples/http2-compat/public/index.js
new file mode 100644
index 0000000..d5ce6bd
--- /dev/null
+++ b/examples/http2-compat/public/index.js
@@ -0,0 +1,11 @@
+const eventSource = new EventSource("/sse");
+
+eventSource.addEventListener("ping", (event) => {
+ const {type, data} = event;
+
+ const element = document.createElement("pre");
+
+ element.innerText = `Got '${type}' event: ${data}.`;
+
+ document.body.appendChild(element);
+});
diff --git a/examples/http2-compat/server.ts b/examples/http2-compat/server.ts
new file mode 100644
index 0000000..d54234f
--- /dev/null
+++ b/examples/http2-compat/server.ts
@@ -0,0 +1,69 @@
+import {resolve} from "path";
+import {promisify} from "util";
+import {createSecureServer} from "http2";
+import {
+ CertificateCreationOptions,
+ CertificateCreationResult,
+ createCertificate as createCertificateCallback,
+} from "pem";
+import {Http2CompatSession} from "better-sse";
+
+(async () => {
+ const createCertificate = promisify<
+ CertificateCreationOptions,
+ CertificateCreationResult
+ >(createCertificateCallback);
+
+ const indexHtmlPath = resolve(__dirname, "./public/index.html");
+ const indexJsPath = resolve(__dirname, "./public/index.js");
+
+ const {serviceKey: key, certificate: cert} = await createCertificate({
+ selfSigned: true,
+ days: 1,
+ });
+
+ const server = createSecureServer({key, cert}, async (req, res) => {
+ const {":path": path, ":method": method} = req.headers;
+ const {stream} = res;
+
+ if (method !== "GET") {
+ stream.respond({":status": 405});
+ stream.end();
+ return;
+ }
+
+ switch (path) {
+ case "/": {
+ stream.respondWithFile(indexHtmlPath);
+ break;
+ }
+ case "/index.js": {
+ stream.respondWithFile(indexJsPath);
+ break;
+ }
+ case "/sse": {
+ const session = new Http2CompatSession(req, res);
+
+ session.once("connected", () => {
+ session.push("Hello world", "ping");
+ });
+
+ break;
+ }
+ default: {
+ stream.respond({":status": 404});
+ stream.end();
+ }
+ }
+ });
+
+ server.on("error", console.error);
+
+ const PORT = process.env.PORT ?? 8443;
+
+ server.listen(PORT, () => {
+ console.log(
+ `Server listening. Open https://localhost:${PORT} in your browser.`
+ );
+ });
+})();
diff --git a/examples/http2/server.ts b/examples/http2/server.ts
index ccccbbb..5764c7b 100644
--- a/examples/http2/server.ts
+++ b/examples/http2/server.ts
@@ -6,7 +6,7 @@ import {
CertificateCreationResult,
createCertificate as createCertificateCallback,
} from "pem";
-import {createSession} from "better-sse";
+import {Http2Session} from "better-sse";
(async () => {
const createCertificate = promisify<
@@ -22,9 +22,10 @@ import {createSession} from "better-sse";
days: 1,
});
- const server = createSecureServer({key, cert}, async (req, res) => {
- const {":path": path, ":method": method} = req.headers;
- const {stream} = res;
+ const server = createSecureServer({key, cert});
+
+ server.on("stream", (stream, headers) => {
+ const {":path": path, ":method": method} = headers;
if (method !== "GET") {
stream.respond({":status": 405});
@@ -42,14 +43,17 @@ import {createSession} from "better-sse";
break;
}
case "/sse": {
- const session = await createSession(req, res);
+ const session = new Http2Session(stream, headers);
- session.push("Hello world", "ping");
+ session.once("connected", () => {
+ session.push("Hello world", "ping");
+ });
break;
}
default: {
stream.respond({":status": 404});
+ stream.end();
}
}
});
diff --git a/examples/package-lock.json b/examples/package-lock.json
index c201cbd..8bec4df 100644
--- a/examples/package-lock.json
+++ b/examples/package-lock.json
@@ -10,7 +10,7 @@
"license": "MIT",
"dependencies": {
"benchmark": "^2.1.4",
- "better-sse": "^0.12.1",
+ "better-sse": "file:..",
"easy-server-sent-events": "^1.0.14",
"eventsource": "^2.0.2",
"express": "^4.19.2",
@@ -28,6 +28,33 @@
"@types/pem": "^1.14.4"
}
},
+ "..": {
+ "version": "0.13.0",
+ "license": "MIT",
+ "devDependencies": {
+ "@types/eventsource": "^1.1.11",
+ "@types/express": "^4.17.16",
+ "@types/node": "^18.11.18",
+ "@typescript-eslint/eslint-plugin": "^5.49.0",
+ "@typescript-eslint/parser": "^5.49.0",
+ "eslint": "^8.32.0",
+ "eslint-plugin-tsdoc": "^0.2.17",
+ "eventsource": "^2.0.2",
+ "npm-run-all": "^4.1.5",
+ "prettier": "^2.8.3",
+ "rimraf": "^4.1.2",
+ "ts-loader": "^9.4.2",
+ "ts-node": "^10.9.1",
+ "typescript": "^4.9.4",
+ "vitest": "^0.28.2",
+ "webpack": "^5.75.0",
+ "webpack-cli": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=12",
+ "pnpm": ">=9"
+ }
+ },
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -311,14 +338,8 @@
}
},
"node_modules/better-sse": {
- "version": "0.12.1",
- "resolved": "https://registry.npmjs.org/better-sse/-/better-sse-0.12.1.tgz",
- "integrity": "sha512-U8BiD7DjQGG72kUiCJ5NM5ioKCqVeE+8Nd3pOPFtYx6PO1s0YtZtwNmImdTqSSmGaqDCmfzNwXcXdiAB4mCJrQ==",
- "license": "MIT",
- "engines": {
- "node": ">=12",
- "pnpm": ">=9"
- }
+ "resolved": "..",
+ "link": true
},
"node_modules/binary-extensions": {
"version": "2.3.0",
diff --git a/examples/package.json b/examples/package.json
index bd90d79..1683a9a 100644
--- a/examples/package.json
+++ b/examples/package.json
@@ -9,7 +9,7 @@
},
"dependencies": {
"benchmark": "^2.1.4",
- "better-sse": "^0.12.1",
+ "better-sse": "file:..",
"easy-server-sent-events": "^1.0.14",
"eventsource": "^2.0.2",
"express": "^4.19.2",
diff --git a/examples/tsconfig.json b/examples/tsconfig.json
index 0dd40a8..8653e86 100644
--- a/examples/tsconfig.json
+++ b/examples/tsconfig.json
@@ -3,7 +3,7 @@
"target": "ES2019",
"strict": true,
"outDir": "./build",
- "moduleResolution": "node",
+ "moduleResolution": "nodenext",
"esModuleInterop": true
}
}
diff --git a/package.json b/package.json
index 4e02fb4..6619e8e 100644
--- a/package.json
+++ b/package.json
@@ -2,8 +2,6 @@
"name": "better-sse",
"description": "Dead simple, dependency-less, spec-compliant server-sent events implementation for Node, written in TypeScript.",
"version": "0.13.0",
- "main": "./build/index.js",
- "types": "./build/index.d.ts",
"license": "MIT",
"author": "Matthew W. ",
"repository": "github:MatthewWid/better-sse",
@@ -17,6 +15,10 @@
"tcp",
"events"
],
+ "engines": {
+ "node": ">=12",
+ "pnpm": ">=9"
+ },
"scripts": {
"build": "webpack --env production",
"test": "vitest",
@@ -25,14 +27,16 @@
"lint": "eslint \"./src/**/*.ts\"",
"prepublishOnly": "npm-run-all clean format test build"
},
+ "main": "./build/http1.js",
+ "types": "./build/adapters/http1/index.d.ts",
+ "exports": {
+ ".": "./build/http1.js",
+ "./http2": "./build/http2.js"
+ },
"files": [
"build",
"!build/**/*.map"
],
- "engines": {
- "node": ">=12",
- "pnpm": ">=9"
- },
"devDependencies": {
"@types/eventsource": "^1.1.11",
"@types/express": "^4.17.16",
diff --git a/src/Session.ts b/src/Session.ts
index dc5b9f6..027f85e 100644
--- a/src/Session.ts
+++ b/src/Session.ts
@@ -1,9 +1,4 @@
-import {
- IncomingMessage as Http1ServerRequest,
- ServerResponse as Http1ServerResponse,
- OutgoingHttpHeaders,
-} from "http";
-import {Http2ServerRequest, Http2ServerResponse} from "http2";
+import {OutgoingHttpHeaders} from "http";
import {EventBuffer, EventBufferOptions} from "./EventBuffer";
import {TypedEmitter, EventMap} from "./lib/TypedEmitter";
import {generateId} from "./lib/generateId";
@@ -98,7 +93,9 @@ interface SessionEvents extends EventMap {
* @param res - The Node HTTP {@link https://nodejs.org/api/http.html#http_class_http_serverresponse | IncomingMessage} object.
* @param options - Options given to the session instance.
*/
-class Session extends TypedEmitter {
+abstract class Session<
+ State = DefaultSessionState
+> extends TypedEmitter {
/**
* The last event ID sent to the client.
*
@@ -128,22 +125,6 @@ class Session extends TypedEmitter {
state: State;
private buffer: EventBuffer;
-
- /**
- * Raw HTTP request.
- */
- private req: Http1ServerRequest | Http2ServerRequest;
-
- /**
- * Raw HTTP response that is the minimal interface needed and forms the
- * intersection between the HTTP/1.1 and HTTP/2 server response interfaces.
- */
- private res:
- | Http1ServerResponse
- | (Http2ServerResponse & {
- write: (chunk: string) => void;
- });
-
private serialize: SerializerFunction;
private sanitize: SanitizerFunction;
private trustClientEventId: boolean;
@@ -153,15 +134,17 @@ class Session extends TypedEmitter {
private statusCode: number;
private headers: OutgoingHttpHeaders;
- constructor(
- req: Http1ServerRequest | Http2ServerRequest,
- res: Http1ServerResponse | Http2ServerResponse,
- options: SessionOptions = {}
- ) {
- super();
+ protected abstract getDefaultHeaders(): OutgoingHttpHeaders;
+ protected abstract getHeader(name: string): string | undefined;
+ protected abstract getParam(name: string): string | undefined;
+ protected abstract sendHead(
+ statusCode: number,
+ headers: OutgoingHttpHeaders
+ ): void;
+ protected abstract sendChunk(chunk: string): void;
- this.req = req;
- this.res = res;
+ constructor(options: SessionOptions = {}) {
+ super();
const serializer = options.serializer ?? serialize;
const sanitizer = options.sanitizer ?? sanitize;
@@ -185,54 +168,33 @@ class Session extends TypedEmitter {
this.state = options.state ?? ({} as State);
- this.req.once("close", this.onDisconnected);
- this.res.once("close", this.onDisconnected);
-
setImmediate(this.initialize);
}
- private initialize = () => {
- const url = `http://${this.req.headers.host}${this.req.url}`;
- const params = new URL(url).searchParams;
-
+ protected initialize = () => {
if (this.trustClientEventId) {
const givenLastEventId =
- this.req.headers["last-event-id"] ??
- params.get("lastEventId") ??
- params.get("evs_last_event_id") ??
+ this.getHeader("last-event-id") ??
+ this.getParam("lastEventId") ??
+ this.getParam("evs_last_event_id") ??
"";
this.lastId = givenLastEventId as string;
}
- const headers: OutgoingHttpHeaders = {};
-
- if (this.res instanceof Http1ServerResponse) {
- headers["Content-Type"] = "text/event-stream";
- headers["Cache-Control"] =
- "private, no-cache, no-store, no-transform, must-revalidate, max-age=0";
- headers["Connection"] = "keep-alive";
- headers["Pragma"] = "no-cache";
- headers["X-Accel-Buffering"] = "no";
- } else {
- headers["content-type"] = "text/event-stream";
- headers["cache-control"] =
- "private, no-cache, no-store, no-transform, must-revalidate, max-age=0";
- headers["pragma"] = "no-cache";
- headers["x-accel-buffering"] = "no";
- }
+ const headers = this.getDefaultHeaders();
for (const [name, value] of Object.entries(this.headers)) {
headers[name] = value ?? "";
}
- this.res.writeHead(this.statusCode, headers);
+ this.sendHead(this.statusCode, headers);
- if (params.has("padding")) {
+ if (this.getParam("padding") !== undefined) {
this.buffer.comment(" ".repeat(2049)).dispatch();
}
- if (params.has("evs_preamble")) {
+ if (this.getParam("evs_preamble") !== undefined) {
this.buffer.comment(" ".repeat(2056)).dispatch();
}
@@ -254,10 +216,7 @@ class Session extends TypedEmitter {
this.emit("connected");
};
- private onDisconnected = () => {
- this.req.removeListener("close", this.onDisconnected);
- this.res.removeListener("close", this.onDisconnected);
-
+ protected onDisconnected() {
if (this.keepAliveTimer) {
clearInterval(this.keepAliveTimer);
}
@@ -265,7 +224,7 @@ class Session extends TypedEmitter {
this.isConnected = false;
this.emit("disconnected");
- };
+ }
private keepAlive = () => {
this.buffer.comment().dispatch();
@@ -334,7 +293,7 @@ class Session extends TypedEmitter {
* @deprecated see https://github.com/MatthewWid/better-sse/issues/52
*/
flush = (): this => {
- this.res.write(this.buffer.read());
+ this.sendChunk(this.buffer.read());
this.buffer.clear();
@@ -419,7 +378,7 @@ class Session extends TypedEmitter {
batcher: EventBuffer | ((buffer: EventBuffer) => void | Promise)
) => {
if (batcher instanceof EventBuffer) {
- this.res.write(batcher.read());
+ this.sendChunk(batcher.read());
} else {
const buffer = new EventBuffer({
serializer: this.serialize,
@@ -428,7 +387,7 @@ class Session extends TypedEmitter {
await batcher(buffer);
- this.res.write(buffer.read());
+ this.sendChunk(buffer.read());
}
};
}
diff --git a/src/adapters/http1/Http1Session.ts b/src/adapters/http1/Http1Session.ts
new file mode 100644
index 0000000..244f1d4
--- /dev/null
+++ b/src/adapters/http1/Http1Session.ts
@@ -0,0 +1,62 @@
+import {
+ IncomingMessage as Http1ServerRequest,
+ ServerResponse as Http1ServerResponse,
+ OutgoingHttpHeaders,
+} from "http";
+import {DefaultSessionState, Session} from "../../Session";
+
+class Http1Session extends Session {
+ private params: URLSearchParams;
+
+ constructor(
+ private req: Http1ServerRequest,
+ private res: Http1ServerResponse,
+ ...args: ConstructorParameters>
+ ) {
+ super(...args);
+
+ req.once("close", this.onDisconnected);
+ res.once("close", this.onDisconnected);
+
+ const url = new URL(`http://localhost${req.url}`);
+ this.params = url.searchParams;
+ }
+
+ protected onDisconnected = () => {
+ this.req.removeListener("close", this.onDisconnected);
+ this.res.removeListener("close", this.onDisconnected);
+
+ super.onDisconnected();
+ };
+
+ protected getDefaultHeaders() {
+ return {
+ "Content-Type": "text/event-stream",
+ "Cache-Control":
+ "private, no-cache, no-store, no-transform, must-revalidate, max-age=0",
+ Connection: "keep-alive",
+ Pragma: "no-cache",
+ "X-Accel-Buffering": "no",
+ };
+ }
+
+ protected getHeader(name: string): string | undefined {
+ const value = this.req.headers[name];
+
+ return Array.isArray(value) ? value.join(",") : value;
+ }
+
+ protected getParam(name: string): string | undefined {
+ return this.params.get(name) ?? undefined;
+ }
+
+ protected sendHead(statusCode: number, headers: OutgoingHttpHeaders) {
+ this.res.writeHead(statusCode, headers);
+ }
+
+ protected sendChunk(chunk: string) {
+ this.res.write(chunk);
+ }
+}
+
+export {Http1Session};
diff --git a/src/adapters/http1/createHttp1Session.ts b/src/adapters/http1/createHttp1Session.ts
new file mode 100644
index 0000000..542c8f3
--- /dev/null
+++ b/src/adapters/http1/createHttp1Session.ts
@@ -0,0 +1,18 @@
+import type {DefaultSessionState} from "../../Session";
+import {Http1Session} from "./Http1Session";
+
+/**
+ * Create a new session and return the session instance once it has connected.
+ */
+const createHttp1Session = (
+ ...args: ConstructorParameters>
+): Promise> =>
+ new Promise((resolve) => {
+ const session = new Http1Session(...args);
+
+ session.once("connected", () => {
+ resolve(session);
+ });
+ });
+
+export {createHttp1Session};
diff --git a/src/adapters/http1/index.ts b/src/adapters/http1/index.ts
new file mode 100644
index 0000000..e62ca99
--- /dev/null
+++ b/src/adapters/http1/index.ts
@@ -0,0 +1,3 @@
+export * from "../..";
+export * from "./Http1Session";
+export {createHttp1Session as createSession} from "./createHttp1Session";
diff --git a/src/adapters/http2/Http2Session.ts b/src/adapters/http2/Http2Session.ts
new file mode 100644
index 0000000..cb0c58a
--- /dev/null
+++ b/src/adapters/http2/Http2Session.ts
@@ -0,0 +1,61 @@
+import {
+ ServerHttp2Stream,
+ IncomingHttpHeaders,
+ OutgoingHttpHeaders,
+} from "http2";
+import {DefaultSessionState, Session} from "../../Session";
+
+class Http2Session extends Session {
+ private responseStream: ServerHttp2Stream;
+ private incomingHeaders: IncomingHttpHeaders;
+ private params: URLSearchParams;
+
+ constructor(
+ stream: ServerHttp2Stream,
+ headers: IncomingHttpHeaders,
+ ...args: ConstructorParameters>
+ ) {
+ super(...args);
+
+ this.responseStream = stream;
+ this.incomingHeaders = headers;
+
+ this.responseStream.on("close", this.onDisconnected);
+
+ const url = new URL(`http://localhost${headers[":path"]}`);
+ this.params = url.searchParams;
+ }
+
+ protected getDefaultHeaders() {
+ return {
+ "content-type": "text/event-stream",
+ "cache-control":
+ "private, no-cache, no-store, no-transform, must-revalidate, max-age=0",
+ pragma: "no-cache",
+ "x-accel-buffering": "no",
+ };
+ }
+
+ protected getHeader(name: string): string | undefined {
+ const {[name]: value} = this.incomingHeaders;
+
+ return Array.isArray(value) ? value.join(",") : value;
+ }
+
+ protected getParam(name: string): string | undefined {
+ return this.params.get(name) ?? undefined;
+ }
+
+ protected sendHead(statusCode: number, headers: OutgoingHttpHeaders) {
+ this.responseStream.respond({
+ ":status": statusCode,
+ ...headers,
+ });
+ }
+
+ protected sendChunk(chunk: string) {
+ this.responseStream.write(chunk);
+ }
+}
+
+export {Http2Session};
diff --git a/src/adapters/http2/createHttp2Session.ts b/src/adapters/http2/createHttp2Session.ts
new file mode 100644
index 0000000..1948d3c
--- /dev/null
+++ b/src/adapters/http2/createHttp2Session.ts
@@ -0,0 +1,17 @@
+import {Http2Session} from "./Http2Session";
+
+/**
+ * Create a new session and return the session instance once it has connected.
+ */
+const createHttp2Session = (
+ ...args: ConstructorParameters>
+): Promise> =>
+ new Promise((resolve) => {
+ const session = new Http2Session(...args);
+
+ session.once("connected", () => {
+ resolve(session);
+ });
+ });
+
+export {createHttp2Session};
diff --git a/src/adapters/http2/index.ts b/src/adapters/http2/index.ts
new file mode 100644
index 0000000..58780a2
--- /dev/null
+++ b/src/adapters/http2/index.ts
@@ -0,0 +1,2 @@
+export * from "./Http2Session";
+export {createHttp2Session as createSession} from "./createHttp2Session";
diff --git a/src/adapters/http2compat/Http2CompatSession.ts b/src/adapters/http2compat/Http2CompatSession.ts
new file mode 100644
index 0000000..ec5aa7c
--- /dev/null
+++ b/src/adapters/http2compat/Http2CompatSession.ts
@@ -0,0 +1,61 @@
+import {
+ Http2ServerRequest,
+ Http2ServerResponse,
+ OutgoingHttpHeaders,
+} from "http2";
+import {DefaultSessionState, Session} from "../../Session";
+
+class Http2CompatSession extends Session {
+ private params: URLSearchParams;
+
+ constructor(
+ private req: Http2ServerRequest,
+ private res: Http2ServerResponse,
+ ...args: ConstructorParameters>
+ ) {
+ super(...args);
+
+ req.once("close", this.onDisconnected);
+ res.once("close", this.onDisconnected);
+
+ const url = new URL(`http://localhost${req.url}`);
+ this.params = url.searchParams;
+ }
+
+ protected onDisconnected() {
+ this.req.removeListener("close", this.onDisconnected);
+ this.res.removeListener("close", this.onDisconnected);
+
+ super.onDisconnected();
+ }
+
+ protected getDefaultHeaders() {
+ return {
+ "content-type": "text/event-stream",
+ "cache-control":
+ "private, no-cache, no-store, no-transform, must-revalidate, max-age=0",
+ pragma: "no-cache",
+ "x-accel-buffering": "no",
+ };
+ }
+
+ protected getHeader(name: string): string | undefined {
+ const value = this.req.headers[name];
+
+ return Array.isArray(value) ? value.join(",") : value;
+ }
+
+ protected getParam(name: string): string | undefined {
+ return this.params.get(name) ?? undefined;
+ }
+
+ protected sendHead(statusCode: number, headers: OutgoingHttpHeaders) {
+ this.res.writeHead(statusCode, headers);
+ }
+
+ protected sendChunk(chunk: string) {
+ this.res.write(chunk);
+ }
+}
+
+export {Http2CompatSession};
diff --git a/src/adapters/http2compat/createHttp2CompatSession.ts b/src/adapters/http2compat/createHttp2CompatSession.ts
new file mode 100644
index 0000000..c5f6b59
--- /dev/null
+++ b/src/adapters/http2compat/createHttp2CompatSession.ts
@@ -0,0 +1,17 @@
+import {Http2CompatSession} from "./Http2CompatSession";
+
+/**
+ * Create a new session and return the session instance once it has connected.
+ */
+const createHttp2CompatSession = (
+ ...args: ConstructorParameters>
+): Promise> =>
+ new Promise((resolve) => {
+ const session = new Http2CompatSession(...args);
+
+ session.once("connected", () => {
+ resolve(session);
+ });
+ });
+
+export {createHttp2CompatSession};
diff --git a/src/adapters/http2compat/index.ts b/src/adapters/http2compat/index.ts
new file mode 100644
index 0000000..d354266
--- /dev/null
+++ b/src/adapters/http2compat/index.ts
@@ -0,0 +1,2 @@
+export * from "./Http2CompatSession";
+export {createHttp2CompatSession as createSession} from "./createHttp2CompatSession";
diff --git a/src/createSession.test.ts b/src/createSession.test.ts
deleted file mode 100644
index 29f346e..0000000
--- a/src/createSession.test.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import {it, expect, beforeEach, afterEach} from "vitest";
-import http from "http";
-import EventSource from "eventsource";
-import {createHttpServer, closeServer, getUrl} from "./lib/testUtils";
-import {Session} from "./Session";
-import {createSession} from "./createSession";
-
-let server: http.Server;
-let url: string;
-let eventsource: EventSource;
-
-beforeEach(async () => {
- server = await createHttpServer();
-
- url = getUrl(server);
-});
-
-afterEach(async () => {
- if (eventsource && eventsource.readyState !== 2) {
- eventsource.close();
- }
-
- await closeServer(server);
-});
-
-it("resolves with an instance of a session", () =>
- new Promise((done) => {
- server.on("request", async (req, res) => {
- const session = await createSession(req, res);
-
- expect(session).toBeInstanceOf(Session);
-
- done();
- });
-
- eventsource = new EventSource(url);
- }));
diff --git a/src/createSession.ts b/src/createSession.ts
deleted file mode 100644
index 85018e0..0000000
--- a/src/createSession.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import {Session} from "./Session";
-
-/**
- * Create a new session and return the session instance once it has connected.
- */
-const createSession = (
- ...args: ConstructorParameters>
-): Promise> =>
- new Promise((resolve) => {
- const session = new Session(...args);
-
- session.once("connected", () => {
- resolve(session);
- });
- });
-
-export {createSession};
diff --git a/src/index.ts b/src/index.ts
index 7b23969..3100564 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,4 @@
export * from "./Session";
-export * from "./createSession";
export * from "./Channel";
export * from "./createChannel";
diff --git a/webpack.config.ts b/webpack.config.ts
index d0c281d..d57032b 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -8,7 +8,8 @@ const config = (): Configuration => ({
mode: "production",
devtool: "source-map",
entry: {
- index: "./src/index.ts",
+ http1: "./src/adapters/http1/index.ts",
+ http2: "./src/adapters/http2/index.ts",
},
output: {
filename: "[name].js",