@react-router/node 7.18.0 → 8.0.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,15 @@
1
- import { RequestListener } from 'node:http';
2
- import { ServerBuild, UNSAFE_MiddlewareEnabled, RouterContextProvider, AppLoadContext, SessionData, SessionIdStorageStrategy, SessionStorage } from 'react-router';
3
- import { ClientAddress } from '@mjackson/node-fetch-server';
4
- import { Readable, Writable } from 'node:stream';
5
1
 
2
+ import { ClientAddress } from "@remix-run/node-fetch-server";
3
+ import { RouterContextProvider, ServerBuild, SessionData, SessionIdStorageStrategy, SessionStorage } from "react-router";
4
+ import { Readable, Writable } from "node:stream";
5
+ import { RequestListener } from "node:http";
6
+
7
+ //#region server.d.ts
6
8
  type MaybePromise<T> = T | Promise<T>;
7
9
  interface RequestListenerOptions {
8
- build: ServerBuild | (() => ServerBuild | Promise<ServerBuild>);
9
- getLoadContext?: (request: Request, client: ClientAddress) => UNSAFE_MiddlewareEnabled extends true ? MaybePromise<RouterContextProvider> : MaybePromise<AppLoadContext>;
10
- mode?: string;
10
+ build: ServerBuild | (() => ServerBuild | Promise<ServerBuild>);
11
+ getLoadContext?: (request: Request, client: ClientAddress) => MaybePromise<RouterContextProvider>;
12
+ mode?: string;
11
13
  }
12
14
  /**
13
15
  * Creates a request listener that handles requests using Node's built-in HTTP server.
@@ -16,17 +18,18 @@ interface RequestListenerOptions {
16
18
  * @returns A request listener that can be used with `http.createServer`.
17
19
  */
18
20
  declare function createRequestListener(options: RequestListenerOptions): RequestListener;
19
-
21
+ //#endregion
22
+ //#region sessions/fileStorage.d.ts
20
23
  interface FileSessionStorageOptions {
21
- /**
22
- * The Cookie used to store the session id on the client, or options used
23
- * to automatically create one.
24
- */
25
- cookie?: SessionIdStorageStrategy["cookie"];
26
- /**
27
- * The directory to use to store session files.
28
- */
29
- dir: string;
24
+ /**
25
+ * The Cookie used to store the session id on the client, or options used
26
+ * to automatically create one.
27
+ */
28
+ cookie?: SessionIdStorageStrategy["cookie"];
29
+ /**
30
+ * The directory to use to store session files.
31
+ */
32
+ dir: string;
30
33
  }
31
34
  /**
32
35
  * Creates a SessionStorage that stores session data on a filesystem.
@@ -36,13 +39,17 @@ interface FileSessionStorageOptions {
36
39
  *
37
40
  * @see https://api.reactrouter.com/v7/functions/_react-router_node.createFileSessionStorage
38
41
  */
39
- declare function createFileSessionStorage<Data = SessionData, FlashData = Data>({ cookie, dir, }: FileSessionStorageOptions): SessionStorage<Data, FlashData>;
40
-
42
+ declare function createFileSessionStorage<Data = SessionData, FlashData = Data>({
43
+ cookie,
44
+ dir
45
+ }: FileSessionStorageOptions): SessionStorage<Data, FlashData>;
46
+ //#endregion
47
+ //#region stream.d.ts
41
48
  declare function writeReadableStreamToWritable(stream: ReadableStream, writable: Writable): Promise<void>;
42
49
  declare function writeAsyncIterableToWritable(iterable: AsyncIterable<Uint8Array>, writable: Writable): Promise<void>;
43
50
  declare function readableStreamToString(stream: ReadableStream<Uint8Array>, encoding?: BufferEncoding): Promise<string>;
