diff --git a/examples/sse/package.json b/examples/sse/package.json
deleted file mode 100644
index 5179843..0000000
--- a/examples/sse/package.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "@examples/sse",
- "version": "10.38.5",
- "private": true,
- "description": "An example project for tupleson",
- "license": "MIT",
- "module": "module",
- "workspaces": [
- "client",
- "server"
- ],
- "scripts": {
- "build": "tsc",
- "dev:server": "tsx watch src/server",
- "dev": "run-p dev:* --print-label"
- },
- "devDependencies": {
- "@types/node": "^18.16.16",
- "npm-run-all": "^4.1.5",
- "tsx": "^3.12.7",
- "tupleson": "latest",
- "typescript": "^5.1.3",
- "wait-port": "^1.0.1"
- }
-}
diff --git a/examples/sse/src/index.html b/examples/sse/src/index.html
deleted file mode 100644
index 88aa0c3..0000000
--- a/examples/sse/src/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
SSE test
-
- See log output / inspector tools
-
-
-
diff --git a/examples/sse/src/server.ts b/examples/sse/src/server.ts
deleted file mode 100644
index 15dbfd0..0000000
--- a/examples/sse/src/server.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import fs from "node:fs";
-import http from "node:http";
-import { createTsonSSEResponse } from "tupleson";
-
-import { tsonOptions } from "./shared.js";
-
-const createResponse = createTsonSSEResponse(tsonOptions);
-
-const randomNumber = (min: number, max: number) =>
- Math.floor(Math.random() * (max - min + 1) + min);
-
-const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
-
-/**
- * This function returns the object we will be sending to the client.
- */
-export function getResponseShape() {
- async function* bigintGenerator() {
- const iterate = new Array(10).fill(0).map((_, i) => BigInt(i));
- for (const number of iterate) {
- await sleep(randomNumber(1, 400));
- yield number;
- }
- }
-
- async function* numberGenerator() {
- const iterate = new Array(10).fill(0).map((_, i) => i);
- for (const number of iterate) {
- await sleep(randomNumber(1, 400));
- yield number;
- }
- }
-
- return {
- bigints: bigintGenerator(),
- foo: "bar",
- numbers: numberGenerator(),
- promise: new Promise((resolve) =>
- setTimeout(() => {
- resolve(42);
- }, 1),
- ),
- rejectedPromise: new Promise((_, reject) =>
- setTimeout(() => {
- reject(new Error("Rejected promise"));
- }, 1),
- ),
- };
-}
-
-export type ResponseShape = ReturnType;
-async function handleRequest(
- req: http.IncomingMessage,
- res: http.ServerResponse,
-) {
- if (req.url?.startsWith("/sse")) {
- const obj = getResponseShape();
- const response = createResponse(obj);
-
- // Stream the response to the client
- for (const [key, value] of response.headers) {
- res.setHeader(key, value);
- }
-
- for await (const value of response.body as any) {
- res.write(value);
- }
-
- res.end();
- return;
- }
-
- const data = fs.readFileSync(__dirname + "/index.html");
- res.write(data.toString());
- res.end();
-}
-
-const server = http.createServer(
- (req: http.IncomingMessage, res: http.ServerResponse) => {
- handleRequest(req, res).catch((err) => {
- console.error(err);
- res.writeHead(500, { "Content-Type": "text/plain" });
- res.end("Internal Server Error\n");
- });
- },
-);
-
-const port = 3000;
-server.listen(port);
-
-console.log(`Server running at http://localhost:${port}`);
diff --git a/examples/sse/src/shared.ts b/examples/sse/src/shared.ts
deleted file mode 100644
index cc973f9..0000000
--- a/examples/sse/src/shared.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import {
- TsonAsyncOptions,
- tsonAsyncIterable,
- tsonBigint,
- tsonPromise,
-} from "tupleson";
-
-/**
- * Shared tupleSON options for the server and client.
- */
-export const tsonOptions: TsonAsyncOptions = {
- // We need to specify the types we want to allow serialization of
- types: [
- // Allow serialization of promises
- tsonPromise,
- // Allow serialization of async iterators
- tsonAsyncIterable,
- // Allow serialization of bigints
- tsonBigint,
- ],
-};
diff --git a/examples/sse/tsconfig.json b/examples/sse/tsconfig.json
deleted file mode 100644
index 95c6bc3..0000000
--- a/examples/sse/tsconfig.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "compilerOptions": {
- "esModuleInterop": true,
- "module": "esnext",
- "moduleResolution": "node",
- "outDir": "dist",
- "strict": true,
- "target": "esnext"
- },
- "include": ["src"]
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index aca1712..6fd40ef 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -23,6 +23,9 @@ importers:
'@types/eslint':
specifier: ^8.44.3
version: 8.44.3
+ '@types/event-source-polyfill':
+ specifier: ^1.0.2
+ version: 1.0.2
'@typescript-eslint/eslint-plugin':
specifier: ^6.7.3
version: 6.7.3(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2)
@@ -1238,6 +1241,10 @@ packages:
resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==}
dev: true
+ /@types/event-source-polyfill@1.0.2:
+ resolution: {integrity: sha512-qE5zrFd73BRs5oSjVys6g/5GboqOMbzLRTUFPAhfULvvvbRAOXw9m4Wk+p1BtoZm4JgW7TljGGfVabBqvi3eig==}
+ dev: true
+
/@types/http-cache-semantics@4.0.2:
resolution: {integrity: sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==}
dev: true
diff --git a/src/async/createTsonAsync.ts b/src/async/createTsonAsync.ts
index c23c490..7009cca 100644
--- a/src/async/createTsonAsync.ts
+++ b/src/async/createTsonAsync.ts
@@ -6,9 +6,8 @@ import {
} from "./serializeAsync.js";
/**
- * @internal
- *
* Only used for testing - when using the async you gotta pick which one you want
+ * @internal
*/
export const createTsonAsync = (opts: TsonAsyncOptions) => ({
parseJsonStream: createTsonParseAsync(opts),
diff --git a/src/async/deserializeAsync.ts b/src/async/deserializeAsync.ts
index 7fb3e85..bad1280 100644
--- a/src/async/deserializeAsync.ts
+++ b/src/async/deserializeAsync.ts
@@ -11,17 +11,12 @@ import {
} from "../sync/syncTypes.js";
import { TsonStreamInterruptedError } from "./asyncErrors.js";
import {
- BrandSerialized,
TsonAsyncIndex,
TsonAsyncOptions,
TsonAsyncStringifierIterable,
TsonAsyncType,
} from "./asyncTypes.js";
-import {
- createReadableStream,
- mapIterable,
- readableStreamToAsyncIterable,
-} from "./iterableUtils.js";
+import { createReadableStream } from "./iterableUtils.js";
import { TsonAsyncValueTuple } from "./serializeAsync.js";
type WalkFn = (value: unknown) => unknown;
@@ -85,13 +80,8 @@ export function createTsonDeserializer(opts: TsonAsyncOptions) {
const idx = serializedValue as TsonAsyncIndex;
- let controller: ReadableStreamDefaultController =
- null as unknown as ReadableStreamDefaultController;
- const readable = new ReadableStream({
- start(c) {
- controller = c;
- },
- });
+ const [readable, controller] = createReadableStream();
+
// the `start` method is called "immediately when the object is constructed"
// [MDN](http://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream)
// so we're guaranteed that the controller is set in the cache
diff --git a/src/async/iterableUtils.ts b/src/async/iterableUtils.ts
index bcddad4..a820ad6 100644
--- a/src/async/iterableUtils.ts
+++ b/src/async/iterableUtils.ts
@@ -1,4 +1,4 @@
-import { assert } from "../internals/assert";
+import { assert } from "../internals/assert.js";
export async function* readableStreamToAsyncIterable(
stream: ReadableStream,
@@ -34,7 +34,7 @@ export async function* mapIterable(
}
}
-export function createReadableStream() {
+export function createReadableStream() {
let controller: ReadableStreamDefaultController =
null as unknown as ReadableStreamDefaultController;
const stream = new ReadableStream({
diff --git a/src/async/serializeAsync.ts b/src/async/serializeAsync.ts
index 37b6525..df26b40 100644
--- a/src/async/serializeAsync.ts
+++ b/src/async/serializeAsync.ts
@@ -19,6 +19,7 @@ import {
TsonAsyncOptions,
TsonAsyncStringifier,
} from "./asyncTypes.js";
+import { createReadableStream } from "./iterableUtils.js";
type WalkFn = (value: unknown) => unknown;
@@ -253,13 +254,7 @@ export function createTsonSSEResponse(opts: TsonAsyncOptions) {
const serialize = createAsyncTsonSerialize(opts);
return (value: TValue) => {
- let controller: ReadableStreamDefaultController =
- null as unknown as ReadableStreamDefaultController;
- const readable = new ReadableStream({
- start(c) {
- controller = c;
- },
- });
+ const [readable, controller] = createReadableStream();
async function iterate() {
const [head, iterable] = serialize(value);
diff --git a/src/async/sse.test.ts b/src/async/sse.test.ts
index 2778556..a380aa2 100644
--- a/src/async/sse.test.ts
+++ b/src/async/sse.test.ts
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
import { EventSourcePolyfill, NativeEventSource } from "event-source-polyfill";
import { expect, test } from "vitest";
-global.EventSource = NativeEventSource || EventSourcePolyfill;
+(global as any).EventSource = NativeEventSource || EventSourcePolyfill;
import { TsonAsyncOptions, tsonAsyncIterable, tsonPromise } from "../index.js";
import { createTestServer, sleep } from "../internals/testUtils.js";