@@ -37,7 +37,7 @@ import {
3737 InvalidArgumentError ,
3838 TemplateError ,
3939} from '../../errors'
40- import { toBlob } from '../../utils'
40+ import { toBlob , toUploadBody } from '../../utils'
4141
4242const FILESYSTEM_HTTP_ERROR_MAP : Record < number , ( message : string ) => Error > = {
4343 404 : ( message : string ) => new FileNotFoundError ( message ) ,
@@ -164,6 +164,26 @@ export interface FilesystemRequestOpts
164164 user ?: Username
165165}
166166
167+ /**
168+ * Options for writing files to the sandbox filesystem.
169+ */
170+ export interface FilesystemWriteOpts extends FilesystemRequestOpts {
171+ /**
172+ * When true, the upload will be gzip-compressed.
173+ */
174+ gzip ?: boolean
175+ }
176+
177+ /**
178+ * Options for reading files from the sandbox filesystem.
179+ */
180+ export interface FilesystemReadOpts extends FilesystemRequestOpts {
181+ /**
182+ * When true, the download will request gzip-encoded responses.
183+ */
184+ gzip ?: boolean
185+ }
186+
167187export interface FilesystemListOpts extends FilesystemRequestOpts {
168188 /**
169189 * Depth of the directory to list.
@@ -222,7 +242,7 @@ export class Filesystem {
222242 */
223243 async read (
224244 path : string ,
225- opts ?: FilesystemRequestOpts & { format ?: 'text' }
245+ opts ?: FilesystemReadOpts & { format ?: 'text' }
226246 ) : Promise < string >
227247 /**
228248 * Read file content as a `Uint8Array`.
@@ -237,7 +257,7 @@ export class Filesystem {
237257 */
238258 async read (
239259 path : string ,
240- opts ?: FilesystemRequestOpts & { format : 'bytes' }
260+ opts ?: FilesystemReadOpts & { format : 'bytes' }
241261 ) : Promise < Uint8Array >
242262 /**
243263 * Read file content as a `Blob`.
@@ -252,7 +272,7 @@ export class Filesystem {
252272 */
253273 async read (
254274 path : string ,
255- opts ?: FilesystemRequestOpts & { format : 'blob' }
275+ opts ?: FilesystemReadOpts & { format : 'blob' }
256276 ) : Promise < Blob >
257277 /**
258278 * Read file content as a `ReadableStream`.
@@ -267,12 +287,12 @@ export class Filesystem {
267287 */
268288 async read (
269289 path : string ,
270- opts ?: FilesystemRequestOpts & { format : 'stream' }
290+ opts ?: FilesystemReadOpts & { format : 'stream' }
271291 ) : Promise < ReadableStream < Uint8Array > >
272292 async read (
273293 path : string ,
274- opts ?: FilesystemRequestOpts & {
275- format ?: 'text' | 'stream ' | 'bytes ' | 'blob '
294+ opts ?: FilesystemReadOpts & {
295+ format ?: 'text' | 'bytes ' | 'blob ' | 'stream '
276296 }
277297 ) : Promise < unknown > {
278298 const format = opts ?. format ?? 'text'
@@ -285,6 +305,11 @@ export class Filesystem {
285305 user = defaultUsername
286306 }
287307
308+ const headers : Record < string , string > = { }
309+ if ( opts ?. gzip ) {
310+ headers [ 'Accept-Encoding' ] = 'gzip'
311+ }
312+
288313 const res = await this . envdApi . api . GET ( '/files' , {
289314 params : {
290315 query : {
@@ -294,6 +319,7 @@ export class Filesystem {
294319 } ,
295320 parseAs : format === 'bytes' ? 'arrayBuffer' : format ,
296321 signal : this . connectionConfig . getSignal ( opts ?. requestTimeoutMs ) ,
322+ headers,
297323 } )
298324
299325 const err = await handleFilesystemEnvdApiError ( res )
@@ -332,11 +358,11 @@ export class Filesystem {
332358 async write (
333359 path : string ,
334360 data : string | ArrayBuffer | Blob | ReadableStream ,
335- opts ?: FilesystemRequestOpts
361+ opts ?: FilesystemWriteOpts
336362 ) : Promise < WriteInfo >
337363 async write (
338364 files : WriteEntry [ ] ,
339- opts ?: FilesystemRequestOpts
365+ opts ?: FilesystemWriteOpts
340366 ) : Promise < WriteInfo [ ] >
341367 async write (
342368 pathOrFiles : string | WriteEntry [ ] ,
@@ -345,8 +371,8 @@ export class Filesystem {
345371 | ArrayBuffer
346372 | Blob
347373 | ReadableStream
348- | FilesystemRequestOpts ,
349- opts ?: FilesystemRequestOpts
374+ | FilesystemWriteOpts ,
375+ opts ?: FilesystemWriteOpts
350376 ) : Promise < WriteInfo | WriteInfo [ ] > {
351377 if ( typeof pathOrFiles !== 'string' && ! Array . isArray ( pathOrFiles ) ) {
352378 throw new Error ( 'Path or files are required' )
@@ -362,7 +388,7 @@ export class Filesystem {
362388 typeof pathOrFiles === 'string'
363389 ? {
364390 path : pathOrFiles ,
365- writeOpts : opts as FilesystemRequestOpts ,
391+ writeOpts : opts as FilesystemWriteOpts ,
366392 writeFiles : [
367393 {
368394 data : dataOrOpts as
@@ -375,7 +401,7 @@ export class Filesystem {
375401 }
376402 : {
377403 path : undefined ,
378- writeOpts : dataOrOpts as FilesystemRequestOpts ,
404+ writeOpts : dataOrOpts as FilesystemWriteOpts ,
379405 writeFiles : pathOrFiles as WriteEntry [ ] ,
380406 }
381407
@@ -394,11 +420,20 @@ export class Filesystem {
394420
395421 const results : WriteInfo [ ] = [ ]
396422
423+ const useGzip = writeOpts ?. gzip === true
424+
397425 if ( useOctetStream ) {
426+ const headers : Record < string , string > = {
427+ 'Content-Type' : 'application/octet-stream' ,
428+ }
429+ if ( useGzip ) {
430+ headers [ 'Content-Encoding' ] = 'gzip'
431+ }
432+
398433 const uploadResults = await Promise . all (
399434 writeFiles . map ( async ( file ) => {
400435 const filePath = path ?? ( file as WriteEntry ) . path
401- const blob = await toBlob ( file . data )
436+ const body = await toUploadBody ( file . data , useGzip )
402437
403438 const res = await this . envdApi . api . POST ( '/files' , {
404439 params : {
@@ -407,10 +442,8 @@ export class Filesystem {
407442 username : user ,
408443 } ,
409444 } ,
410- bodySerializer : ( ) => blob ,
411- headers : {
412- 'Content-Type' : 'application/octet-stream' ,
413- } ,
445+ bodySerializer : ( ) => body ,
446+ headers,
414447 signal : this . connectionConfig . getSignal (
415448 writeOpts ?. requestTimeoutMs
416449 ) ,
@@ -491,7 +524,7 @@ export class Filesystem {
491524 */
492525 async writeFiles (
493526 files : WriteEntry [ ] ,
494- opts ?: FilesystemRequestOpts
527+ opts ?: FilesystemWriteOpts
495528 ) : Promise < WriteInfo [ ] > {
496529 return this . write ( files , opts ) as Promise < WriteInfo [ ] >
497530 }
0 commit comments