You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@react-router/node

Package Overview
Dependencies
Maintainers
1
Versions
685
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-router/node - npm Package Compare versions

Comparing version
0.0.0-experimental-3a25d7f8a
to
0.0.0-experimental-3bba3331c
+32
dist/globals.mjs
/**
* @react-router/node v0.0.0-experimental-3bba3331c
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
import { File, Headers, Request, Response, fetch, FormData } from 'undici';
import { webcrypto } from 'node:crypto';
function installGlobals() {
global.File = File;
// @ts-ignore - this shows as an error in VSCode but is not an error via TSC so we can't use `ts-expect-error`
global.Headers = Headers;
// @ts-expect-error - overriding globals
global.Request = Request;
// @ts-expect-error - overriding globals
global.Response = Response;
// @ts-expect-error - overriding globals
global.fetch = fetch;
// @ts-expect-error - overriding globals
global.FormData = FormData;
if (!global.crypto) {
// @ts-expect-error - overriding globals
global.crypto = webcrypto;
}
}
export { installGlobals };
/**
* @react-router/node v0.0.0-experimental-3bba3331c
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
export { installGlobals } from './globals.mjs';
export { createFileSessionStorage } from './sessions/fileStorage.mjs';
export { createReadableStreamFromReadable, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable } from './stream.mjs';
/**
* @react-router/node v0.0.0-experimental-3bba3331c
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
import { installGlobals } from './globals.mjs';
installGlobals();
/**
* @react-router/node v0.0.0-experimental-3bba3331c
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
import { promises } from 'node:fs';
import * as path from 'node:path';
import { createSessionStorage } from 'react-router';
/**
* Creates a SessionStorage that stores session data on a filesystem.
*
* The advantage of using this instead of cookie session storage is that
* files may contain much more data than cookies.
*
* @see https://remix.run/utils/sessions#createfilesessionstorage-node
*/
function createFileSessionStorage({
cookie,
dir
}) {
return createSessionStorage({
cookie,
async createData(data, expires) {
let content = JSON.stringify({
data,
expires
});
while (true) {
let randomBytes = crypto.getRandomValues(new Uint8Array(8));
// This storage manages an id space of 2^64 ids, which is far greater
// than the maximum number of files allowed on an NTFS or ext4 volume
// (2^32). However, the larger id space should help to avoid collisions
// with existing ids when creating new sessions, which speeds things up.
let id = Buffer.from(randomBytes).toString("hex");
try {
let file = getFile(dir, id);
await promises.mkdir(path.dirname(file), {
recursive: true
});
await promises.writeFile(file, content, {
encoding: "utf-8",
flag: "wx"
});
return id;
} catch (error) {
if (error.code !== "EEXIST") throw error;
}
}
},
async readData(id) {
try {
let file = getFile(dir, id);
let content = JSON.parse(await promises.readFile(file, "utf-8"));
let data = content.data;
let expires = typeof content.expires === "string" ? new Date(content.expires) : null;
if (!expires || expires > new Date()) {
return data;
}
// Remove expired session data.
if (expires) await promises.unlink(file);
return null;
} catch (error) {
if (error.code !== "ENOENT") throw error;
return null;
}
},
async updateData(id, data, expires) {
let content = JSON.stringify({
data,
expires
});
let file = getFile(dir, id);
await promises.mkdir(path.dirname(file), {
recursive: true
});
await promises.writeFile(file, content, "utf-8");
},
async deleteData(id) {
// Return early if the id is empty, otherwise we'll end up trying to
// unlink the dir, which will cause the EPERM error.
if (!id) {
return;
}
try {
await promises.unlink(getFile(dir, id));
} catch (error) {
if (error.code !== "ENOENT") throw error;
}
}
});
}
function getFile(dir, id) {
// Divide the session id up into a directory (first 2 bytes) and filename
// (remaining 6 bytes) to reduce the chance of having very large directories,
// which should speed up file access. This is a maximum of 2^16 directories,
// each with 2^48 files.
return path.join(dir, id.slice(0, 4), id.slice(4));
}
export { createFileSessionStorage, getFile };
/**
* @react-router/node v0.0.0-experimental-3bba3331c
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
import { Stream } from 'node:stream';
async function writeReadableStreamToWritable(stream, writable) {
let reader = stream.getReader();
let flushable = writable;
try {
while (true) {
let {
done,
value
} = await reader.read();
if (done) {
writable.end();
break;
}
writable.write(value);
if (typeof flushable.flush === "function") {
flushable.flush();
}
}
} catch (error) {
writable.destroy(error);
throw error;
}
}
async function writeAsyncIterableToWritable(iterable, writable) {
try {
for await (let chunk of iterable) {
writable.write(chunk);
}
writable.end();
} catch (error) {
writable.destroy(error);
throw error;
}
}
async function readableStreamToString(stream, encoding) {
let reader = stream.getReader();
let chunks = [];
while (true) {
let {
done,
value
} = await reader.read();
if (done) {
break;
}
if (value) {
chunks.push(value);
}
}
return Buffer.concat(chunks).toString(encoding);
}
const createReadableStreamFromReadable = source => {
let pump = new StreamPump(source);
let stream = new ReadableStream(pump, pump);
return stream;
};
class StreamPump {
constructor(stream) {
this.highWaterMark = stream.readableHighWaterMark || new Stream.Readable().readableHighWaterMark;
this.accumalatedSize = 0;
this.stream = stream;
this.enqueue = this.enqueue.bind(this);
this.error = this.error.bind(this);
this.close = this.close.bind(this);
}
size(chunk) {
return (chunk === null || chunk === void 0 ? void 0 : chunk.byteLength) || 0;
}
start(controller) {
this.controller = controller;
this.stream.on("data", this.enqueue);
this.stream.once("error", this.error);
this.stream.once("end", this.close);
this.stream.once("close", this.close);
}
pull() {
this.resume();
}
cancel(reason) {
if (this.stream.destroy) {
this.stream.destroy(reason);
}
this.stream.off("data", this.enqueue);
this.stream.off("error", this.error);
this.stream.off("end", this.close);
this.stream.off("close", this.close);
}
enqueue(chunk) {
if (this.controller) {
try {
let bytes = chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
let available = (this.controller.desiredSize || 0) - bytes.byteLength;
this.controller.enqueue(bytes);
if (available <= 0) {
this.pause();
}
} catch (error) {
this.controller.error(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"));
this.cancel();
}
}
}
pause() {
if (this.stream.pause) {
this.stream.pause();
}
}
resume() {
if (this.stream.readable && this.stream.resume) {
this.stream.resume();
}
}
close() {
if (this.controller) {
this.controller.close();
delete this.controller;
}
}
error(error) {
if (this.controller) {
this.controller.error(error);
delete this.controller;
}
}
}
export { createReadableStreamFromReadable, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable };
+3
-0

@@ -0,1 +1,3 @@

/// <reference types="node" />
import { webcrypto as nodeWebCrypto } from "node:crypto";
declare global {

@@ -15,2 +17,3 @@ namespace NodeJS {

WritableStream: typeof WritableStream;
crypto: typeof nodeWebCrypto;
}

@@ -17,0 +20,0 @@ }

+7
-2
/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
* @react-router/node v0.0.0-experimental-3bba3331c
*

@@ -16,6 +16,7 @@ * Copyright (c) Remix Software Inc.

var undici = require('undici');
var node_crypto = require('node:crypto');
function installGlobals() {
global.File = undici.File;
// @ts-expect-error - overriding globals
// @ts-ignore - this shows as an error in VSCode but is not an error via TSC so we can't use `ts-expect-error`
global.Headers = undici.Headers;

@@ -30,4 +31,8 @@ // @ts-expect-error - overriding globals

global.FormData = undici.FormData;
if (!global.crypto) {
// @ts-expect-error - overriding globals
global.crypto = node_crypto.webcrypto;
}
}
exports.installGlobals = installGlobals;
export { installGlobals } from "./globals";
export { createFileSessionStorage } from "./sessions/fileStorage";
export { createFileUploadHandler as unstable_createFileUploadHandler, NodeOnDiskFile, } from "./upload/fileUploadHandler";
export { createCookie, createCookieSessionStorage, createMemorySessionStorage, createSessionStorage, } from "./implementations";
export { createReadableStreamFromReadable, readableStreamToString, writeAsyncIterableToWritable, writeReadableStreamToWritable, } from "./stream";
export { createRequestHandler, createSession, defer, isCookie, isSession, json, MaxPartSizeExceededError, redirect, redirectDocument, unstable_composeUploadHandlers, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData, } from "@react-router/server-runtime";
export type { ActionFunction, ActionFunctionArgs, AppLoadContext, Cookie, CookieOptions, CookieParseOptions, CookieSerializeOptions, CookieSignatureOptions, DataFunctionArgs, EntryContext, ErrorResponse, HandleDataRequestFunction, HandleDocumentRequestFunction, HeadersArgs, HeadersFunction, HtmlLinkDescriptor, JsonFunction, LinkDescriptor, LinksFunction, LoaderFunction, LoaderFunctionArgs, MemoryUploadHandlerFilterArgs, MemoryUploadHandlerOptions, HandleErrorFunction, PageLinkDescriptor, RequestHandler, SerializeFrom, ServerBuild, ServerEntryModule, ServerRuntimeMetaArgs as MetaArgs, ServerRuntimeMetaDescriptor as MetaDescriptor, ServerRuntimeMetaFunction as MetaFunction, Session, SessionData, SessionIdStorageStrategy, SessionStorage, SignFunction, TypedDeferredData, TypedResponse, UnsignFunction, UploadHandler, UploadHandlerPart, } from "@react-router/server-runtime";
/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
* @react-router/node v0.0.0-experimental-3bba3331c
*

@@ -17,6 +17,3 @@ * Copyright (c) Remix Software Inc.

var fileStorage = require('./sessions/fileStorage.js');
var fileUploadHandler = require('./upload/fileUploadHandler.js');
var implementations = require('./implementations.js');
var stream = require('./stream.js');
var serverRuntime = require('@react-router/server-runtime');

@@ -27,8 +24,2 @@

exports.createFileSessionStorage = fileStorage.createFileSessionStorage;
exports.NodeOnDiskFile = fileUploadHandler.NodeOnDiskFile;
exports.unstable_createFileUploadHandler = fileUploadHandler.createFileUploadHandler;
exports.createCookie = implementations.createCookie;
exports.createCookieSessionStorage = implementations.createCookieSessionStorage;
exports.createMemorySessionStorage = implementations.createMemorySessionStorage;
exports.createSessionStorage = implementations.createSessionStorage;
exports.createReadableStreamFromReadable = stream.createReadableStreamFromReadable;

@@ -38,49 +29,1 @@ exports.readableStreamToString = stream.readableStreamToString;

exports.writeReadableStreamToWritable = stream.writeReadableStreamToWritable;
Object.defineProperty(exports, 'MaxPartSizeExceededError', {
enumerable: true,
get: function () { return serverRuntime.MaxPartSizeExceededError; }
});
Object.defineProperty(exports, 'createRequestHandler', {
enumerable: true,
get: function () { return serverRuntime.createRequestHandler; }
});
Object.defineProperty(exports, 'createSession', {
enumerable: true,
get: function () { return serverRuntime.createSession; }
});
Object.defineProperty(exports, 'defer', {
enumerable: true,
get: function () { return serverRuntime.defer; }
});
Object.defineProperty(exports, 'isCookie', {
enumerable: true,
get: function () { return serverRuntime.isCookie; }
});
Object.defineProperty(exports, 'isSession', {
enumerable: true,
get: function () { return serverRuntime.isSession; }
});
Object.defineProperty(exports, 'json', {
enumerable: true,
get: function () { return serverRuntime.json; }
});
Object.defineProperty(exports, 'redirect', {
enumerable: true,
get: function () { return serverRuntime.redirect; }
});
Object.defineProperty(exports, 'redirectDocument', {
enumerable: true,
get: function () { return serverRuntime.redirectDocument; }
});
Object.defineProperty(exports, 'unstable_composeUploadHandlers', {
enumerable: true,
get: function () { return serverRuntime.unstable_composeUploadHandlers; }
});
Object.defineProperty(exports, 'unstable_createMemoryUploadHandler', {
enumerable: true,
get: function () { return serverRuntime.unstable_createMemoryUploadHandler; }
});
Object.defineProperty(exports, 'unstable_parseMultipartFormData', {
enumerable: true,
get: function () { return serverRuntime.unstable_parseMultipartFormData; }
});
/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
* @react-router/node v0.0.0-experimental-3bba3331c
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

@@ -1,2 +0,2 @@

import type { SessionStorage, SessionIdStorageStrategy, SessionData } from "@react-router/server-runtime";
import type { SessionStorage, SessionIdStorageStrategy, SessionData } from "react-router";
interface FileSessionStorageOptions {

@@ -3,0 +3,0 @@ /**

/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
* @react-router/node v0.0.0-experimental-3bba3331c
*

@@ -15,26 +15,24 @@ * Copyright (c) Remix Software Inc.

var crypto = require('node:crypto');
var node_fs = require('node:fs');
var path = require('node:path');
var implementations = require('../implementations.js');
var reactRouter = require('react-router');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
n["default"] = e;
return Object.freeze(n);
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
var path__namespace = /*#__PURE__*/_interopNamespace(path);