44
51
  declare const createReadableStreamFromReadable: (source: Readable & {
45
- readableHighWaterMark?: number;
46
- }) => ReadableStream<Uint8Array>;
47
-
48
- export { type RequestListenerOptions, createFileSessionStorage, createReadableStreamFromReadable, createRequestListener, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable };
52
+ readableHighWaterMark?: number;
53
+ }) => ReadableStream<Uint8Array<ArrayBufferLike>>;
54
+ //#endregion
55
+ export { type RequestListenerOptions, createFileSessionStorage, createReadableStreamFromReadable, createRequestListener, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/node v7.18.0
2
+ * @react-router/node v8.0.0-pre.1
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -8,371 +8,286 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- "use strict";
12
- var __create = Object.create;
13
- var __defProp = Object.defineProperty;
14
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
15
- var __getOwnPropNames = Object.getOwnPropertyNames;
16
- var __getProtoOf = Object.getPrototypeOf;
17
- var __hasOwnProp = Object.prototype.hasOwnProperty;
18
- var __export = (target, all) => {
19
- for (var name in all)
20
- __defProp(target, name, { get: all[name], enumerable: true });
21
- };
22
- var __copyProps = (to, from, except, desc) => {
23
- if (from && typeof from === "object" || typeof from === "function") {
24
- for (let key of __getOwnPropNames(from))
25
- if (!__hasOwnProp.call(to, key) && key !== except)
26
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
27
- }
28
- return to;
29
- };
30
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
31
- // If the importer is in node compatibility mode or this is not an ESM
32
- // file that has been converted to a CommonJS file using a Babel-
33
- // compatible transform (i.e. "__esModule" has not been set), then set
34
- // "default" to the CommonJS "module.exports" for node compatibility.
35
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
36
- mod
37
- ));
38
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
39
-
40
- // index.ts
41
- var index_exports = {};
42
- __export(index_exports, {
43
- createFileSessionStorage: () => createFileSessionStorage,
44
- createReadableStreamFromReadable: () => createReadableStreamFromReadable,
45
- createRequestListener: () => createRequestListener,
46
- readableStreamToString: () => readableStreamToString,
47
- writeAsyncIterableToWritable: () => writeAsyncIterableToWritable,
48
- writeReadableStreamToWritable: () => writeReadableStreamToWritable
49
- });
50
- module.exports = __toCommonJS(index_exports);
51
-
52
- // server.ts
53
- var import_react_router = require("react-router");
54
- var import_node_fetch_server = require("@mjackson/node-fetch-server");
11
+ import { createRequestListener as createRequestListener$1 } from "@remix-run/node-fetch-server";
12
+ import { createRequestHandler, createSessionStorage } from "react-router";
13
+ import { promises } from "node:fs";
14
+ import * as path from "node:path";
15
+ import { Stream } from "node:stream";
16
+ //#region server.ts
17
+ /**
18
+ * Creates a request listener that handles requests using Node's built-in HTTP server.
19
+ *
20
+ * @param options Options for creating a request listener.
21
+ * @returns A request listener that can be used with `http.createServer`.
22
+ */
55
23
  function createRequestListener(options) {
56
- let handleRequest = (0, import_react_router.createRequestHandler)(options.build, options.mode);
57
- return (0, import_node_fetch_server.createRequestListener)(async (request, client) => {
58
- let loadContext = await options.getLoadContext?.(request, client);
59
- return handleRequest(request, loadContext);
60
- });
24
+ let handleRequest = createRequestHandler(options.build, options.mode);
25
+ return createRequestListener$1(async (request, client) => {
26
+ return handleRequest(request, await options.getLoadContext?.(request, client));
27
+ });
61
28
  }
