@remix-run/node 1.4.3 → 1.5.0-pre.2
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/base64.js +1 -1
- package/crypto.js +1 -1
- package/fetch.d.ts +21 -22
- package/fetch.js +32 -109
- package/globals.d.ts +2 -0
- package/globals.js +11 -9
- package/implementations.js +1 -1
- package/index.d.ts +4 -7
- package/index.js +28 -12
- package/magicExports/esm/remix.js +1 -1
- package/magicExports/remix.d.ts +1 -1
- package/magicExports/remix.js +1 -1
- package/package.json +8 -11
- package/sessions/fileStorage.js +1 -1
- package/stream.d.ts +8 -0
- package/stream.js +167 -0
- package/upload/fileUploadHandler.d.ts +15 -10
- package/upload/fileUploadHandler.js +107 -52
- package/formData.d.ts +0 -27
- package/formData.js +0 -108
- package/parseMultipartFormData.d.ts +0 -11
- package/parseMultipartFormData.js +0 -114
- package/upload/memoryUploadHandler.d.ts +0 -21
- package/upload/memoryUploadHandler.js +0 -80
- package/upload/meter.d.ts +0 -15
- package/upload/meter.js +0 -47
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import type { UploadHandler } from "
|
|
2
|
+
import type { UploadHandler } from "@remix-run/server-runtime";
|
|
3
3
|
export declare type FileUploadHandlerFilterArgs = {
|
|
4
4
|
filename: string;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
contentType: string;
|
|
6
|
+
name: string;
|
|
7
7
|
};
|
|
8
8
|
export declare type FileUploadHandlerPathResolverArgs = {
|
|
9
9
|
filename: string;
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
contentType: string;
|
|
11
|
+
name: string;
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
14
|
* Chooses the path of the file to be uploaded. If a string is not
|
|
@@ -34,7 +34,7 @@ export declare type FileUploadHandlerOptions = {
|
|
|
34
34
|
* The maximum upload size allowed. If the size is exceeded an error will be thrown.
|
|
35
35
|
* Defaults to 3000000B (3MB).
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
maxPartSize?: number;
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
40
40
|
* @param filename
|
|
@@ -43,18 +43,23 @@ export declare type FileUploadHandlerOptions = {
|
|
|
43
43
|
*/
|
|
44
44
|
filter?(args: FileUploadHandlerFilterArgs): boolean | Promise<boolean>;
|
|
45
45
|
};
|
|
46
|
-
export declare function createFileUploadHandler({ directory, avoidFileConflicts, file, filter,
|
|
46
|
+
export declare function createFileUploadHandler({ directory, avoidFileConflicts, file, filter, maxPartSize, }?: FileUploadHandlerOptions): UploadHandler;
|
|
47
47
|
export declare class NodeOnDiskFile implements File {
|
|
48
48
|
private filepath;
|
|
49
|
-
size: number;
|
|
50
49
|
type: string;
|
|
50
|
+
private slicer?;
|
|
51
51
|
name: string;
|
|
52
52
|
lastModified: number;
|
|
53
53
|
webkitRelativePath: string;
|
|
54
|
-
constructor(filepath: string,
|
|
54
|
+
constructor(filepath: string, type: string, slicer?: {
|
|
55
|
+
start: number;
|
|
56
|
+
end: number;
|
|
57
|
+
} | undefined);
|
|
58
|
+
get size(): number;
|
|
59
|
+
slice(start?: number, end?: number, type?: string): Blob;
|
|
55
60
|
arrayBuffer(): Promise<ArrayBuffer>;
|
|
56
|
-
slice(start?: any, end?: any, contentType?: any): Blob;
|
|
57
61
|
stream(): ReadableStream<any>;
|
|
58
62
|
stream(): NodeJS.ReadableStream;
|
|
59
63
|
text(): Promise<string>;
|
|
64
|
+
get [Symbol.toStringTag](): string;
|
|
60
65
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/node v1.
|
|
2
|
+
* @remix-run/node v1.5.0-pre.2
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -17,7 +17,31 @@ var fs = require('fs');
|
|
|
17
17
|
var promises = require('fs/promises');
|
|
18
18
|
var os = require('os');
|
|
19
19
|
var path = require('path');
|
|
20
|
-
var
|
|
20
|
+
var stream = require('stream');
|
|
21
|
+
var util = require('util');
|
|
22
|
+
var serverRuntime = require('@remix-run/server-runtime');
|
|
23
|
+
var streamSlice = require('stream-slice');
|
|
24
|
+
var stream$1 = require('../stream.js');
|
|
25
|
+
|
|
26
|
+
function _interopNamespace(e) {
|
|
27
|
+
if (e && e.__esModule) return e;
|
|
28
|
+
var n = Object.create(null);
|
|
29
|
+
if (e) {
|
|
30
|
+
Object.keys(e).forEach(function (k) {
|
|
31
|
+
if (k !== 'default') {
|
|
32
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
33
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
get: function () { return e[k]; }
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
n["default"] = e;
|
|
41
|
+
return Object.freeze(n);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
var streamSlice__namespace = /*#__PURE__*/_interopNamespace(streamSlice);
|
|
21
45
|
|
|
22
46
|
let defaultFilePathResolver = ({
|
|
23
47
|
filename
|
|
@@ -42,45 +66,41 @@ function createFileUploadHandler({
|
|
|
42
66
|
avoidFileConflicts = true,
|
|
43
67
|
file = defaultFilePathResolver,
|
|
44
68
|
filter,
|
|
45
|
-
|
|
46
|
-
}) {
|
|
69
|
+
maxPartSize = 3000000
|
|
70
|
+
} = {}) {
|
|
47
71
|
return async ({
|
|
48
72
|
name,
|
|
49
|
-
stream,
|
|
50
73
|
filename,
|
|
51
|
-
|
|
52
|
-
|
|
74
|
+
contentType,
|
|
75
|
+
data
|
|
53
76
|
}) => {
|
|
54
|
-
if (filter && !(await filter({
|
|
77
|
+
if (!filename || filter && !(await filter({
|
|
78
|
+
name,
|
|
55
79
|
filename,
|
|
56
|
-
|
|
57
|
-
mimetype
|
|
80
|
+
contentType
|
|
58
81
|
}))) {
|
|
59
|
-
|
|
60
|
-
return;
|
|
82
|
+
return undefined;
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
let dir = typeof directory === "string" ? directory : directory({
|
|
86
|
+
name,
|
|
64
87
|
filename,
|
|
65
|
-
|
|
66
|
-
mimetype
|
|
88
|
+
contentType
|
|
67
89
|
});
|
|
68
90
|
|
|
69
91
|
if (!dir) {
|
|
70
|
-
|
|
71
|
-
return;
|
|
92
|
+
return undefined;
|
|
72
93
|
}
|
|
73
94
|
|
|
74
95
|
let filedir = path.resolve(dir);
|
|
75
96
|
let path$1 = typeof file === "string" ? file : file({
|
|
97
|
+
name,
|
|
76
98
|
filename,
|
|
77
|
-
|
|
78
|
-
mimetype
|
|
99
|
+
contentType
|
|
79
100
|
});
|
|
80
101
|
|
|
81
102
|
if (!path$1) {
|
|
82
|
-
|
|
83
|
-
return;
|
|
103
|
+
return undefined;
|
|
84
104
|
}
|
|
85
105
|
|
|
86
106
|
let filepath = path.resolve(filedir, path$1);
|
|
@@ -92,47 +112,76 @@ function createFileUploadHandler({
|
|
|
92
112
|
await promises.mkdir(path.dirname(filepath), {
|
|
93
113
|
recursive: true
|
|
94
114
|
}).catch(() => {});
|
|
95
|
-
let
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
force: true
|
|
110
|
-
}).catch(() => {});
|
|
111
|
-
reject(error);
|
|
115
|
+
let writeFileStream = fs.createWriteStream(filepath);
|
|
116
|
+
let size = 0;
|
|
117
|
+
let deleteFile = false;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
for await (let chunk of data) {
|
|
121
|
+
size += chunk.byteLength;
|
|
122
|
+
|
|
123
|
+
if (size > maxPartSize) {
|
|
124
|
+
deleteFile = true;
|
|
125
|
+
throw new serverRuntime.MaxPartSizeExceededError(name, maxPartSize);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
writeFileStream.write(chunk);
|
|
112
129
|
}
|
|
130
|
+
} finally {
|
|
131
|
+
writeFileStream.end();
|
|
132
|
+
await util.promisify(stream.finished)(writeFileStream);
|
|
113
133
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return new NodeOnDiskFile(filepath, meter$1.bytes, mimetype);
|
|
134
|
+
if (deleteFile) {
|
|
135
|
+
await promises.rm(filepath).catch(() => {});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return new NodeOnDiskFile(filepath, contentType);
|
|
121
140
|
};
|
|
122
141
|
}
|
|
123
142
|
class NodeOnDiskFile {
|
|
124
143
|
lastModified = 0;
|
|
125
144
|
webkitRelativePath = "";
|
|
126
145
|
|
|
127
|
-
constructor(filepath,
|
|
146
|
+
constructor(filepath, type, slicer) {
|
|
128
147
|
this.filepath = filepath;
|
|
129
|
-
this.size = size;
|
|
130
148
|
this.type = type;
|
|
149
|
+
this.slicer = slicer;
|
|
131
150
|
this.name = path.basename(filepath);
|
|
132
151
|
}
|
|
133
152
|
|
|
153
|
+
get size() {
|
|
154
|
+
let stats = fs.statSync(this.filepath);
|
|
155
|
+
|
|
156
|
+
if (this.slicer) {
|
|
157
|
+
let slice = this.slicer.end - this.slicer.start;
|
|
158
|
+
return slice < 0 ? 0 : slice > stats.size ? stats.size : slice;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return stats.size;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
slice(start, end, type) {
|
|
165
|
+
var _this$slicer;
|
|
166
|
+
|
|
167
|
+
if (typeof start === "number" && start < 0) start = this.size + start;
|
|
168
|
+
if (typeof end === "number" && end < 0) end = this.size + end;
|
|
169
|
+
let startOffset = ((_this$slicer = this.slicer) === null || _this$slicer === void 0 ? void 0 : _this$slicer.start) || 0;
|
|
170
|
+
start = startOffset + (start || 0);
|
|
171
|
+
end = startOffset + (end || this.size);
|
|
172
|
+
return new NodeOnDiskFile(this.filepath, typeof type === "string" ? type : this.type, {
|
|
173
|
+
start,
|
|
174
|
+
end
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
134
178
|
async arrayBuffer() {
|
|
135
179
|
let stream = fs.createReadStream(this.filepath);
|
|
180
|
+
|
|
181
|
+
if (this.slicer) {
|
|
182
|
+
stream = stream.pipe(streamSlice__namespace.slice(this.slicer.start, this.slicer.end));
|
|
183
|
+
}
|
|
184
|
+
|
|
136
185
|
return new Promise((resolve, reject) => {
|
|
137
186
|
let buf = [];
|
|
138
187
|
stream.on("data", chunk => buf.push(chunk));
|
|
@@ -141,16 +190,22 @@ class NodeOnDiskFile {
|
|
|
141
190
|
});
|
|
142
191
|
}
|
|
143
192
|
|
|
144
|
-
|
|
145
|
-
|
|
193
|
+
stream() {
|
|
194
|
+
let stream = fs.createReadStream(this.filepath);
|
|
195
|
+
|
|
196
|
+
if (this.slicer) {
|
|
197
|
+
stream = stream.pipe(streamSlice__namespace.slice(this.slicer.start, this.slicer.end));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return stream$1.createReadableStreamFromReadable(stream);
|
|
146
201
|
}
|
|
147
202
|
|
|
148
|
-
|
|
149
|
-
return
|
|
203
|
+
async text() {
|
|
204
|
+
return stream$1.readableStreamToString(this.stream());
|
|
150
205
|
}
|
|
151
206
|
|
|
152
|
-
|
|
153
|
-
return
|
|
207
|
+
get [Symbol.toStringTag]() {
|
|
208
|
+
return "File";
|
|
154
209
|
}
|
|
155
210
|
|
|
156
211
|
}
|
package/formData.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import type { Readable } from "stream";
|
|
3
|
-
export declare type UploadHandlerArgs = {
|
|
4
|
-
name: string;
|
|
5
|
-
stream: Readable;
|
|
6
|
-
filename: string;
|
|
7
|
-
encoding: string;
|
|
8
|
-
mimetype: string;
|
|
9
|
-
};
|
|
10
|
-
export declare type UploadHandler = (args: UploadHandlerArgs) => Promise<string | File | undefined>;
|
|
11
|
-
export declare function isFile(blob: Blob): blob is File;
|
|
12
|
-
declare class NodeFormData implements FormData {
|
|
13
|
-
private _fields;
|
|
14
|
-
constructor(form?: any);
|
|
15
|
-
append(name: string, value: string | Blob, fileName?: string): void;
|
|
16
|
-
delete(name: string): void;
|
|
17
|
-
get(name: string): FormDataEntryValue | null;
|
|
18
|
-
getAll(name: string): FormDataEntryValue[];
|
|
19
|
-
has(name: string): boolean;
|
|
20
|
-
set(name: string, value: string | Blob, fileName?: string): void;
|
|
21
|
-
forEach(callbackfn: (value: FormDataEntryValue, key: string, parent: FormData) => void, thisArg?: any): void;
|
|
22
|
-
entries(): IterableIterator<[string, FormDataEntryValue]>;
|
|
23
|
-
keys(): IterableIterator<string>;
|
|
24
|
-
values(): IterableIterator<FormDataEntryValue>;
|
|
25
|
-
[Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
|
|
26
|
-
}
|
|
27
|
-
export { NodeFormData as FormData };
|
package/formData.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @remix-run/node v1.4.3
|
|
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
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
-
|
|
15
|
-
function isBlob(value) {
|
|
16
|
-
return typeof value === "object" && (typeof value.arrayBuffer === "function" || typeof value.size === "number" || typeof value.slice === "function" || typeof value.stream === "function" || typeof value.text === "function" || typeof value.type === "string");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function isFile(blob) {
|
|
20
|
-
let file = blob;
|
|
21
|
-
return typeof file.name === "string";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
class NodeFormData {
|
|
25
|
-
constructor(form) {
|
|
26
|
-
if (typeof form !== "undefined") {
|
|
27
|
-
throw new Error("Form data on the server is not supported.");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
this._fields = {};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
append(name, value, fileName) {
|
|
34
|
-
if (typeof value !== "string" && !isBlob(value)) {
|
|
35
|
-
throw new Error("formData.append can only accept a string or Blob");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
this._fields[name] = this._fields[name] || [];
|
|
39
|
-
|
|
40
|
-
if (typeof value === "string" || isFile(value)) {
|
|
41
|
-
this._fields[name].push(value);
|
|
42
|
-
} else {
|
|
43
|
-
this._fields[name].push(new File([value], fileName || "unknown"));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
delete(name) {
|
|
48
|
-
delete this._fields[name];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
get(name) {
|
|
52
|
-
let arr = this._fields[name];
|
|
53
|
-
return (arr === null || arr === void 0 ? void 0 : arr.slice(-1)[0]) ?? null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
getAll(name) {
|
|
57
|
-
let arr = this._fields[name];
|
|
58
|
-
return arr || [];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
has(name) {
|
|
62
|
-
return name in this._fields;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
set(name, value, fileName) {
|
|
66
|
-
if (typeof value !== "string" && !isBlob(value)) {
|
|
67
|
-
throw new Error("formData.set can only accept a string or Blob");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (typeof value === "string" || isFile(value)) {
|
|
71
|
-
this._fields[name] = [value];
|
|
72
|
-
} else {
|
|
73
|
-
this._fields[name] = [new File([value], fileName || "unknown")];
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
forEach(callbackfn, thisArg) {
|
|
78
|
-
Object.entries(this._fields).forEach(([name, values]) => {
|
|
79
|
-
values.forEach(value => callbackfn(value, name, thisArg), thisArg);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
entries() {
|
|
84
|
-
return Object.entries(this._fields).reduce((entries, [name, values]) => {
|
|
85
|
-
values.forEach(value => entries.push([name, value]));
|
|
86
|
-
return entries;
|
|
87
|
-
}, []).values();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
keys() {
|
|
91
|
-
return Object.keys(this._fields).values();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
values() {
|
|
95
|
-
return Object.entries(this._fields).reduce((results, [name, values]) => {
|
|
96
|
-
values.forEach(value => results.push(value));
|
|
97
|
-
return results;
|
|
98
|
-
}, []).values();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
*[Symbol.iterator]() {
|
|
102
|
-
yield* this.entries();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
exports.FormData = NodeFormData;
|
|
108
|
-
exports.isFile = isFile;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { Readable } from "stream";
|
|
3
|
-
import type { UploadHandler } from "./formData";
|
|
4
|
-
import { FormData as NodeFormData } from "./formData";
|
|
5
|
-
/**
|
|
6
|
-
* Allows you to handle multipart forms (file uploads) for your app.
|
|
7
|
-
*
|
|
8
|
-
* @see https://remix.run/api/remix#parsemultipartformdata-node
|
|
9
|
-
*/
|
|
10
|
-
export declare function parseMultipartFormData(request: Request, uploadHandler: UploadHandler): Promise<FormData>;
|
|
11
|
-
export declare function internalParseFormData(contentType: string, body: string | Buffer | Readable, abortController?: AbortController, uploadHandler?: UploadHandler): Promise<NodeFormData>;
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @remix-run/node v1.4.3
|
|
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
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
-
|
|
15
|
-
var stream = require('stream');
|
|
16
|
-
var Busboy = require('busboy');
|
|
17
|
-
var formData = require('./formData.js');
|
|
18
|
-
|
|
19
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
|
-
|
|
21
|
-
var Busboy__default = /*#__PURE__*/_interopDefaultLegacy(Busboy);
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Allows you to handle multipart forms (file uploads) for your app.
|
|
25
|
-
*
|
|
26
|
-
* @see https://remix.run/api/remix#parsemultipartformdata-node
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
function parseMultipartFormData(request, uploadHandler) {
|
|
30
|
-
return request.formData(uploadHandler);
|
|
31
|
-
}
|
|
32
|
-
async function internalParseFormData(contentType, body, abortController, uploadHandler) {
|
|
33
|
-
let formData$1 = new formData.FormData();
|
|
34
|
-
let fileWorkQueue = [];
|
|
35
|
-
let stream$1;
|
|
36
|
-
|
|
37
|
-
if (typeof body === "string" || Buffer.isBuffer(body)) {
|
|
38
|
-
stream$1 = stream.Readable.from(body);
|
|
39
|
-
} else {
|
|
40
|
-
stream$1 = body;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
await new Promise(async (resolve, reject) => {
|
|
44
|
-
try {
|
|
45
|
-
let busboy = new Busboy__default["default"]({
|
|
46
|
-
highWaterMark: 2 * 1024 * 1024,
|
|
47
|
-
headers: {
|
|
48
|
-
"content-type": contentType
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
let aborted = false;
|
|
52
|
-
|
|
53
|
-
function abort(error) {
|
|
54
|
-
if (aborted) return;
|
|
55
|
-
aborted = true;
|
|
56
|
-
stream$1.unpipe();
|
|
57
|
-
stream$1.removeAllListeners();
|
|
58
|
-
busboy.removeAllListeners();
|
|
59
|
-
abortController === null || abortController === void 0 ? void 0 : abortController.abort();
|
|
60
|
-
reject(error || new Error("failed to parse form data"));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
busboy.on("field", (name, value) => {
|
|
64
|
-
formData$1.append(name, value);
|
|
65
|
-
});
|
|
66
|
-
busboy.on("file", (name, filestream, filename, encoding, mimetype) => {
|
|
67
|
-
if (uploadHandler) {
|
|
68
|
-
fileWorkQueue.push((async () => {
|
|
69
|
-
try {
|
|
70
|
-
let value = await uploadHandler({
|
|
71
|
-
name,
|
|
72
|
-
stream: filestream,
|
|
73
|
-
filename,
|
|
74
|
-
encoding,
|
|
75
|
-
mimetype
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
if (typeof value !== "undefined") {
|
|
79
|
-
formData$1.append(name, value);
|
|
80
|
-
}
|
|
81
|
-
} catch (error) {
|
|
82
|
-
// Emit error to busboy to bail early if possible
|
|
83
|
-
busboy.emit("error", error); // It's possible that the handler is doing stuff and fails
|
|
84
|
-
// *after* busboy has finished. Rethrow the error for surfacing
|
|
85
|
-
// in the Promise.all(fileWorkQueue) below.
|
|
86
|
-
|
|
87
|
-
throw error;
|
|
88
|
-
} finally {
|
|
89
|
-
filestream.resume();
|
|
90
|
-
}
|
|
91
|
-
})());
|
|
92
|
-
} else {
|
|
93
|
-
filestream.resume();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (!uploadHandler) {
|
|
97
|
-
console.warn(`Tried to parse multipart file upload for field "${name}" but no uploadHandler was provided.` + " Read more here: https://remix.run/api/remix#parseMultipartFormData-node");
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
stream$1.on("error", abort);
|
|
101
|
-
stream$1.on("aborted", abort);
|
|
102
|
-
busboy.on("error", abort);
|
|
103
|
-
busboy.on("finish", resolve);
|
|
104
|
-
stream$1.pipe(busboy);
|
|
105
|
-
} catch (err) {
|
|
106
|
-
reject(err);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
await Promise.all(fileWorkQueue);
|
|
110
|
-
return formData$1;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
exports.internalParseFormData = internalParseFormData;
|
|
114
|
-
exports.parseMultipartFormData = parseMultipartFormData;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { UploadHandler } from "../formData";
|
|
2
|
-
export declare type MemoryUploadHandlerFilterArgs = {
|
|
3
|
-
filename: string;
|
|
4
|
-
encoding: string;
|
|
5
|
-
mimetype: string;
|
|
6
|
-
};
|
|
7
|
-
export declare type MemoryUploadHandlerOptions = {
|
|
8
|
-
/**
|
|
9
|
-
* The maximum upload size allowed. If the size is exceeded an error will be thrown.
|
|
10
|
-
* Defaults to 3000000B (3MB).
|
|
11
|
-
*/
|
|
12
|
-
maxFileSize?: number;
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* @param filename
|
|
16
|
-
* @param mimetype
|
|
17
|
-
* @param encoding
|
|
18
|
-
*/
|
|
19
|
-
filter?(args: MemoryUploadHandlerFilterArgs): boolean | Promise<boolean>;
|
|
20
|
-
};
|
|
21
|
-
export declare function createMemoryUploadHandler({ filter, maxFileSize, }: MemoryUploadHandlerOptions): UploadHandler;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @remix-run/node v1.4.3
|
|
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
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
-
|
|
15
|
-
var stream = require('stream');
|
|
16
|
-
var file = require('@web-std/file');
|
|
17
|
-
var meter = require('./meter.js');
|
|
18
|
-
|
|
19
|
-
function createMemoryUploadHandler({
|
|
20
|
-
filter,
|
|
21
|
-
maxFileSize = 3000000
|
|
22
|
-
}) {
|
|
23
|
-
return async ({
|
|
24
|
-
name,
|
|
25
|
-
stream,
|
|
26
|
-
filename,
|
|
27
|
-
encoding,
|
|
28
|
-
mimetype
|
|
29
|
-
}) => {
|
|
30
|
-
if (filter && !(await filter({
|
|
31
|
-
filename,
|
|
32
|
-
encoding,
|
|
33
|
-
mimetype
|
|
34
|
-
}))) {
|
|
35
|
-
stream.resume();
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let bufferStream = new BufferStream();
|
|
40
|
-
await new Promise((resolve, reject) => {
|
|
41
|
-
let meter$1 = new meter.Meter(name, maxFileSize);
|
|
42
|
-
let aborted = false;
|
|
43
|
-
|
|
44
|
-
async function abort(error) {
|
|
45
|
-
if (aborted) return;
|
|
46
|
-
aborted = true;
|
|
47
|
-
stream.unpipe();
|
|
48
|
-
meter$1.unpipe();
|
|
49
|
-
stream.removeAllListeners();
|
|
50
|
-
meter$1.removeAllListeners();
|
|
51
|
-
bufferStream.removeAllListeners();
|
|
52
|
-
reject(error);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
stream.on("error", abort);
|
|
56
|
-
meter$1.on("error", abort);
|
|
57
|
-
bufferStream.on("error", abort);
|
|
58
|
-
bufferStream.on("finish", resolve);
|
|
59
|
-
stream.pipe(meter$1).pipe(bufferStream);
|
|
60
|
-
});
|
|
61
|
-
return new file.File(bufferStream.data, filename, {
|
|
62
|
-
type: mimetype
|
|
63
|
-
});
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
class BufferStream extends stream.Transform {
|
|
68
|
-
constructor() {
|
|
69
|
-
super();
|
|
70
|
-
this.data = [];
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
_transform(chunk, _, callback) {
|
|
74
|
-
this.data.push(chunk);
|
|
75
|
-
callback();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
exports.createMemoryUploadHandler = createMemoryUploadHandler;
|
package/upload/meter.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import type { TransformCallback } from "stream";
|
|
3
|
-
import { Transform } from "stream";
|
|
4
|
-
export declare class Meter extends Transform {
|
|
5
|
-
field: string;
|
|
6
|
-
maxBytes: number | undefined;
|
|
7
|
-
bytes: number;
|
|
8
|
-
constructor(field: string, maxBytes: number | undefined);
|
|
9
|
-
_transform(chunk: any, _: BufferEncoding, callback: TransformCallback): void;
|
|
10
|
-
}
|
|
11
|
-
export declare class MeterError extends Error {
|
|
12
|
-
field: string;
|
|
13
|
-
maxBytes: number;
|
|
14
|
-
constructor(field: string, maxBytes: number);
|
|
15
|
-
}
|