@php-wasm/stream-compression 0.0.1 → 0.9.17

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.
Files changed (59) hide show
  1. package/LICENSE +339 -0
  2. package/index.cjs +1 -0
  3. package/index.d.ts +143 -0
  4. package/index.js +546 -0
  5. package/package.json +36 -29
  6. package/{src/test/vitest-setup-file.ts → test/vitest-setup-file.d.ts} +0 -1
  7. package/utils/append-bytes.d.ts +7 -0
  8. package/utils/collect-bytes.d.ts +8 -0
  9. package/utils/collect-file.d.ts +8 -0
  10. package/utils/collect-string.d.ts +8 -0
  11. package/utils/concat-bytes.d.ts +9 -0
  12. package/utils/concat-string.d.ts +6 -0
  13. package/utils/concat-uint8-array.d.ts +7 -0
  14. package/utils/filter-stream.d.ts +7 -0
  15. package/utils/iterable-stream-polyfill.d.ts +1 -0
  16. package/utils/iterator-to-stream.d.ts +8 -0
  17. package/utils/limit-bytes.d.ts +8 -0
  18. package/utils/prepend-bytes.d.ts +7 -0
  19. package/utils/skip-first-bytes.d.ts +7 -0
  20. package/utils/skip-last-bytes.d.ts +7 -0
  21. package/utils/streamed-file.d.ts +39 -0
  22. package/zip/decode-remote-zip.d.ts +14 -0
  23. package/zip/decode-zip.d.ts +82 -0
  24. package/zip/encode-zip.d.ts +7 -0
  25. package/{src/zip/index.ts → zip/index.d.ts} +0 -2
  26. package/zip/types.d.ts +66 -0
  27. package/.eslintrc.json +0 -18
  28. package/project.json +0 -34
  29. package/src/index.ts +0 -7
  30. package/src/test/append-bytes.spec.ts +0 -25
  31. package/src/test/decode-zip.spec.ts +0 -22
  32. package/src/test/encode-zip.spec.ts +0 -47
  33. package/src/test/fixtures/hello-dolly.zip +0 -0
  34. package/src/test/prepend-bytes.spec.ts +0 -25
  35. package/src/test/skip-first-bytes.spec.ts +0 -41
  36. package/src/test/skip-last-bytes.spec.ts +0 -27
  37. package/src/utils/append-bytes.ts +0 -16
  38. package/src/utils/collect-bytes.ts +0 -24
  39. package/src/utils/collect-file.ts +0 -16
  40. package/src/utils/collect-string.ts +0 -25
  41. package/src/utils/concat-bytes.ts +0 -38
  42. package/src/utils/concat-string.ts +0 -17
  43. package/src/utils/concat-uint8-array.ts +0 -17
  44. package/src/utils/filter-stream.ts +0 -15
  45. package/src/utils/iterable-stream-polyfill.ts +0 -35
  46. package/src/utils/iterator-to-stream.ts +0 -39
  47. package/src/utils/limit-bytes.ts +0 -40
  48. package/src/utils/prepend-bytes.ts +0 -18
  49. package/src/utils/skip-first-bytes.ts +0 -21
  50. package/src/utils/skip-last-bytes.ts +0 -24
  51. package/src/utils/streamed-file.ts +0 -58
  52. package/src/zip/decode-remote-zip.ts +0 -409
  53. package/src/zip/decode-zip.ts +0 -349
  54. package/src/zip/encode-zip.ts +0 -278
  55. package/src/zip/types.ts +0 -76
  56. package/tsconfig.json +0 -23
  57. package/tsconfig.lib.json +0 -14
  58. package/tsconfig.spec.json +0 -25
  59. package/vite.config.ts +0 -55
