Skip to content

Commit c5e8df8

Browse files
chore(client): only accept standard types for file uploads (#25)
1 parent 8e0ab12 commit c5e8df8

File tree

17 files changed

+267
-280
lines changed

17 files changed

+267
-280
lines changed

scripts/build

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ cp dist/index.d.ts dist/index.d.mts
4040
cp tsconfig.dist-src.json dist/src/tsconfig.json
4141
cp src/internal/shim-types.d.ts dist/internal/shim-types.d.ts
4242
cp src/internal/shim-types.d.ts dist/internal/shim-types.d.mts
43-
mkdir -p dist/internal/polyfill
44-
cp src/internal/polyfill/*.{mjs,js,d.ts} dist/internal/polyfill
43+
mkdir -p dist/internal/shims
44+
cp src/internal/shims/*.{mjs,js,d.ts} dist/internal/shims
4545

4646
node scripts/utils/postprocess-files.cjs
4747

src/client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,9 @@ export class Lightswitch {
472472

473473
const timeout = setTimeout(() => controller.abort(), ms);
474474

475-
const isReadableBody = Shims.isReadableLike(options.body);
475+
const isReadableBody =
476+
((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
477+
(typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
476478

477479
const fetchOptions: RequestInit = {
478480
signal: controller.signal as any,

src/internal/polyfill/file.node.d.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/internal/polyfill/file.node.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/internal/polyfill/file.node.mjs

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/internal/shims.ts

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,62 +20,6 @@ export function getDefaultFetch(): Fetch {
2020
);
2121
}
2222

23-
/**
24-
* A minimal copy of the NodeJS `stream.Readable` class so that we can
25-
* accept the NodeJS types in certain places, e.g. file uploads
26-
*
27-
* https://nodejs.org/api/stream.html#class-streamreadable
28-
*/
29-
export interface ReadableLike {
30-
readable: boolean;
31-
readonly readableEnded: boolean;
32-
readonly readableFlowing: boolean | null;
33-
readonly readableHighWaterMark: number;
34-
readonly readableLength: number;
35-
readonly readableObjectMode: boolean;
36-
destroyed: boolean;
37-
read(size?: number): any;
38-
pause(): this;
39-
resume(): this;
40-
isPaused(): boolean;
41-
destroy(error?: Error): this;
42-
[Symbol.asyncIterator](): AsyncIterableIterator<any>;
43-
}
44-
45-
/**
46-
* Determines if the given value looks like a NodeJS `stream.Readable`
47-
* object and that it is readable, i.e. has not been consumed.
48-
*
49-
* https://nodejs.org/api/stream.html#class-streamreadable
50-
*/
51-
export function isReadableLike(value: any) {
52-
// We declare our own class of Readable here, so it's not feasible to
53-
// do an 'instanceof' check. Instead, check for Readable-like properties.
54-
return !!value && value.readable === true && typeof value.read === 'function';
55-
}
56-
57-
/**
58-
* A minimal copy of the NodeJS `fs.ReadStream` class for usage within file uploads.
59-
*
60-
* https://nodejs.org/api/fs.html#class-fsreadstream
61-
*/
62-
export interface FsReadStreamLike extends ReadableLike {
63-
path: {}; // real type is string | Buffer but we can't reference `Buffer` here
64-
}
65-
66-
/**
67-
* Determines if the given value looks like a NodeJS `fs.ReadStream`
68-
* object.
69-
*
70-
* This just checks if the object matches our `Readable` interface
71-
* and defines a `path` property, there may be false positives.
72-
*
73-
* https://nodejs.org/api/fs.html#class-fsreadstream
74-
*/
75-
export function isFsReadStreamLike(value: any): value is FsReadStreamLike {
76-
return isReadableLike(value) && 'path' in value;
77-
}
78-
7923
type ReadableStreamArgs = ConstructorParameters<typeof ReadableStream>;
8024

8125
export function makeReadableStream(...args: ReadableStreamArgs): ReadableStream {

src/internal/shims/file.node.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// The infer is to make TS show it as a nice union type,
2+
// instead of literally `ConstructorParameters<typeof Blob>[0]`
3+
type FallbackBlobSource = ConstructorParameters<typeof Blob>[0] extends infer T ? T : never;
4+
/**
5+
* A [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) provides information about files.
6+
*/
7+
declare class FallbackFile extends Blob {
8+
constructor(sources: FallbackBlobSource, fileName: string, options?: any);
9+
/**
10+
* The name of the `File`.
11+
*/
12+
readonly name: string;
13+
/**
14+
* The last modified date of the `File`.
15+
*/
16+
readonly lastModified: number;
17+
}
18+
export type File = InstanceType<typeof File>;
19+
export const File: typeof globalThis extends { File: infer fileConstructor } ? fileConstructor
20+
: typeof FallbackFile;

0 commit comments

Comments
 (0)