All files / tar / mod.ts

100.00% Branches 0/0
100.00% Lines 22/22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x2
x1
 
x1
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x1
x1
 
x1
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x1
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x2
x1





















































































































































































































































































/**
 * Streaming utilities for working with tar archives.
 *
 * Files are not compressed, only collected into the archive.
 *
 * ```ts no-eval
 * import { UntarStream } from "@std/tar/untar-stream";
 * import { dirname, normalize } from "@std/path";
 *
 * for await (
 *   const entry of (await Deno.open("./out.tar.gz"))
 *     .readable
 *     .pipeThrough(new DecompressionStream("gzip"))
 *     .pipeThrough(new UntarStream())
 * ) {
 *   const path = normalize(entry.path);
 *   await Deno.mkdir(dirname(path));
 *   await entry.readable?.pipeTo((await Deno.create(path)).writable);
 * }
 * ```
 *
 * @experimental
 * @module
 */
import type { TarStreamFile as _interface_TarStreamFile } from "jsr:@std/[email protected]"
/**
 * The interface required to provide a file.
 *
 * @experimental
 */
interface TarStreamFile extends _interface_TarStreamFile {}
export type { TarStreamFile }

import type { TarStreamDir as _interface_TarStreamDir } from "jsr:@std/[email protected]"
/**
 * The interface required to provide a directory.
 *
 * @experimental
 */
interface TarStreamDir extends _interface_TarStreamDir {}
export type { TarStreamDir }

import type { TarStreamInput as _typeAlias_TarStreamInput } from "jsr:@std/[email protected]"
/**
 * A union type merging all the TarStream interfaces that can be piped into the
 * TarStream class.
 *
 * @experimental
 */
type TarStreamInput = _typeAlias_TarStreamInput
export type { TarStreamInput }

import type { TarStreamOptions as _interface_TarStreamOptions } from "jsr:@std/[email protected]"
/**
 * The options that can go along with a file or directory.
 *
 * @experimental
 */
interface TarStreamOptions extends _interface_TarStreamOptions {}
export type { TarStreamOptions }

import { TarStream as _class_TarStream } from "jsr:@std/[email protected]"
/**
 * ### Overview
 * A TransformStream to create a tar archive. Tar archives allow for storing
 * multiple files in a single file (called an archive, or sometimes a tarball).
 *   These archives typically have a single '.tar' extension.  This
 * implementation follows the [FreeBSD 15.0](https://man.freebsd.org/cgi/man.cgi?query=tar&sektion=5&apropos=0&manpath=FreeBSD+15.0-CURRENT) spec.
 *
 * ### File Format & Limitations
 * The ustar file format is used for creating the tar archive.  While this
 * format is compatible with most tar readers, the format has several
 * limitations, including:
 * - Paths must be at most 256 characters.
 * - Files must be at most 8 GiBs in size, or 64 GiBs if `sizeExtension` is set
 * to true.
 * - Sparse files are not supported.
 *
 * ### Usage
 * TarStream may throw an error for several reasons. A few of those are:
 * - The path is invalid.
 * - The size provided does not match that of the iterable's length.
 *
 * ### Compression
 * Tar archives are not compressed by default.  If you'd like to compress the
 * archive, you may do so by piping it through a compression stream.
 *
 * @experimental
 * @example Usage
 * ```ts no-eval
 * import { TarStream, type TarStreamInput } from "@std/tar/tar-stream";
 *
 * await ReadableStream.from<TarStreamInput>([
 *   {
 *     type: "directory",
 *     path: 'potato/'
 *   },
 *   {
 *     type: "file",
 *     path: 'deno.json',
 *     size: (await Deno.stat('deno.json')).size,
 *     readable: (await Deno.open('deno.json')).readable
 *   },
 *   {
 *     type: "file",
 *     path: '.vscode/settings.json',
 *     size: (await Deno.stat('.vscode/settings.json')).size,
 *     readable: (await Deno.open('.vscode/settings.json')).readable
 *   }
 * ])
 *   .pipeThrough(new TarStream())
 *   .pipeThrough(new CompressionStream('gzip'))
 *   .pipeTo((await Deno.create('./out.tar.gz')).writable)
 * ```
 */
class TarStream extends _class_TarStream {}
export { TarStream }

import { assertValidPath as _function_assertValidPath } from "jsr:@std/[email protected]"
/**
 * Asserts that the path provided is valid for a {@linkcode TarStream}.
 *
 * @experimental
 * @param path The path as a string
 *
 * @example Usage
 * ```ts no-assert no-eval
 * import { assertValidPath, TarStream, type TarStreamInput } from "@std/tar";
 *
 * const paths = (await Array.fromAsync(Deno.readDir("./")))
 *   .filter(entry => entry.isFile)
 *   .map((entry) => entry.name)
 *   // Filter out any paths that are invalid as they are to be placed inside a Tar.
 *   .filter(path => {
 *     try {
 *       assertValidPath(path);
 *       return true;
 *     } catch (error) {
 *       console.error(error);
 *       return false;
 *     }
 *   });
 *
 * await Deno.mkdir('./out/', { recursive: true })
 * await ReadableStream.from(paths)
 *   .pipeThrough(
 *     new TransformStream<string, TarStreamInput>({
 *       async transform(path, controller) {
 *         controller.enqueue({
 *           type: "file",
 *           path,
 *           size: (await Deno.stat(path)).size,
 *           readable: (await Deno.open(path)).readable,
 *         });
 *       },
 *     }),
 *   )
 *   .pipeThrough(new TarStream())
 *   .pipeThrough(new CompressionStream('gzip'))
 *   .pipeTo((await Deno.create('./out/archive.tar.gz')).writable);
 * ```
 */