@@ -0,0 +1,8 @@
1
+ import { IterableReadableStream } from './iterable-stream-polyfill';
2
+ /**
3
+ * Converts an iterator or iterable to a stream.
4
+ *
5
+ * @param iteratorOrIterable The iterator or iterable to convert.
6
+ * @returns A stream that will yield the values from the iterator or iterable.
7
+ */
8
+ export declare function iteratorToStream<T>(iteratorOrIterable: AsyncIterator<T> | Iterator<T> | AsyncIterable<T> | Iterable<T>): IterableReadableStream<T>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Limit the number of bytes read from a stream.
3
+ *
4
+ * @param stream The stream to limit.
5
+ * @param bytes The number of bytes to read from the stream.
6
+ * @returns A new stream that will read at most `bytes` bytes from `stream`.
7
+ */
8
+ export declare function limitBytes(stream: ReadableStream<Uint8Array>, bytes: number): ReadableStream<any>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Prepend bytes to a stream.
3
+ *
4
+ * @param bytes The bytes to prepend.
5
+ * @returns A transform stream that will prepend the specified bytes.
6
+ */
7
+ export declare function prependBytes(bytes: Uint8Array): TransformStream<Uint8Array, Uint8Array>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Skips the first `length` bytes of a stream.
3
+ *
4
+ * @param length The number of bytes to skip.
5
+ * @returns A transform stream that will skip the specified number of bytes.
6
+ */
7
+ export declare function skipFirstBytes(length: number): TransformStream<Uint8Array, Uint8Array>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Skips the first `length` bytes of a stream.
3
+ *
4
+ * @param length The number of bytes to skip.
5
+ * @returns A transform stream that will skip the specified number of bytes.
6
+ */
7
+ export declare function skipLastBytes(skip: number, streamLength: number): TransformStream<any, any>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Represents a file that is streamed and not fully
3
+ * loaded into memory.
4
+ */
5
+ export declare class StreamedFile extends File {
6
+ private readableStream;
7
+ /**
8
+ * Creates a new StreamedFile instance.
9
+ *
10
+ * @param readableStream The readable stream containing the file data.
11
+ * @param name The name of the file.
12
+ * @param type The MIME type of the file.
13
+ */
14
+ constructor(readableStream: ReadableStream<Uint8Array>, name: string, type?: string);
15
+ /**
16
+ * Overrides the slice() method of the File class.
17
+ *
18
+ * @returns A Blob representing a portion of the file.
19
+ */
20
+ slice(): Blob;
21
+ /**
22
+ * Returns the readable stream associated with the file.
23
+ *
24
+ * @returns The readable stream.
25
+ */
26
+ stream(): ReadableStream<Uint8Array>;
27
+ /**
28
+ * Loads the file data into memory and then returns it as a string.
29
+ *
30
+ * @returns File data as text.
31
+ */
32
+ text(): Promise<string>;
33
+ /**
34
+ * Loads the file data into memory and then returns it as an ArrayBuffer.
35
+ *
36
+ * @returns File data as an ArrayBuffer.
37
+ */
38
+ arrayBuffer(): Promise<Uint8Array>;
39
+ }
@@ -0,0 +1,14 @@
1
+ import { CentralDirectoryEntry, FileEntry } from './types';
2
+ import { IterableReadableStream } from '../utils/iterable-stream-polyfill';
3
+ /**
4
+ * Streams the contents of a remote zip file.
5
+ *
6
+ * If the zip is large and the predicate is filtering the zip contents,
7
+ * only the matching files will be downloaded using the Range header
8
+ * (if supported by the server).
9
+ *
10
+ * @param url The URL of the zip file.
11
+ * @param predicate Optional. A function that returns true if the file should be downloaded.
12
+ * @returns A stream of zip entries.
13
+ */
14
+ export declare function decodeRemoteZip(url: string, predicate?: (dirEntry: CentralDirectoryEntry | FileEntry) => boolean): Promise<IterableReadableStream<FileEntry> | IterableReadableStream<File>>;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Reads files from a stream of zip file bytes.
3
+ */
4
+ import { IterableReadableStream } from '../utils/iterable-stream-polyfill';
5
+ import { CentralDirectoryEntry, FileEntry } from './types';
6
+ /**
7
+ * Unzips a stream of zip file bytes.
8
+ *
9
+ * @param stream A stream of zip file bytes.
10
+ * @param predicate Optional. A function that returns true if the file should be downloaded.
11
+ * @returns An iterable stream of File objects.
12
+ */
13
+ export declare function decodeZip(stream: ReadableStream<Uint8Array>, predicate?: () => boolean): IterableReadableStream<File>;
14
+ /**
15
+ * Parses a stream of zipped bytes into FileEntry informations.
16
+ *
17
+ * @param stream A stream of zip file bytes.
18
+ * @param predicate Optional. A function that returns true if the file should be downloaded.
19
+ * @returns An iterable stream of FileEntry objects.
20
+ */
21
+ export declare function streamZippedFileEntries(stream: ReadableStream<Uint8Array>, predicate?: (dirEntry: CentralDirectoryEntry | FileEntry) => boolean): IterableReadableStream<FileEntry>;
22
+ /**
23
+ * Reads a file entry from a zip file.
24
+ *
25
+ * The file entry is structured as follows:
26
+ *
27
+ * ```
28
+ * Offset Bytes Description
29
+ * 0 4 Local file header signature = 0x04034b50 (PK♥♦ or "PK\3\4")
30
+ * 4 2 Version needed to extract (minimum)
31
+ * 6 2 General purpose bit flag
32
+ * 8 2 Compression method; e.g. none = 0, DEFLATE = 8 (or "\0x08\0x00")
33
+ * 10 2 File last modification time
34
+ * 12 2 File last modification date
35
+ * 14 4 CRC-32 of uncompressed data
36
+ * 18 4 Compressed size (or 0xffffffff for ZIP64)
37
+ * 22 4 Uncompressed size (or 0xffffffff for ZIP64)
38
+ * 26 2 File name length (n)
39
+ * 28 2 Extra field length (m)
40
+ * 30 n File name
41
+ * 30+n m Extra field
42
+ * ```
43
+ *
44
+ * @param stream
45
+ * @param skipSignature Do not consume the signature from the stream.
46
+ * @returns
47
+ */
48
+ export declare function readFileEntry(stream: ReadableStream<Uint8Array>, skipSignature?: boolean): Promise<FileEntry | null>;
49
+ /**
50
+ * Reads a central directory entry from a zip file.
51
+ *
52
+ * The central directory entry is structured as follows:
53
+ *
54
+ * ```
55
+ * Offset Bytes Description
56
+ * 0 4 Central directory file header signature = 0x02014b50
57
+ * 4 2 Version made by
58
+ * 6 2 Version needed to extract (minimum)
59
+ * 8 2 General purpose bit flag
60
+ * 10 2 Compression method
61
+ * 12 2 File last modification time
62
+ * 14 2 File last modification date
63
+ * 16 4 CRC-32 of uncompressed data
64
+ * 20 4 Compressed size (or 0xffffffff for ZIP64)
65
+ * 24 4 Uncompressed size (or 0xffffffff for ZIP64)
66
+ * 28 2 File name length (n)
67
+ * 30 2 Extra field length (m)
68
+ * 32 2 File comment length (k)
69
+ * 34 2 Disk number where file starts (or 0xffff for ZIP64)
70
+ * 36 2 Internal file attributes
71
+ * 38 4 External file attributes
72
+ * 42 4 Relative offset of local file header (or 0xffffffff for ZIP64). This is the number of bytes between the start of the first disk on which the file occurs, and the start of the local file header. This allows software reading the central directory to locate the position of the file inside the ZIP file.
73
+ * 46 n File name
74
+ * 46+n m Extra field
75
+ * 46+n+m k File comment
76
+ * ```
77
+ *
78
+ * @param stream
79
+ * @param skipSignature
80
+ * @returns
81
+ */
82
+ export declare function readCentralDirectoryEntry(stream: ReadableStream<Uint8Array>, skipSignature?: boolean): Promise<CentralDirectoryEntry | null>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Compresses the given files into a ZIP archive.
3
+ *
4
+ * @param files - An async or sync iterable of files to be compressed.
5
+ * @returns A readable stream of the compressed ZIP archive as Uint8Array chunks.
6
+ */
7
+ export declare function encodeZip(files: AsyncIterable<File> | Iterable<File>): ReadableStream<Uint8Array>;
@@ -1,5 +1,3 @@
1
- import '../utils/iterable-stream-polyfill';
2
-
3
1
  export * from './decode-zip';
