import * as fs from "fs-extra" ; import * as path from "path" ; import { isText , isTooBig } from "codesandbox-import-utils/lib/is-text" ; import { IModule , INormalizedModules } from "codesandbox-import-util-types" ; import FileError from "./file-error" ; const MAX_FILE_SIZE = 5 * 1024 * 1024 ; export interface IUploads { [ path ] : Buffer ; } async function normalizeFilesInDirectory ( p , startingPath ) { const entries = await fs . readdir ( p ) ; const dirs = [ ] ; const files = [ ] ; const errors = [ ] ; let uploads = { } ; await Promise . all ( entries . map ( async ( e ) => { const absolutePath = path . join ( p , e ) ; const stat = await fs . stat ( absolutePath ) ; if ( stat . isDirectory ( ) ) { if ( e !== "node_modules" && e !== ".git" ) { dirs . push ( absolutePath ) ; } } else { files . push ( absolutePath ) ; } } ) ) ; const recursiveDirs = ( await Promise . all ( dirs . map ( ( d ) => normalizeFilesInDirectory ( d , startingPath ) ) ) ) . reduce ( ( prev , next ) => { next . errors . forEach ( ( e ) => { errors . push ( e ) ; } ) ; uploads = { ... next . uploads , ... uploads } ; return { ... prev , ... next . files } ; } , { } ) ; const fileData = ( await Promise . all ( files . map ( async ( t ) => { const code = await fs . readFile ( t ) ; const relativePath = t . replace ( startingPath + "/" , "" ) ; const isBinary = ! ( await isText ( t , code ) ) ; if ( isBinary ) { if ( code . byteLength > MAX_FILE_SIZE ) { errors . push ( new FileError ( isTooBig ( code ) ? "Is too big" : "Is a binary file" , relativePath , true ) ) ; return false ; } else { uploads [ relativePath ] = code ; return false ; } } return { path : relativePath , code : code . toString ( ) } ; } ) ) ) . reduce ( ( prev , next ) => { if ( next === false ) { return prev ; } return { ... prev , [ next . path ] : { content : next . code } } ; } , { } ) ; return { errors , uploads , files : { ... recursiveDirs , ... fileData } } ; } const exists = async ( p ) => { try { const stat = await fs . stat ( p ) ; return true ; } catch ( e ) { return false ; } } ; export param { string } path export default async function parseSandbox ( resolvedPath ) { const dirExists = await exists ( resolvedPath ) ; if ( ! dirExists ) { throw new Error ( `The given path (${ resolvedPath }) doesn't exist.` ) ; } const fileData = await normalizeFilesInDirectory ( resolvedPath , resolvedPath ) ; return fileData ; }