const assertValidPath = _function_assertValidPath as typeof _function_assertValidPath
export { assertValidPath }

import { assertValidTarStreamOptions as _function_assertValidTarStreamOptions } from "jsr:@std/[email protected]"
/**
 * Asserts that the options provided are valid for a {@linkcode TarStream}.
 *
 * @experimental
 * @param options The TarStreamOptions
 *
 * @example Usage
 * ```ts no-assert no-eval
 * import { assertValidTarStreamOptions, TarStream, type TarStreamInput } from "@std/tar";
 *
 *  const paths = (await Array.fromAsync(Deno.readDir('./')))
 *   .filter(entry => entry.isFile)
 *   .map(entry => entry.name);
 *
 * await Deno.mkdir('./out/', { recursive: true })
 * await ReadableStream.from(paths)
 *   .pipeThrough(new TransformStream<string, TarStreamInput>({
 *     async transform(path, controller) {
 *       const stats = await Deno.stat(path);
 *       const options = { mtime: stats.mtime?.getTime()! / 1000 };
 *       try {
 *         // Filter out any paths that would have an invalid options provided.
 *         assertValidTarStreamOptions(options);
 *         controller.enqueue({
 *           type: "file",
 *           path,
 *           size: stats.size,
 *           readable: (await Deno.open(path)).readable,
 *           options,
 *         });
 *       } catch (error) {
 *         console.error(error);
 *       }
 *     },
 *   }))
 *   .pipeThrough(new TarStream())
 *   .pipeThrough(new CompressionStream('gzip'))
 *   .pipeTo((await Deno.create('./out/archive.tar.gz')).writable);
 * ```
 */
const assertValidTarStreamOptions = _function_assertValidTarStreamOptions as typeof _function_assertValidTarStreamOptions
export { assertValidTarStreamOptions }

import type { OldStyleFormat as _interface_OldStyleFormat } from "jsr:@std/[email protected]"
/**
 * The original tar	archive	header format.
 *
 * @experimental
 */
interface OldStyleFormat extends _interface_OldStyleFormat {}
export type { OldStyleFormat }

import type { PosixUstarFormat as _interface_PosixUstarFormat } from "jsr:@std/[email protected]"
/**
 * The POSIX ustar archive header format.
 *
 * @experimental
 */
interface PosixUstarFormat extends _interface_PosixUstarFormat {}
export type { PosixUstarFormat }

import type { TarStreamEntry as _interface_TarStreamEntry } from "jsr:@std/[email protected]"
/**
 * The structure of an entry extracted from a Tar archive.
 *
 * @experimental
 */
interface TarStreamEntry extends _interface_TarStreamEntry {}
export type { TarStreamEntry }

import { UntarStream as _class_UntarStream } from "jsr:@std/[email protected]"
/**
 * ### Overview
 * A TransformStream to expand a tar archive.  Tar archives allow for storing
 * multiple files in a single file (called an archive, or sometimes a tarball).
 *
 * These archives typically have a single '.tar' extension.  This
 * implementation follows the [FreeBSD 15.0](https://man.freebsd.org/cgi/man.cgi?query=tar&sektion=5&apropos=0&manpath=FreeBSD+15.0-CURRENT) spec.
 *
 * ### Supported File Formats
 * Only the ustar file format is supported.  This is the most common format.
 * Additionally the numeric extension for file size.
 *
 * ### Usage
 * When expanding the archive, as demonstrated in the example, one must decide
 * to either consume the ReadableStream property, if present, or cancel it. The
 * next entry won't be resolved until the previous ReadableStream is either
 * consumed or cancelled.
 *
 * ### Understanding Compressed
 * A tar archive may be compressed, often identified by an additional file
 * extension, such as '.tar.gz' for gzip. This TransformStream does not support
 * decompression which must be done before expanding the archive.
 *
 * @experimental
 * @example Usage
 * ```ts no-eval
 * import { UntarStream } from "@std/tar/untar-stream";
 * import { dirname, normalize } from "@std/path";
 *
 * for await (
 *   const entry of (await Deno.open("./out.tar.gz"))
 *     .readable
 *     .pipeThrough(new DecompressionStream("gzip"))
 *     .pipeThrough(new UntarStream())
 * ) {
 *   const path = normalize(entry.path);
 *   await Deno.mkdir(dirname(path));
 *   await entry.readable?.pipeTo((await Deno.create(path)).writable);
 * }
 * ```
 */
class UntarStream extends _class_UntarStream {}
export { UntarStream }