@@ -54,3 +52,3 @@

}) {
return implementations.createSessionStorage({
return reactRouter.createSessionStorage({
cookie,

@@ -63,5 +61,3 @@ async createData(data, expires) {

while (true) {
// TODO: Once Node v19 is supported we should use the globally provided
// Web Crypto API's crypto.getRandomValues() function here instead.
let randomBytes = crypto__namespace.webcrypto.getRandomValues(new Uint8Array(8));
let randomBytes = crypto.getRandomValues(new Uint8Array(8));
// This storage manages an id space of 2^64 ids, which is far greater

@@ -96,2 +92,3 @@ // than the maximum number of files allowed on an NTFS or ext4 volume

}
// Remove expired session data.

@@ -98,0 +95,0 @@ if (expires) await node_fs.promises.unlink(file);

/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
* @react-router/node v0.0.0-experimental-3bba3331c
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

{
"name": "@react-router/node",
"version": "0.0.0-experimental-3a25d7f8a",
"version": "0.0.0-experimental-3bba3331c",
"description": "Node.js platform abstractions for React Router",

@@ -11,3 +11,3 @@ "bugs": {

"url": "https://github.com/remix-run/react-router",
"directory": "packages/remix-node"
"directory": "packages/react-router-node"
},

@@ -20,7 +20,9 @@ "license": "MIT",

"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./install": {
"types": "./dist/install.d.ts",
"default": "./dist/install.js"
"import": "./dist/install.mjs",
"require": "./dist/install.js"
},

@@ -30,19 +32,19 @@ "./package.json": "./package.json"

"sideEffects": [
"./dist/install.js"
"./dist/install.js",
"./dist/install.mjs"
],
"dependencies": {
"@web3-storage/multipart-parser": "^1.0.0",
"cookie-signature": "^1.1.0",
"source-map-support": "^0.5.21",
"stream-slice": "^0.1.2",
"undici": "^6.10.1",
"@react-router/server-runtime": "0.0.0-experimental-3a25d7f8a"
"undici": "^6.19.2"
},
"devDependencies": {
"@types/cookie-signature": "^1.0.3",
"@types/source-map-support": "^0.5.4",
"typescript": "^5.1.6"
"typescript": "^5.1.6",
"react-router": "0.0.0-experimental-3bba3331c"
},
"peerDependencies": {
"typescript": "^5.1.0"
"typescript": "^5.1.0",
"react-router": "0.0.0-experimental-3bba3331c"
},

@@ -49,0 +51,0 @@ "peerDependenciesMeta": {

import type { SignFunction, UnsignFunction } from "@react-router/server-runtime";
export declare const sign: SignFunction;
export declare const unsign: UnsignFunction;
/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var cookieSignature = require('cookie-signature');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var cookieSignature__default = /*#__PURE__*/_interopDefaultLegacy(cookieSignature);
const sign = async (value, secret) => {
return cookieSignature__default["default"].sign(value, secret);
};
const unsign = async (signed, secret) => {
return cookieSignature__default["default"].unsign(signed, secret);
};
exports.sign = sign;
exports.unsign = unsign;
export declare const createCookie: import("@react-router/server-runtime").CreateCookieFunction;
export declare const createCookieSessionStorage: import("@react-router/server-runtime").CreateCookieSessionStorageFunction;
export declare const createSessionStorage: import("@react-router/server-runtime").CreateSessionStorageFunction;
export declare const createMemorySessionStorage: import("@react-router/server-runtime").CreateMemorySessionStorageFunction;
/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var serverRuntime = require('@react-router/server-runtime');
var crypto = require('./crypto.js');
const createCookie = serverRuntime.createCookieFactory({
sign: crypto.sign,
unsign: crypto.unsign
});
const createCookieSessionStorage = serverRuntime.createCookieSessionStorageFactory(createCookie);
const createSessionStorage = serverRuntime.createSessionStorageFactory(createCookie);
const createMemorySessionStorage = serverRuntime.createMemorySessionStorageFactory(createSessionStorage);
exports.createCookie = createCookie;
exports.createCookieSessionStorage = createCookieSessionStorage;
exports.createMemorySessionStorage = createMemorySessionStorage;
exports.createSessionStorage = createSessionStorage;
/// <reference types="node" />
import type { UploadHandler } from "@react-router/server-runtime";
export type FileUploadHandlerFilterArgs = {
filename: string;
contentType: string;
name: string;
};
export type FileUploadHandlerPathResolverArgs = {
filename: string;
contentType: string;
name: string;
};
/**
* Chooses the path of the file to be uploaded. If a string is not
* returned the file will not be written.
*/
export type FileUploadHandlerPathResolver = (args: FileUploadHandlerPathResolverArgs) => string | undefined;
export type FileUploadHandlerOptions = {
/**
* Avoid file conflicts by appending a count on the end of the filename
* if it already exists on disk. Defaults to `true`.
*/
avoidFileConflicts?: boolean;
/**
* The directory to write the upload.
*/
directory?: string | FileUploadHandlerPathResolver;
/**
* The name of the file in the directory. Can be a relative path, the directory
* structure will be created if it does not exist.
*/
file?: FileUploadHandlerPathResolver;
/**
* The maximum upload size allowed. If the size is exceeded an error will be thrown.
* Defaults to 3000000B (3MB).
*/
maxPartSize?: number;
/**
*
* @param filename
* @param contentType
* @param name
*/
filter?(args: FileUploadHandlerFilterArgs): boolean | Promise<boolean>;
};
export declare function createFileUploadHandler({ directory, avoidFileConflicts, file, filter, maxPartSize, }?: FileUploadHandlerOptions): UploadHandler;
export declare class NodeOnDiskFile implements Omit<File, "constructor"> {
private filepath;
type: string;
private slicer?;
name: string;
lastModified: number;
webkitRelativePath: string;
prototype: File;
constructor(filepath: string, type: string, slicer?: {
start: number;
end: number;
} | undefined);
get size(): number;
slice(start?: number, end?: number, type?: string): Blob;
arrayBuffer(): Promise<ArrayBuffer>;
stream(): ReadableStream<any>;
stream(): NodeJS.ReadableStream;
text(): Promise<string>;
get [Symbol.toStringTag](): string;
remove(): Promise<void>;
getFilePath(): string;
}
/**
* @react-router/node v0.0.0-experimental-3a25d7f8a
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var crypto = require('node:crypto');
var node_fs = require('node:fs');
var promises = require('node:fs/promises');
var node_os = require('node:os');
var path = require('node:path');
var node_stream = require('node:stream');
var node_util = require('node:util');
var serverRuntime = require('@react-router/server-runtime');
var streamSlice = require('stream-slice');
var stream = require('../stream.js');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var streamSlice__namespace = /*#__PURE__*/_interopNamespace(streamSlice);
let defaultFilePathResolver = ({
filename
}) => {
let ext = filename ? path.extname(filename) : "";
return "upload_" + crypto.randomBytes(4).readUInt32LE(0) + ext;
};
async function uniqueFile(filepath) {
let ext = path.extname(filepath);
let uniqueFilepath = filepath;
for (let i = 1; await promises.stat(uniqueFilepath).then(() => true).catch(() => false); i++) {
uniqueFilepath = (ext ? filepath.slice(0, -ext.length) : filepath) + `-${new Date().getTime()}${ext}`;
}
return uniqueFilepath;
}
function createFileUploadHandler({
directory = node_os.tmpdir(),
avoidFileConflicts = true,
file = defaultFilePathResolver,
filter,
maxPartSize = 3000000
} = {}) {
return async ({
name,
filename,
contentType,
data
}) => {
if (!filename || filter && !(await filter({
name,
filename,
contentType
}))) {
return undefined;
}
let dir = typeof directory === "string" ? directory : directory({
name,
filename,
contentType
});
if (!dir) {
return undefined;
}
let filedir = path.resolve(dir);
let path$1 = typeof file === "string" ? file : file({
name,
filename,
contentType
});
if (!path$1) {
return undefined;
}
let filepath = path.resolve(filedir, path$1);
if (avoidFileConflicts) {
filepath = await uniqueFile(filepath);
}
await promises.mkdir(path.dirname(filepath), {
recursive: true
}).catch(() => {});
let writeFileStream = node_fs.createWriteStream(filepath);
let size = 0;
let deleteFile = false;
try {
for await (let chunk of data) {
size += chunk.byteLength;
if (size > maxPartSize) {
deleteFile = true;
throw new serverRuntime.MaxPartSizeExceededError(name, maxPartSize);
}
writeFileStream.write(chunk);
}
} finally {
writeFileStream.end();
await node_util.promisify(node_stream.finished)(writeFileStream);
if (deleteFile) {
await promises.rm(filepath).catch(() => {});
}
}
// TODO: remove this typecast once TS fixed File class regression
// https://github.com/microsoft/TypeScript/issues/52166
return new NodeOnDiskFile(filepath, contentType);
};
}
// TODO: remove this `Omit` usage once TS fixed File class regression
// https://github.com/microsoft/TypeScript/issues/52166
class NodeOnDiskFile {
lastModified = 0;
webkitRelativePath = "";
// TODO: remove this property once TS fixed File class regression
// https://github.com/microsoft/TypeScript/issues/52166
prototype = File.prototype;
constructor(filepath, type, slicer) {
this.filepath = filepath;
this.type = type;
this.slicer = slicer;
this.name = path.basename(filepath);
}
get size() {
let stats = node_fs.statSync(this.filepath);
if (this.slicer) {
let slice = this.slicer.end - this.slicer.start;
return slice < 0 ? 0 : slice > stats.size ? stats.size : slice;
}
return stats.size;
}
slice(start, end, type) {
var _this$slicer;
if (typeof start === "number" && start < 0) start = this.size + start;
if (typeof end === "number" && end < 0) end = this.size + end;
let startOffset = ((_this$slicer = this.slicer) === null || _this$slicer === void 0 ? void 0 : _this$slicer.start) || 0;
start = startOffset + (start || 0);
end = startOffset + (end || this.size);
return new NodeOnDiskFile(this.filepath, typeof type === "string" ? type : this.type, {
start,
end
}
// TODO: remove this typecast once TS fixed File class regression
// https://github.com/microsoft/TypeScript/issues/52166
);
}
async arrayBuffer() {
let stream = node_fs.createReadStream(this.filepath);
if (this.slicer) {
stream = stream.pipe(streamSlice__namespace.slice(this.slicer.start, this.slicer.end));
}
return new Promise((resolve, reject) => {
let buf = [];
stream.on("data", chunk => buf.push(chunk));
stream.on("end", () => resolve(Buffer.concat(buf)));
stream.on("error", err => reject(err));
});
}
stream() {
let stream$1 = node_fs.createReadStream(this.filepath);
if (this.slicer) {
stream$1 = stream$1.pipe(streamSlice__namespace.slice(this.slicer.start, this.slicer.end));
}
return stream.createReadableStreamFromReadable(stream$1);
}
async text() {
return stream.readableStreamToString(this.stream());
}
get [Symbol.toStringTag]() {
return "File";
}
remove() {
return promises.unlink(this.filepath);
}
getFilePath() {
return this.filepath;
}
}
exports.NodeOnDiskFile = NodeOnDiskFile;
exports.createFileUploadHandler = createFileUploadHandler;