62
-
63
- // sessions/fileStorage.ts
64
- var import_node_fs = require("fs");
65
- var path = __toESM(require("path"));
66
- var import_react_router2 = require("react-router");
67
- function createFileSessionStorage({
68
- cookie,
69
- dir
70
- }) {
71
- return (0, import_react_router2.createSessionStorage)({
72
- cookie,
73
- async createData(data, expires) {
74
- let content = JSON.stringify({ data, expires });
75
- while (true) {
76
- let randomBytes = crypto.getRandomValues(new Uint8Array(8));
77
- let id = Buffer.from(randomBytes).toString("hex");
78
- try {
79
- let file = getFile(dir, id);
80
- if (!file) {
81
- throw new Error("Error generating session");
82
- }
83
- await import_node_fs.promises.mkdir(path.dirname(file), { recursive: true });
84
- await import_node_fs.promises.writeFile(file, content, { encoding: "utf-8", flag: "wx" });
85
- return id;
86
- } catch (error) {
87
- if (error.code !== "EEXIST") throw error;
88
- }
89
- }
90
- },
91
- async readData(id) {
92
- try {
93
- let file = getFile(dir, id);
94
- if (!file) {
95
- return null;
96
- }
97
- let content = JSON.parse(await import_node_fs.promises.readFile(file, "utf-8"));
98
- let data = content.data;
99
- let expires = typeof content.expires === "string" ? new Date(content.expires) : null;
100
- if (!expires || expires > /* @__PURE__ */ new Date()) {
101
- return data;
102
- }
103
- if (expires) await import_node_fs.promises.unlink(file);
104
- return null;
105
- } catch (error) {
106
- if (error.code !== "ENOENT") throw error;
107
- return null;
108
- }
109
- },
110
- async updateData(id, data, expires) {
111
- let content = JSON.stringify({ data, expires });
112
- let file = getFile(dir, id);
113
- if (!file) {
114
- return;
115
- }
116
- await import_node_fs.promises.mkdir(path.dirname(file), { recursive: true });
117
- await import_node_fs.promises.writeFile(file, content, "utf-8");
118
- },
119
- async deleteData(id) {
120
- if (!id) {
121
- return;
122
- }
123
- let file = getFile(dir, id);
124
- if (!file) {
125
- return;
126
- }
127
- try {
128
- await import_node_fs.promises.unlink(file);
129
- } catch (error) {
130
- if (error.code !== "ENOENT") throw error;
131
- }
132
- }
133
- });
29
+ //#endregion
30
+ //#region sessions/fileStorage.ts
31
+ /**
32
+ * Creates a SessionStorage that stores session data on a filesystem.
33
+ *
34
+ * The advantage of using this instead of cookie session storage is that
35
+ * files may contain much more data than cookies.
36
+ *
37
+ * @see https://api.reactrouter.com/v7/functions/_react-router_node.createFileSessionStorage
38
+ */
39
+ function createFileSessionStorage({ cookie, dir }) {
40
+ return createSessionStorage({
41
+ cookie,
42
+ async createData(data, expires) {
43
+ let content = JSON.stringify({
44
+ data,
45
+ expires
46
+ });
47
+ while (true) {
48
+ let randomBytes = crypto.getRandomValues(new Uint8Array(8));
49
+ let id = Buffer.from(randomBytes).toString("hex");
50
+ try {
51
+ let file = getFile(dir, id);
52
+ if (!file) throw new Error("Error generating session");
53
+ await promises.mkdir(path.dirname(file), { recursive: true });
54
+ await promises.writeFile(file, content, {
55
+ encoding: "utf-8",
56
+ flag: "wx"
57
+ });
58
+ return id;
59
+ } catch (error) {
60
+ if (error.code !== "EEXIST") throw error;
61
+ }
62
+ }
63
+ },
64
+ async readData(id) {
65
+ try {
66
+ let file = getFile(dir, id);
67
+ if (!file) return null;
68
+ let content = JSON.parse(await promises.readFile(file, "utf-8"));
69
+ let data = content.data;
70
+ let expires = typeof content.expires === "string" ? new Date(content.expires) : null;
71
+ if (!expires || expires > /* @__PURE__ */ new Date()) return data;
72
+ if (expires) await promises.unlink(file);
73
+ return null;
74
+ } catch (error) {
75
+ if (error.code !== "ENOENT") throw error;
76
+ return null;
77
+ }
78
+ },
79
+ async updateData(id, data, expires) {
80
+ let content = JSON.stringify({
81
+ data,
82
+ expires
83
+ });
84
+ let file = getFile(dir, id);
85
+ if (!file) return;
86
+ await promises.mkdir(path.dirname(file), { recursive: true });
87
+ await promises.writeFile(file, content, "utf-8");
88
+ },
89
+ async deleteData(id) {
90
+ if (!id) return;
91
+ let file = getFile(dir, id);
92
+ if (!file) return;
93
+ try {
94
+ await promises.unlink(file);
95
+ } catch (error) {
96
+ if (error.code !== "ENOENT") throw error;
97
+ }
98
+ }
99
+ });
134
100
  }
135
101
  function getFile(dir, id) {
136
- if (!/^[0-9a-f]{16}$/i.test(id)) {
137
- return null;
138
- }
139
- return path.join(dir, id.slice(0, 4), id.slice(4));
102
+ if (!/^[0-9a-f]{16}$/i.test(id)) return null;
103
+ return path.join(dir, id.slice(0, 4), id.slice(4));
140
104
  }
141
-
142
- // stream.ts
143
- var import_node_stream = require("stream");
105
+ //#endregion
106
+ //#region stream.ts
144
107
  async function writeReadableStreamToWritable(stream, writable) {
145
- let reader = stream.getReader();
146
- let flushable = writable;
147
- let writableError = monitorWritableError(writable);
148
- try {
149
- while (true) {
150
- writableError.throwIfClosed();
151
- let { done, value } = await writableError.race(reader.read());
152
- if (done) {
153
- writable.end();
154
- break;
155
- }
156
- writableError.throwIfClosed();
157
- let canContinueWriting = writable.write(value);
158
- if (typeof flushable.flush === "function") {
159
- flushable.flush();
160
- }
161
- if (!canContinueWriting) {
162
- await waitForDrain(writable, writableError);
163
- }
164
- }
165
- } catch (error) {
166
- try {
167
- reader.cancel(error).catch(() => {
168
- });
169
- } catch {
170
- }
171
- writable.destroy(error);
172
- throw error;
173
- } finally {
174
- writableError.cleanup();
175
- try {
176
- reader.releaseLock();
177
- } catch {
178
- }
179
- }
108
+ let reader = stream.getReader();
109
+ let flushable = writable;
110
+ let writableError = monitorWritableError(writable);
111
+ try {
112
+ while (true) {
113
+ writableError.throwIfClosed();
114
+ let { done, value } = await writableError.race(reader.read());
115
+ if (done) {
116
+ writable.end();
117
+ break;
118
+ }
119
+ writableError.throwIfClosed();
120
+ let canContinueWriting = writable.write(value);
121
+ if (typeof flushable.flush === "function") flushable.flush();
122
+ if (!canContinueWriting) await waitForDrain(writable, writableError);
123
+ }
124
+ } catch (error) {
125
+ try {
126
+ reader.cancel(error).catch(() => {});
127
+ } catch {}
128
+ writable.destroy(error);
129
+ throw error;
130
+ } finally {
131
+ writableError.cleanup();
132
+ try {
133
+ reader.releaseLock();
134
+ } catch {}
135
+ }
180
136
  }
181
137
  function monitorWritableError(writable) {
182
- let settled = false;
183
- let writableError;
184
- let rejectWritableError;
185
- let writableErrorPromise = new Promise((_, reject2) => {
186
- rejectWritableError = reject2;
187
- });
188
- writableErrorPromise.catch(() => {
189
- });
190
- function cleanup() {
191
- writable.off("error", onError);
192
- writable.off("close", onClose);
193
- }
194
- function reject(error) {
195
- if (settled) {
196
- return;
197
- }
198
- settled = true;
199
- writableError = error;
200
- cleanup();
201
- rejectWritableError(error);
202
- }
203
- function onError(error) {
204
- reject(error);
205
- }
206
- function onClose() {
207
- reject(new Error("Writable closed before stream finished"));
208
- }
209
- writable.once("error", onError);
210
- writable.once("close", onClose);
211
- return {
212
- cleanup,
213
- race(promise) {
214
- return Promise.race([promise, writableErrorPromise]);
215
- },
216
- throwIfClosed() {
217
- if (writableError) {
218
- throw writableError;
219
- }
220
- if (writable.destroyed || writable.writableEnded) {
221
- throw new Error("Cannot write to a destroyed or ended writable stream");
222
- }
223
- }
224
- };
138
+ let settled = false;
139
+ let writableError;
140
+ let rejectWritableError;
141
+ let writableErrorPromise = new Promise((_, reject) => {
142
+ rejectWritableError = reject;
143
+ });
144
+ writableErrorPromise.catch(() => {});
145
+ function cleanup() {
146
+ writable.off("error", onError);
147
+ writable.off("close", onClose);
148
+ }
149
+ function reject(error) {
150
+ if (settled) return;
151
+ settled = true;
152
+ writableError = error;
153
+ cleanup();
154
+ rejectWritableError(error);
155
+ }
156
+ function onError(error) {
157
+ reject(error);
158
+ }
159
+ function onClose() {
160
+ reject(/* @__PURE__ */ new Error("Writable closed before stream finished"));
161
+ }
162
+ writable.once("error", onError);
163
+ writable.once("close", onClose);
164
+ return {
165
+ cleanup,
166
+ race(promise) {
167
+ return Promise.race([promise, writableErrorPromise]);
168
+ },
169
+ throwIfClosed() {
170
+ if (writableError) throw writableError;
171
+ if (writable.destroyed || writable.writableEnded) throw new Error("Cannot write to a destroyed or ended writable stream");
172
+ }
173
+ };
225
174
  }
226
175
  function waitForDrain(writable, writableError) {
227
- let cleanup = () => {
228
- };
229
- let drainPromise = new Promise((resolve) => {
230
- function onDrain() {
231
- cleanup();
232
- resolve();
233
- }
234
- cleanup = function cleanup2() {
235
- writable.off("drain", onDrain);
236
- };
237
- writable.once("drain", onDrain);
238
- });
239
- return writableError.race(drainPromise).finally(cleanup);
176
+ let cleanup = () => {};
177
+ let drainPromise = new Promise((resolve) => {
178
+ function onDrain() {
179
+ cleanup();
180
+ resolve();
181
+ }
182
+ cleanup = function cleanup() {
183
+ writable.off("drain", onDrain);
184
+ };
185
+ writable.once("drain", onDrain);
186
+ });
187
+ return writableError.race(drainPromise).finally(cleanup);
240
188
  }
241
189
  async function writeAsyncIterableToWritable(iterable, writable) {
242
- let writableError = monitorWritableError(writable);
243
- let iterator = iterable[Symbol.asyncIterator]();
244
- let completed = false;
245
- try {
246
- while (true) {
247
- writableError.throwIfClosed();
248
- let { done, value: chunk } = await writableError.race(iterator.next());
249
- if (done) {
250
- completed = true;
251
- break;
252
- }
253
- writableError.throwIfClosed();
254
- let canContinueWriting = writable.write(chunk);
255
- if (!canContinueWriting) {
256
- await waitForDrain(writable, writableError);
257
- }
258
- }
259
- writable.end();
260
- } catch (error) {
261
- if (!completed) {
262
- try {
263
- Promise.resolve(iterator.return?.()).catch(() => {
264
- });
265
- } catch {
266
- }
267
- }
268
- writable.destroy(error);
269
- throw error;
270
- } finally {
271
- writableError.cleanup();
272
- }
190
+ let writableError = monitorWritableError(writable);
191
+ let iterator = iterable[Symbol.asyncIterator]();
192
+ let completed = false;
193
+ try {
194
+ while (true) {
195
+ writableError.throwIfClosed();
196
+ let { done, value: chunk } = await writableError.race(iterator.next());
197
+ if (done) {
198
+ completed = true;
199
+ break;
200
+ }
201
+ writableError.throwIfClosed();
202
+ if (!writable.write(chunk)) await waitForDrain(writable, writableError);
203
+ }
204
+ writable.end();
205
+ } catch (error) {
206
+ if (!completed) try {
207
+ Promise.resolve(iterator.return?.()).catch(() => {});
208
+ } catch {}
209
+ writable.destroy(error);
210
+ throw error;
211
+ } finally {
212
+ writableError.cleanup();
213
+ }
273
214
  }
274
215
  async function readableStreamToString(stream, encoding) {
275
- let reader = stream.getReader();
276
- let chunks = [];
277
- while (true) {
278
- let { done, value } = await reader.read();
279
- if (done) {
280
- break;
281
- }
282
- if (value) {
283
- chunks.push(value);
284
- }
285
- }
286
- return Buffer.concat(chunks).toString(encoding);
216
+ let reader = stream.getReader();
217
+ let chunks = [];
218
+ while (true) {
219
+ let { done, value } = await reader.read();
220
+ if (done) break;
221
+ if (value) chunks.push(value);
222
+ }
223
+ return Buffer.concat(chunks).toString(encoding);
287
224
  }
288
- var createReadableStreamFromReadable = (source) => {
289
- let pump = new StreamPump(source);
290
- let stream = new ReadableStream(pump, pump);
291
- return stream;
225
+ const createReadableStreamFromReadable = (source) => {
226
+ let pump = new StreamPump(source);
227
+ return new ReadableStream(pump, pump);
292
228
  };
293
229
  var StreamPump = class {
294
- highWaterMark;
295
- accumulatedSize;
296
- stream;
297
- controller;
298
- constructor(stream) {
299
- this.highWaterMark = stream.readableHighWaterMark || new import_node_stream.Stream.Readable().readableHighWaterMark;
300
- this.accumulatedSize = 0;
301
- this.stream = stream;
302
- this.enqueue = this.enqueue.bind(this);
303
- this.error = this.error.bind(this);
304
- this.close = this.close.bind(this);
305
- }
306
- size(chunk) {
307
- return chunk?.byteLength || 0;
308
- }
309
- start(controller) {
310
- this.controller = controller;
311
- this.stream.on("data", this.enqueue);
312
- this.stream.once("error", this.error);
313
- this.stream.once("end", this.close);
314
- this.stream.once("close", this.close);
315
- }
316
- pull() {
317
- this.resume();
318
- }
319
- cancel(reason) {
320
- if (this.stream.destroy) {
321
- this.stream.destroy(reason);
322
- }
323
- this.stream.off("data", this.enqueue);
324
- this.stream.off("error", this.error);
325
- this.stream.off("end", this.close);
326
- this.stream.off("close", this.close);
327
- }
328
- enqueue(chunk) {
329
- if (this.controller) {
330
- try {
331
- let bytes = chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
332
- let available = (this.controller.desiredSize || 0) - bytes.byteLength;
333
- this.controller.enqueue(bytes);
334
- if (available <= 0) {
335
- this.pause();
336
- }
337
- } catch (e) {
338
- this.controller.error(
339
- new Error(
340
- "Could not create Buffer, chunk must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object"
341
- )
342
- );
343
- this.cancel();
344
- }
345
- }
346
- }
347
- pause() {
348
- if (this.stream.pause) {
349
- this.stream.pause();
350
- }
351
- }
352
- resume() {
353
- if (this.stream.readable && this.stream.resume) {
354
- this.stream.resume();
355
- }
356
- }
357
- close() {
358
- if (this.controller) {
359
- this.controller.close();
360
- delete this.controller;
361
- }
362
- }
363
- error(error) {
364
- if (this.controller) {
365
- this.controller.error(error);
366
- delete this.controller;
367
- }
368
- }
230
+ highWaterMark;
231
+ accumulatedSize;
232
+ stream;
233
+ controller;
234
+ constructor(stream) {
235
+ this.highWaterMark = stream.readableHighWaterMark || new Stream.Readable().readableHighWaterMark;
236
+ this.accumulatedSize = 0;
237
+ this.stream = stream;
238
+ this.enqueue = this.enqueue.bind(this);
239
+ this.error = this.error.bind(this);
240
+ this.close = this.close.bind(this);
241
+ }
242
+ size(chunk) {
243
+ return chunk?.byteLength || 0;
244
+ }
245
+ start(controller) {
246
+ this.controller = controller;
247
+ this.stream.on("data", this.enqueue);
248
+ this.stream.once("error", this.error);
249
+ this.stream.once("end", this.close);
250
+ this.stream.once("close", this.close);
251
+ }
252
+ pull() {
253
+ this.resume();
254
+ }
255
+ cancel(reason) {
256
+ if (this.stream.destroy) this.stream.destroy(reason);
257
+ this.stream.off("data", this.enqueue);
258
+ this.stream.off("error", this.error);
259
+ this.stream.off("end", this.close);
260
+ this.stream.off("close", this.close);
261
+ }
262
+ enqueue(chunk) {
263
+ if (this.controller) try {
264
+ let bytes = typeof chunk === "string" ? Buffer.from(chunk) : new Uint8Array(chunk);
265
+ let available = (this.controller.desiredSize || 0) - bytes.byteLength;
266
+ this.controller.enqueue(bytes);
267
+ if (available <= 0) this.pause();
268
+ } catch (e) {
269
+ this.controller.error(/* @__PURE__ */ new Error("Could not create Buffer, chunk must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object"));
270
+ this.cancel();
271
+ }
272
+ }
273
+ pause() {
274
+ if (this.stream.pause) this.stream.pause();
275
+ }
276
+ resume() {
277
+ if (this.stream.readable && this.stream.resume) this.stream.resume();
278
+ }
279
+ close() {
280
+ if (this.controller) {
281
+ this.controller.close();
282
+ delete this.controller;
283
+ }
284
+ }
285
+ error(error) {
286
+ if (this.controller) {
287
+ this.controller.error(error);
288
+ delete this.controller;
289
+ }
290
+ }
369
291
  };
370
- // Annotate the CommonJS export names for ESM import in node:
371
- 0 && (module.exports = {
372
- createFileSessionStorage,
373
- createReadableStreamFromReadable,
374
- createRequestListener,
375
- readableStreamToString,
376
- writeAsyncIterableToWritable,
377
- writeReadableStreamToWritable
378
- });
292
+ //#endregion
293
+ export { createFileSessionStorage, createReadableStreamFromReadable, createRequestListener, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable };
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@react-router/node",
3
- "version": "7.18.0",
3
+ "type": "module",
4
+ "version": "8.0.0-pre.1",
4
5
  "description": "Node.js platform abstractions for React Router",
5
6
  "bugs": {
6
7
  "url": "https://github.com/remix-run/react-router/issues"
@@ -15,25 +16,15 @@
15
16
  "main": "dist/index.js",
16
17
  "exports": {
17
18
  ".": {
18
- "node": {
19
- "types": "./dist/index.d.ts",
20
- "module-sync": "./dist/index.mjs",
21
- "default": "./dist/index.js"
22
- },
23
- "import": {
24
- "types": "./dist/index.d.mts",
25
- "default": "./dist/index.mjs"
26
- },
27
- "default": {
28
- "types": "./dist/index.d.ts",
29
- "default": "./dist/index.js"
30
- }
19
+ "types": "./dist/index.d.ts",
20
+ "module-sync": "./dist/index.js",
21
+ "default": "./dist/index.js"
31
22
  },
32
23
  "./package.json": "./package.json"
33
24
  },
34
25
  "wireit": {
35
26
  "build": {
36
- "command": "tsup",
27
+ "command": "tsdown",
37
28
  "files": [
38
29
  "../../pnpm-workspace.yaml",
39
30
  "sessions/**",
@@ -47,17 +38,18 @@
47
38
  }
48
39
  },
49
40
  "dependencies": {
50
- "@mjackson/node-fetch-server": "^0.2.0"
41
+ "@remix-run/node-fetch-server": "^0.13.3"
51
42
  },
52
43
  "devDependencies": {
53
- "tsup": "^8.3.0",
54
- "typescript": "^5.4.5",
55
- "wireit": "0.14.9",
56
- "react-router": "7.18.0"
44
+ "@types/node": "^22.19.19",
45
+ "tsdown": "^0.22.0",
46
+ "typescript": "^6.0.3",
47
+ "wireit": "0.14.12",
48
+ "react-router": "8.0.0-pre.1"
57
49
  },
58
50
  "peerDependencies": {
59
51
  "typescript": "^5.1.0 || ^6.0.0",
60
- "react-router": "7.18.0"
52
+ "react-router": "8.0.0-pre.1"
61
53
  },
62
54
  "peerDependenciesMeta": {
63
55
  "typescript": {
@@ -65,7 +57,7 @@
65
57
  }
66
58
  },
67
59
  "engines": {
68
- "node": ">=20.0.0"
60
+ "node": ">=22.22.0"
69
61
  },
70
62
  "files": [
71
63
  "dist/",
package/dist/index.d.mts DELETED
@@ -1,48 +0,0 @@
1
- import { RequestListener } from 'node:http';
2
- import { ServerBuild, UNSAFE_MiddlewareEnabled, RouterContextProvider, AppLoadContext, SessionData, SessionIdStorageStrategy, SessionStorage } from 'react-router';
3
- import { ClientAddress } from '@mjackson/node-fetch-server';
4
- import { Readable, Writable } from 'node:stream';
5
-
6
- type MaybePromise<T> = T | Promise<T>;
7
- interface RequestListenerOptions {
8
- build: ServerBuild | (() => ServerBuild | Promise<ServerBuild>);
9
- getLoadContext?: (request: Request, client: ClientAddress) => UNSAFE_MiddlewareEnabled extends true ? MaybePromise<RouterContextProvider> : MaybePromise<AppLoadContext>;
10
- mode?: string;
11
- }
12
- /**
13
- * Creates a request listener that handles requests using Node's built-in HTTP server.
14
- *
15
- * @param options Options for creating a request listener.
16
- * @returns A request listener that can be used with `http.createServer`.
17
- */
18
- declare function createRequestListener(options: RequestListenerOptions): RequestListener;
19
-
20
- interface FileSessionStorageOptions {
21
- /**
22
- * The Cookie used to store the session id on the client, or options used
23
- * to automatically create one.
24
- */
25
- cookie?: SessionIdStorageStrategy["cookie"];
26
- /**
27
- * The directory to use to store session files.
28
- */
29
- dir: string;
30
- }
31
- /**
32
- * Creates a SessionStorage that stores session data on a filesystem.
33
- *
34
- * The advantage of using this instead of cookie session storage is that
35
- * files may contain much more data than cookies.
36
- *
37
- * @see https://api.reactrouter.com/v7/functions/_react-router_node.createFileSessionStorage
38
- */
39
- declare function createFileSessionStorage<Data = SessionData, FlashData = Data>({ cookie, dir, }: FileSessionStorageOptions): SessionStorage<Data, FlashData>;
40
-
41
- declare function writeReadableStreamToWritable(stream: ReadableStream, writable: Writable): Promise<void>;
42
- declare function writeAsyncIterableToWritable(iterable: AsyncIterable<Uint8Array>, writable: Writable): Promise<void>;
43
- declare function readableStreamToString(stream: ReadableStream<Uint8Array>, encoding?: BufferEncoding): Promise<string>;
44
- declare const createReadableStreamFromReadable: (source: Readable & {
45
- readableHighWaterMark?: number;
46
- }) => ReadableStream<Uint8Array>;
47
-
48
- export { type RequestListenerOptions, createFileSessionStorage, createReadableStreamFromReadable, createRequestListener, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable };
package/dist/index.mjs DELETED
@@ -1,337 +0,0 @@
1
- /**
2
- * @react-router/node v7.18.0
3
- *
4
- * Copyright (c) Remix Software Inc.
5
- *
6
- * This source code is licensed under the MIT license found in the
7
- * LICENSE.md file in the root directory of this source tree.
8
- *
9
- * @license MIT
10
- */
11
-
12
- // server.ts
13
- import { createRequestHandler } from "react-router";
14
- import { createRequestListener as createRequestListener_ } from "@mjackson/node-fetch-server";
15
- function createRequestListener(options) {
16
- let handleRequest = createRequestHandler(options.build, options.mode);
17
- return createRequestListener_(async (request, client) => {
18
- let loadContext = await options.getLoadContext?.(request, client);
19
- return handleRequest(request, loadContext);
20
- });
21
- }
22
-
23
- // sessions/fileStorage.ts
24
- import { promises as fsp } from "fs";
25
- import * as path from "path";
26
- import { createSessionStorage } from "react-router";
27
- function createFileSessionStorage({
28
- cookie,
29
- dir
30
- }) {
31
- return createSessionStorage({
32
- cookie,
33
- async createData(data, expires) {
34
- let content = JSON.stringify({ data, expires });
35
- while (true) {
36
- let randomBytes = crypto.getRandomValues(new Uint8Array(8));
37
- let id = Buffer.from(randomBytes).toString("hex");
38
- try {
39
- let file = getFile(dir, id);
40
- if (!file) {
41
- throw new Error("Error generating session");
42
- }
43
- await fsp.mkdir(path.dirname(file), { recursive: true });
44
- await fsp.writeFile(file, content, { encoding: "utf-8", flag: "wx" });
45
- return id;
46
- } catch (error) {
47
- if (error.code !== "EEXIST") throw error;
48
- }
49
- }
50
- },
51
- async readData(id) {
52
- try {
53
- let file = getFile(dir, id);
54
- if (!file) {
55
- return null;
56
- }
57
- let content = JSON.parse(await fsp.readFile(file, "utf-8"));
58
- let data = content.data;
59
- let expires = typeof content.expires === "string" ? new Date(content.expires) : null;
60
- if (!expires || expires > /* @__PURE__ */ new Date()) {
61
- return data;
62
- }
63
- if (expires) await fsp.unlink(file);
64
- return null;
65
- } catch (error) {
66
- if (error.code !== "ENOENT") throw error;
67
- return null;
68
- }
69
- },
70
- async updateData(id, data, expires) {
71
- let content = JSON.stringify({ data, expires });
72
- let file = getFile(dir, id);
73
- if (!file) {
74
- return;
75
- }
76
- await fsp.mkdir(path.dirname(file), { recursive: true });
77
- await fsp.writeFile(file, content, "utf-8");
78
- },
79
- async deleteData(id) {
80
- if (!id) {
81
- return;
82
- }
83
- let file = getFile(dir, id);
84
- if (!file) {
85
- return;
86
- }
87
- try {
88
- await fsp.unlink(file);
89
- } catch (error) {
90
- if (error.code !== "ENOENT") throw error;
91
- }
92
- }
93
- });
94
- }
95
- function getFile(dir, id) {
96
- if (!/^[0-9a-f]{16}$/i.test(id)) {
97
- return null;
98
- }
99
- return path.join(dir, id.slice(0, 4), id.slice(4));
100
- }
101
-
102
- // stream.ts
103
- import { Stream } from "stream";
104
- async function writeReadableStreamToWritable(stream, writable) {
105
- let reader = stream.getReader();
106
- let flushable = writable;
107
- let writableError = monitorWritableError(writable);
108
- try {
109
- while (true) {
110
- writableError.throwIfClosed();
111
- let { done, value } = await writableError.race(reader.read());
112
- if (done) {
113
- writable.end();
114
- break;
115
- }
116
- writableError.throwIfClosed();
117
- let canContinueWriting = writable.write(value);
118
- if (typeof flushable.flush === "function") {
119
- flushable.flush();
120
- }
121
- if (!canContinueWriting) {
122
- await waitForDrain(writable, writableError);
123
- }
124
- }
125
- } catch (error) {
126
- try {
127
- reader.cancel(error).catch(() => {
128
- });
129
- } catch {
130
- }
131
- writable.destroy(error);
132
- throw error;
133
- } finally {
134
- writableError.cleanup();
135
- try {
136
- reader.releaseLock();
137
- } catch {
138
- }
139
- }
140
- }
141
- function monitorWritableError(writable) {
142
- let settled = false;
143
- let writableError;
144
- let rejectWritableError;
145
- let writableErrorPromise = new Promise((_, reject2) => {
146
- rejectWritableError = reject2;
147
- });
148
- writableErrorPromise.catch(() => {
149
- });
150
- function cleanup() {
151
- writable.off("error", onError);
152
- writable.off("close", onClose);
153
- }
154
- function reject(error) {
155
- if (settled) {
156
- return;
157
- }
158
- settled = true;
159
- writableError = error;
160
- cleanup();
161
- rejectWritableError(error);
162
- }
163
- function onError(error) {
164
- reject(error);
165
- }
166
- function onClose() {
167
- reject(new Error("Writable closed before stream finished"));
168
- }
169
- writable.once("error", onError);
170
- writable.once("close", onClose);
171
- return {
172
- cleanup,
173
- race(promise) {
174
- return Promise.race([promise, writableErrorPromise]);
175
- },
176
- throwIfClosed() {
177
- if (writableError) {
178
- throw writableError;
179
- }
180
- if (writable.destroyed || writable.writableEnded) {
181
- throw new Error("Cannot write to a destroyed or ended writable stream");
182
- }
183
- }
184
- };
185
- }
186
- function waitForDrain(writable, writableError) {
187
- let cleanup = () => {
188
- };
189
- let drainPromise = new Promise((resolve) => {
190
- function onDrain() {
191
- cleanup();
192
- resolve();
193
- }
194
- cleanup = function cleanup2() {
195
- writable.off("drain", onDrain);
196
- };
197
- writable.once("drain", onDrain);
198
- });
199
- return writableError.race(drainPromise).finally(cleanup);
200
- }
201
- async function writeAsyncIterableToWritable(iterable, writable) {
202
- let writableError = monitorWritableError(writable);
203
- let iterator = iterable[Symbol.asyncIterator]();
204
- let completed = false;
205
- try {
206
- while (true) {
207
- writableError.throwIfClosed();
208
- let { done, value: chunk } = await writableError.race(iterator.next());
209
- if (done) {
210
- completed = true;
211
- break;
212
- }
213
- writableError.throwIfClosed();
214
- let canContinueWriting = writable.write(chunk);
215
- if (!canContinueWriting) {
216
- await waitForDrain(writable, writableError);
217
- }
218
- }
219
- writable.end();
220
- } catch (error) {
221
- if (!completed) {
222
- try {
223
- Promise.resolve(iterator.return?.()).catch(() => {
224
- });
225
- } catch {
226
- }
227
- }
228
- writable.destroy(error);
229
- throw error;
230
- } finally {
231
- writableError.cleanup();
232
- }
233
- }
234
- async function readableStreamToString(stream, encoding) {
235
- let reader = stream.getReader();
236
- let chunks = [];
237
- while (true) {
238
- let { done, value } = await reader.read();
239
- if (done) {
240
- break;
241
- }
242
- if (value) {
243
- chunks.push(value);
244
- }
245
- }
246
- return Buffer.concat(chunks).toString(encoding);
247
- }
248
- var createReadableStreamFromReadable = (source) => {
249
- let pump = new StreamPump(source);
250
- let stream = new ReadableStream(pump, pump);
251
- return stream;
252
- };
253
- var StreamPump = class {
254
- highWaterMark;
255
- accumulatedSize;
256
- stream;
257
- controller;
258
- constructor(stream) {
259
- this.highWaterMark = stream.readableHighWaterMark || new Stream.Readable().readableHighWaterMark;
260
- this.accumulatedSize = 0;
261
- this.stream = stream;
262
- this.enqueue = this.enqueue.bind(this);
263
- this.error = this.error.bind(this);
264
- this.close = this.close.bind(this);
265
- }
266
- size(chunk) {
267
- return chunk?.byteLength || 0;
268
- }
269
- start(controller) {
270
- this.controller = controller;
271
- this.stream.on("data", this.enqueue);
272
- this.stream.once("error", this.error);
273
- this.stream.once("end", this.close);
274
- this.stream.once("close", this.close);
275
- }
276
- pull() {
277
- this.resume();
278
- }
279
- cancel(reason) {
280
- if (this.stream.destroy) {
281
- this.stream.destroy(reason);
282
- }
283
- this.stream.off("data", this.enqueue);
284
- this.stream.off("error", this.error);
285
- this.stream.off("end", this.close);
286
- this.stream.off("close", this.close);
287
- }
288
- enqueue(chunk) {
289
- if (this.controller) {
290
- try {
291
- let bytes = chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
292
- let available = (this.controller.desiredSize || 0) - bytes.byteLength;
293
- this.controller.enqueue(bytes);
294
- if (available <= 0) {
295
- this.pause();
296
- }
297
- } catch (e) {
298
- this.controller.error(
299
- new Error(
300
- "Could not create Buffer, chunk must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object"
301
- )
302
- );
303
- this.cancel();
304
- }
305
- }
306
- }
307
- pause() {
308
- if (this.stream.pause) {
309
- this.stream.pause();
310
- }
311
- }
312
- resume() {
313
- if (this.stream.readable && this.stream.resume) {
314
- this.stream.resume();
315
- }
316
- }
317
- close() {
318
- if (this.controller) {
319
- this.controller.close();
320
- delete this.controller;
321
- }
322
- }
323
- error(error) {
324
- if (this.controller) {
325
- this.controller.error(error);
326
- delete this.controller;
327
- }
328
- }
329
- };
330
- export {
331
- createFileSessionStorage,
332
- createReadableStreamFromReadable,
333
- createRequestListener,
334
- readableStreamToString,
335
- writeAsyncIterableToWritable,
336
- writeReadableStreamToWritable
337
- };