4
2
  export * from './decode-remote-zip';
5
3
  export * from './encode-zip';
package/zip/types.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ export declare const FILE_HEADER_SIZE = 32;
2
+ export declare const SIGNATURE_FILE: 67324752;
3
+ export declare const SIGNATURE_CENTRAL_DIRECTORY: 33639248;
4
+ export declare const SIGNATURE_CENTRAL_DIRECTORY_END: 101010256;
5
+ export declare const SIGNATURE_DATA_DESCRIPTOR: 134695760;
6
+ export declare const COMPRESSION_NONE: 0;
7
+ export declare const COMPRESSION_DEFLATE: 8;
8
+ export type CompressionMethod = typeof COMPRESSION_NONE | typeof COMPRESSION_DEFLATE;
9
+ export type ZipEntry = FileEntry | CentralDirectoryEntry | CentralDirectoryEndEntry;
10
+ /**
11
+ * Data of the file entry header encoded in a ".zip" file.
12
+ */
13
+ export interface FileHeader {
14
+ signature: typeof SIGNATURE_FILE;
15
+ version: number;
16
+ generalPurpose: number;
17
+ compressionMethod: CompressionMethod;
18
+ lastModifiedTime: number;
19
+ lastModifiedDate: number;
20
+ crc: number;
21
+ compressedSize: number;
22
+ uncompressedSize: number;
23
+ path: Uint8Array;
24
+ extra: Uint8Array;
25
+ }
26
+ export interface FileEntry extends FileHeader {
27
+ isDirectory: boolean;
28
+ bytes: Uint8Array;
29
+ }
30
+ /**
31
+ * Data of the central directory entry encoded in a ".zip" file.
32
+ */
33
+ export interface CentralDirectoryEntry {
34
+ signature: typeof SIGNATURE_CENTRAL_DIRECTORY;
35
+ versionCreated: number;
36
+ versionNeeded: number;
37
+ generalPurpose: number;
38
+ compressionMethod: CompressionMethod;
39
+ lastModifiedTime: number;
40
+ lastModifiedDate: number;
41
+ crc: number;
42
+ compressedSize: number;
43
+ uncompressedSize: number;
44
+ diskNumber: number;
45
+ internalAttributes: number;
46
+ externalAttributes: number;
47
+ firstByteAt: number;
48
+ lastByteAt: number;
49
+ path: Uint8Array;
50
+ extra: Uint8Array;
51
+ fileComment: Uint8Array;
52
+ isDirectory: boolean;
53
+ }
54
+ /**
55
+ * Data of the central directory end entry encoded in a ".zip" file.
56
+ */
57
+ export interface CentralDirectoryEndEntry {
58
+ signature: typeof SIGNATURE_CENTRAL_DIRECTORY_END;
59
+ numberOfDisks: number;
60
+ centralDirectoryStartDisk: number;
61
+ numberCentralDirectoryRecordsOnThisDisk: number;
62
+ numberCentralDirectoryRecords: number;
63
+ centralDirectorySize: number;
64
+ centralDirectoryOffset: number;
65
+ comment: Uint8Array;
66
+ }
package/.eslintrc.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "extends": ["../../../.eslintrc.json"],
3
- "ignorePatterns": ["!**/*"],
4
- "overrides": [
5
- {
6
- "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7
- "rules": {}
8
- },
9
- {
10
- "files": ["*.ts", "*.tsx"],
11
- "rules": {}
12
- },
13
- {
14
- "files": ["*.js", "*.jsx"],
15
- "rules": {}
16
- }
17
- ]
18
- }
package/project.json DELETED
@@ -1,34 +0,0 @@
1
- {
2
- "name": "php-wasm-stream-compression",
3
- "$schema": "../../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "packages/php-wasm/stream-compression/src",
5
- "projectType": "library",
6
- "targets": {
7
- "build": {
8
- "executor": "@nx/vite:build",
9
- "outputs": ["{options.outputPath}"],
10
- "options": {
11
- "outputPath": "dist/packages/php-wasm/stream-compression"
12
- }
13
- },
14
- "test": {
15
- "executor": "@nx/vite:test",
16
- "outputs": ["{options.reportsDirectory}"],
17
- "options": {
18
- "passWithNoTests": true,
19
- "reportsDirectory": "../../../coverage/packages/php-wasm/stream-compression"
20
- }
21
- },
22
- "lint": {
23
- "executor": "@nx/linter:eslint",
24
- "outputs": ["{options.outputFile}"],
25
- "options": {
26
- "lintFilePatterns": [
27
- "packages/php-wasm/stream-compression/**/*.ts",
28
- "packages/php-wasm/stream-compression/package.json"
29
- ]
30
- }
31
- }
32
- },
33
- "tags": ["scope:independent-from-php-binaries"]
34
- }
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- import '@php-wasm/node-polyfills';
2
-
3
- export { collectBytes } from './utils/collect-bytes';
4
- export { collectFile } from './utils/collect-file';
5
- export { iteratorToStream } from './utils/iterator-to-stream';
6
- export { StreamedFile } from './utils/streamed-file';
7
- export { encodeZip, decodeZip, decodeRemoteZip } from './zip';
@@ -1,25 +0,0 @@
1
- import { appendBytes } from '../utils/append-bytes';
2
-
3
- describe('appendBytes', () => {
4
- it('Should append the specified number of bytes', async () => {
5
- const stream = new ReadableStream<Uint8Array>({
6
- type: 'bytes',
7
- start(controller) {
8
- controller.enqueue(new Uint8Array([1, 2, 3]));
9
- controller.close();
10
- },
11
- }).pipeThrough(appendBytes(new Uint8Array([4, 5])));
12
-
13
- const reader = stream.getReader();
14
- const result1 = await reader.read();
15
- expect(result1.value).toEqual(new Uint8Array([1, 2, 3]));
16
- expect(result1.done).toBe(false);
17
-
18
- const result2 = await reader.read();
19
- expect(result2.value).toEqual(new Uint8Array([4, 5]));
20
- expect(result2.done).toBe(false);
21
-
22
- const result3 = await reader.read();
23
- expect(result3.done).toBe(true);
24
- });
25
- });
@@ -1,22 +0,0 @@
1
- import { decodeZip } from '../zip/decode-zip';
2
- import { readFile } from 'fs/promises';
3
-
4
- describe('decodeZip', () => {
5
- it('Should uncompress compress files', async () => {
6
- const zipBytes = await readFile(
7
- __dirname + '/fixtures/hello-dolly.zip'
8
- );
9
- const zipStream = decodeZip(new Blob([zipBytes]).stream());
10
-
11
- const files = [];
12
- for await (const file of zipStream) {
13
- files.push(file);
14
- }
15
- expect(files.length).toBe(3);
16
- expect(files[0].name).toBe('hello-dolly/');
17
- expect(files[1].name).toBe('hello-dolly/hello.php');
18
- expect(files[1].size).toBe(2593);
19
- expect(files[2].name).toBe('hello-dolly/readme.txt');
20
- expect(files[2].size).toBe(624);
21
- });
22
- });
@@ -1,47 +0,0 @@
1
- import { collectBytes } from '../utils/collect-bytes';
2
- import { encodeZip } from '../zip/encode-zip';
3
- import { decodeZip } from '../zip/decode-zip';
4
-
5
- describe('compressFiles', () => {
6
- it('Should compress files into a zip archive', async () => {
7
- const files: File[] = [
8
- new File(
9
- [new Uint8Array([1, 2, 3, 4, 5])],
10
- 'wp-content/plugins/hello.php'
11
- ),
12
- new File(
13
- [new Uint8Array([1, 2, 3, 4, 5])],
14
- 'wp-content/plugins/hello/hello.php'
15
- ),
16
- new File(
17
- [new Uint8Array([1, 2, 3, 4, 5])],
18
- 'wp-content/plugins/hello/hello2.php'
19
- ),
20
- new File(
21
- [new Uint8Array([1, 2, 3, 4, 5])],
22
- 'wp-content/plugins/hello/hello3.php'
23
- ),
24
- ];
25
-
26
- const zipBytes = await collectBytes(
27
- encodeZip(files[Symbol.iterator]())
28
- );
29
- const zipStream = decodeZip(new Blob([zipBytes!]).stream());
30
-
31
- const reader = zipStream.getReader();
32
- let i = 0;
33
- for (i = 0; i < files.length; i++) {
34
- const { value: receivedFile, done } = await reader.read();
35
- const receivedBytes = new Uint8Array(
36
- await receivedFile!.arrayBuffer()
37
- );
38
- const expectedBytes = new Uint8Array(await files[i].arrayBuffer());
39
- expect(receivedBytes).toEqual(expectedBytes);
40
- expect(done).toBe(false);
41
- }
42
- expect(i).toBe(files.length);
43
-
44
- const { done } = await reader.read();
45
- expect(done).toBe(true);
46
- });
47
- });
Binary file
@@ -1,25 +0,0 @@
1
- import { prependBytes } from '../utils/prepend-bytes';
2
-
3
- describe('prependBytes', () => {
4
- it('Should prepend the specified number of bytes', async () => {
5
- const stream = new ReadableStream<Uint8Array>({
6
- type: 'bytes',
7
- start(controller) {
8
- controller.enqueue(new Uint8Array([4, 5]));
9
- controller.close();
10
- },
11
- }).pipeThrough(prependBytes(new Uint8Array([1, 2, 3])));
12
-
13
- const reader = stream.getReader();
14
- const result1 = await reader.read();
15
- expect(result1.value).toEqual(new Uint8Array([1, 2, 3]));
16
- expect(result1.done).toBe(false);
17
-
18
- const result2 = await reader.read();
19
- expect(result2.value).toEqual(new Uint8Array([4, 5]));
20
- expect(result2.done).toBe(false);
21
-
22
- const result3 = await reader.read();
23
- expect(result3.done).toBe(true);
24
- });
25
- });
@@ -1,41 +0,0 @@
1
- import { skipFirstBytes } from '../utils/skip-first-bytes';
2
-
3
- describe('skipFirstBytes', () => {
4
- it('Should skip the specified number of bytes', async () => {
5
- const stream = new ReadableStream<Uint8Array>({
6
- type: 'bytes',
7
- start(controller) {
8
- controller.enqueue(new Uint8Array([1, 2, 3, 4, 5]));
9
- controller.close();
10
- },
11
- }).pipeThrough(skipFirstBytes(3));
12
-
13
- const reader = stream.getReader();
14
- const result1 = await reader.read();
15
- expect(result1.value).toEqual(new Uint8Array([4, 5]));
16
- expect(result1.done).toBe(false);
17
-
18
- const result2 = await reader.read();
19
- expect(result2.done).toBe(true);
20
- });
21
-
22
- it('Should skip the specified number of bytes across multiple pulls', async () => {
23
- const stream = new ReadableStream<Uint8Array>({
24
- type: 'bytes',
25
- start(controller) {
26
- controller.enqueue(new Uint8Array([1]));
27
- controller.enqueue(new Uint8Array([2, 3]));
28
- controller.enqueue(new Uint8Array([4, 5, 6]));
29
- controller.close();
30
- },
31
- }).pipeThrough(skipFirstBytes(4));
32
-
33
- const reader = stream.getReader();
34
- const result1 = await reader.read();
35
- expect(result1.value).toEqual(new Uint8Array([5, 6]));
36
- expect(result1.done).toBe(false);
37
-
38
- const result2 = await reader.read();
39
- expect(result2.done).toBe(true);
40
- });
41
- });
@@ -1,27 +0,0 @@
1
- import { skipLastBytes } from '../utils/skip-last-bytes';
2
-
3
- describe('skipLastBytes', () => {
4
- it('Should skip the specified number of bytes', async () => {
5
- const stream = new ReadableStream<Uint8Array>({
6
- type: 'bytes',
7
- start(controller) {
8
- controller.enqueue(new Uint8Array([1, 2, 3, 4, 5]));
9
- controller.enqueue(new Uint8Array([6, 7]));
10
- controller.enqueue(new Uint8Array([8, 9]));
11
- controller.close();
12
- },
13
- }).pipeThrough(skipLastBytes(3, 9));
14
-
15
- const reader = stream.getReader();
16
- const result1 = await reader.read();
17
- expect(result1.value).toEqual(new Uint8Array([1, 2, 3, 4, 5]));
18
- expect(result1.done).toBe(false);
19
-
20
- const result2 = await reader.read();
21
- expect(result2.value).toEqual(new Uint8Array([6]));
22
- expect(result2.done).toBe(false);
23
-
24
- const result3 = await reader.read();
25
- expect(result3.done).toBe(true);
26
- });
27
- });
@@ -1,16 +0,0 @@
1
- /**
2
- * Appends bytes to a stream.
3
- *
4
- * @param bytes The bytes to append.
5
- * @returns A transform stream that will append the specified bytes.
6
- */
7
- export function appendBytes(bytes: Uint8Array) {
8
- return new TransformStream<Uint8Array, Uint8Array>({
9
- async transform(chunk, controller) {
10
- controller.enqueue(chunk);
11
- },
12
- async flush(controller) {
13
- controller.enqueue(bytes);
14
- },
15
- });
16
- }
@@ -1,24 +0,0 @@
1
- import { concatBytes } from './concat-bytes';
2
- import { limitBytes } from './limit-bytes';
3
-
4
- /**
5
- * Collects the contents of the entire stream into a single Uint8Array.
6
- *
7
- * @param stream The stream to collect.
8
- * @param bytes Optional. The number of bytes to read from the stream.
9
- * @returns The string contents of the stream.
10
- */
11
- export async function collectBytes(
12
- stream: ReadableStream<Uint8Array>,
13
- bytes?: number
14
- ) {
15
- if (bytes !== undefined) {
16
- stream = limitBytes(stream, bytes);
17
- }
18
-
19
- return await stream
20
- .pipeThrough(concatBytes(bytes))
21
- .getReader()
22
- .read()
23
- .then(({ value }) => value!);
24
- }
@@ -1,16 +0,0 @@
1
- import { collectBytes } from './collect-bytes';
2
-
3
- /**
4
- * Collects the contents of the entire stream into a single File object.
5
- *
6
- * @param stream The stream to collect.
7
- * @param fileName The name of the file
8
- * @returns The string contents of the stream.
9
- */
10
- export async function collectFile(
11
- fileName: string,
12
- stream: ReadableStream<Uint8Array>
13
- ) {
14
- // @TODO: use StreamingFile
15
- return new File([await collectBytes(stream)], fileName);
16
- }
@@ -1,25 +0,0 @@
1
- import { concatString } from './concat-string';
2
- import { limitBytes } from './limit-bytes';
3
-
4
- /**
5
- * Collects the contents of the entire stream into a single string.
6
- *
7
- * @param stream The stream to collect.
8
- * @param bytes Optional. The number of bytes to read from the stream.
9
- * @returns The string contents of the stream.
10
- */
11
- export async function collectString(
12
- stream: ReadableStream<Uint8Array>,
13
- bytes?: number
14
- ) {
15
- if (bytes !== undefined) {
16
- stream = limitBytes(stream, bytes);
17
- }
18
-
19
- return await stream
20
- .pipeThrough(new TextDecoderStream())
21
- .pipeThrough(concatString())
22
- .getReader()
23
- .read()
24
- .then(({ value }) => value);
25
- }
@@ -1,38 +0,0 @@
1
- import { concatUint8Array } from './concat-uint8-array';
2
-
3
- /**
4
- * Concatenates the contents of the stream into a single Uint8Array.
5
- *
6
- * @param totalBytes Optional. The number of bytes to concatenate. Used to
7
- * pre-allocate the buffer. If not provided, the buffer will
8
- * be dynamically resized as needed.
9
- * @returns A stream that will emit a single UInt8Array entry before closing.
10
- */
11
- export function concatBytes(totalBytes?: number) {
12
- if (totalBytes === undefined) {
13
- let acc = new Uint8Array();
14
- return new TransformStream<Uint8Array, Uint8Array>({
15
- transform(chunk) {
16
- acc = concatUint8Array(acc, chunk);
17
- },
18
-
19
- flush(controller) {
20
- controller.enqueue(acc);
21
- },
22
- });
23
- } else {
24
- const buffer = new ArrayBuffer(totalBytes || 0);
25
- let offset = 0;
26
- return new TransformStream<Uint8Array, Uint8Array>({
27
- transform(chunk) {
28
- const view = new Uint8Array(buffer);
29
- view.set(chunk, offset);
30
- offset += chunk.byteLength;
31
- },
32
-
33
- flush(controller) {
34
- controller.enqueue(new Uint8Array(buffer));
35
- },
36
- });
37
- }
38
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Concatenate all chunks into a single string.
3
- *
4
- * @returns A stream that will emit a single string entry before closing.
5
- */
6
- export function concatString() {
7
- const chunks: string[] = [];
8
- return new TransformStream<string, string>({
9
- transform(chunk) {
10
- chunks.push(chunk);
11
- },
12
-
13
- flush(controller) {
14
- controller.enqueue(chunks.join(''));
15
- },
16
- });
17
- }