UNPKG

zippycli

Version:
1 lines 19.6 kB
{"version":3,"sources":["commands/download.ts"],"names":["join","pathJoin","flags","fse","extract","PARTIAL_FILE_PREFIX","DEFAULT_TIMEOUT","DEFAULT_UPDATE_INTERVAL","fstat","parseDate","pipelineP","dateHumanTimestamp","Progress","Command","Download","run","args","parse","source","timeout","update","mtime","outdir","dir","file","output","input","Error","sources","_readInputFile","req","_initRequest","errors","i","length","log","_handleSource","err","toString","exit","outfile","updateInterval","info","download","filename","filepath","stat","isFile","headResponse","Promise","resolve","reject","url","method","response","statusCode","contentLength","headers","acceptRanges","lastModified","contentLengthI","parseInt","size","canResume","dateModified","partFilename","_partialFilename","partFilepath","partFileStat","resumeFrom","ensureFile","createWriteStream","progress","start","_transferProgressOutputInit","dl","_download","stream","on","data","add","complete","end","_transferProgressOutputAfter","partFileDoneStat","time","getTime","utimes","move","resume","Range","statusCodeExpected","error","once","abort","then","catch","help","char","string","description","boolean","integer","default","name","required"],"mappings":"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","sourcesContent":["/* eslint-disable import/no-default-export */\n\nimport {join as pathJoin} from 'path';\n\nimport {flags} from '@oclif/command';\nimport fse from 'fs-extra';\nimport {extract} from 'zs-extract';\n\nimport {\n\tPARTIAL_FILE_PREFIX,\n\tDEFAULT_TIMEOUT,\n\tDEFAULT_UPDATE_INTERVAL\n} from '../constants';\nimport {fstat, parseDate, pipelineP, dateHumanTimestamp} from '../util';\nimport {Progress} from '../progress';\nimport {Command} from '../command';\nimport {IRequestFactory, IRequestResponse} from '../request';\n\n/**\n * Download command.\n */\nexport class Download extends Command {\n\t/**\n\t * Aliases.\n\t */\n\tpublic static readonly aliases = ['dl', 'd'];\n\n\t/**\n\t * Description.\n\t */\n\tpublic static readonly description = 'download file from source';\n\n\t/**\n\t * Examples.\n\t */\n\tpublic static readonly examples = [];\n\n\t/**\n\t * Flags.\n\t */\n\tpublic static readonly flags = {\n\t\thelp: flags.help({char: 'h'}),\n\t\toutput: flags.string({\n\t\t\tchar: 'o',\n\t\t\tdescription: 'output file'\n\t\t}),\n\t\tdir: flags.string({\n\t\t\tchar: 'd',\n\t\t\tdescription: 'output directory'\n\t\t}),\n\t\tinput: flags.boolean({\n\t\t\tchar: 'i',\n\t\t\tdescription: 'source is input file with a URL on each line'\n\t\t}),\n\t\tmtime: flags.boolean({\n\t\t\tchar: 'm',\n\t\t\tdescription: 'use server modified time if available'\n\t\t}),\n\t\ttimeout: flags.integer({\n\t\t\tchar: 't',\n\t\t\tdescription: 'request timeout in seconds',\n\t\t\tdefault: DEFAULT_TIMEOUT\n\t\t}),\n\t\tupdate: flags.integer({\n\t\t\tchar: 'u',\n\t\t\tdescription: 'update interval in milliseconds',\n\t\t\tdefault: DEFAULT_UPDATE_INTERVAL\n\t\t})\n\t};\n\n\t/**\n\t * Arguments.\n\t */\n\tpublic static readonly args = [\n\t\t{\n\t\t\tname: 'source',\n\t\t\trequired: true,\n\t\t\tdescription: 'source to download from'\n\t\t}\n\t];\n\n\t/**\n\t * Handler.\n\t */\n\tpublic async run() {\n\t\tconst {args, flags} = this.parse(Download);\n\t\tconst source = args.source as string;\n\t\tconst {timeout, update} = flags;\n\t\tconst mtime = flags.mtime || false;\n\t\tconst outdir = flags.dir || '';\n\t\tconst file = flags.output || '';\n\t\tconst input = flags.input || false;\n\t\tif (file && input) {\n\t\t\tthrow new Error('Both file and input arguments found');\n\t\t}\n\n\t\tconst sources = flags.input\n\t\t\t? await this._readInputFile(source)\n\t\t\t: [source];\n\n\t\tconst req = this._initRequest(timeout * 1000);\n\n\t\tlet errors = false;\n\n\t\tfor (let i = 0; i < sources.length; i++) {\n\t\t\tconst source = sources[i];\n\t\t\tif (i) {\n\t\t\t\tthis.log('');\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\t\tawait this._handleSource(\n\t\t\t\t\tsource,\n\t\t\t\t\toutdir,\n\t\t\t\t\tfile,\n\t\t\t\t\tmtime,\n\t\t\t\t\tupdate,\n\t\t\t\t\treq\n\t\t\t\t);\n\t\t\t} catch (err) {\n\t\t\t\terrors = true;\n\t\t\t\tthis.log(`error: ${(err as Error).toString()}`);\n\t\t\t}\n\t\t}\n\n\t\tif (errors) {\n\t\t\tthis.exit(1);\n\t\t}\n\t}\n\n\t/**\n\t * Handle an individual source.\n\t *\n\t * @param source The source.\n\t * @param outdir Output dir.\n\t * @param outfile Output files.\n\t * @param mtime Modification time.\n\t * @param updateInterval Update interval.\n\t * @param req Request factory.\n\t */\n\tprotected async _handleSource(\n\t\tsource: string,\n\t\toutdir: string,\n\t\toutfile: string,\n\t\tmtime: boolean,\n\t\tupdateInterval: number,\n\t\treq: IRequestFactory\n\t) {\n\t\tthis.log(`source: ${source}`);\n\n\t\tconst info = await extract(source, req);\n\t\tconst {download} = info;\n\t\tconst filename = outfile || info.filename;\n\n\t\tif (!filename) {\n\t\t\tthrow new Error('No filename extracted or specified');\n\t\t}\n\n\t\tthis.log(`download: ${download}`);\n\t\tthis.log(`filename: ${filename}`);\n\n\t\tif (outdir) {\n\t\t\tthis.log(`dir: ${outdir}`);\n\t\t}\n\t\tconst filepath = outdir ? pathJoin(outdir, filename) : filename;\n\n\t\t// Get file stat and size if a file.\n\t\tconst stat = await fstat(filepath);\n\n\t\t// If path already exists, and is not file, then error.\n\t\tif (stat && !stat.isFile()) {\n\t\t\tthrow new Error('Output filename already exists');\n\t\t}\n\n\t\t// Make a HEAD request to the download URL, to get file headers.\n\t\tconst headResponse = await new Promise<IRequestResponse>(\n\t\t\t(resolve, reject) => {\n\t\t\t\treq(\n\t\t\t\t\t{\n\t\t\t\t\t\turl: download,\n\t\t\t\t\t\tmethod: 'HEAD'\n\t\t\t\t\t},\n\t\t\t\t\t(err, response) => {\n\t\t\t\t\t\tif (err) {\n\t\t\t\t\t\t\treject(err);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolve(response);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t);\n\n\t\t// Verify the status code.\n\t\tconst {statusCode} = headResponse;\n\t\tif (statusCode !== 200) {\n\t\t\tthrow new Error(`Invalid status code: ${statusCode}`);\n\t\t}\n\n\t\t// Read headers.\n\t\tconst contentLength = headResponse.headers['content-length'];\n\t\tconst acceptRanges = headResponse.headers['accept-ranges'];\n\t\tconst lastModified = headResponse.headers['last-modified'];\n\t\tthis.log(`content-length: ${contentLength}`);\n\t\tthis.log(`accept-ranges: ${acceptRanges}`);\n\t\tthis.log(`last-modified: ${lastModified}`);\n\n\t\t// Parse the content-length header.\n\t\tconst contentLengthI = parseInt(contentLength || '', 10);\n\n\t\t// If path exists and is file, verify size.\n\t\tif (stat) {\n\t\t\tif (contentLengthI || contentLengthI === 0) {\n\t\t\t\tif (contentLengthI === stat.size) {\n\t\t\t\t\tthis.log('done: Already retrieved');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Invalid existing file size: ${stat.size}`);\n\t\t\t}\n\t\t\tthrow new Error('Could not verify correct file size');\n\t\t}\n\n\t\t// Determine if possible to resume any partial downloads.\n\t\tconst canResume = acceptRanges === 'bytes';\n\n\t\t// Parse the date modified.\n\t\tconst dateModified = parseDate(lastModified || '');\n\n\t\t// Create part file name.\n\t\tconst partFilename = this._partialFilename(filename);\n\t\tconst partFilepath = outdir\n\t\t\t? pathJoin(outdir, partFilename)\n\t\t\t: partFilename;\n\t\tthis.log(`filename-partial: ${partFilename}`);\n\n\t\t// Stat the part file if exists, throw if not file.\n\t\tconst partFileStat = await fstat(partFilepath);\n\t\tif (partFileStat && !partFileStat.isFile()) {\n\t\t\tthrow new Error('Partial file path exists but not a file');\n\t\t}\n\n\t\t// Get offset to resume download from if possible.\n\t\tconst resumeFrom = canResume && partFileStat ? partFileStat.size : 0;\n\t\tif (resumeFrom) {\n\t\t\tthis.log(`resume-from: ${resumeFrom}`);\n\t\t}\n\t\tif (resumeFrom > contentLengthI) {\n\t\t\tthrow new Error(`Partial larger than expected: ${resumeFrom}`);\n\t\t}\n\n\t\t// Open the file for append if resuming, else write.\n\t\tawait fse.ensureFile(partFilepath);\n\t\tconst file = fse.createWriteStream(partFilepath, {\n\t\t\tflags: resumeFrom ? 'a' : 'w'\n\t\t});\n\n\t\t// Only download if partial file is not complete.\n\t\tif (contentLengthI && resumeFrom !== contentLengthI) {\n\t\t\tthis.log(`download-start: ${dateHumanTimestamp()}`);\n\n\t\t\t// Start a progress monitor.\n\t\t\tconst progress = new Progress(contentLengthI, resumeFrom);\n\t\t\tprogress.start(updateInterval, this._transferProgressOutputInit());\n\n\t\t\t// Start download, monitoring progress.\n\t\t\tconst dl = this._download(file, download, req, resumeFrom);\n\t\t\tdl.stream.on('data', data => {\n\t\t\t\tprogress.add(data.length);\n\t\t\t});\n\n\t\t\t// Await completion.\n\t\t\ttry {\n\t\t\t\tawait dl.complete;\n\t\t\t} finally {\n\t\t\t\tprogress.end();\n\t\t\t\tthis._transferProgressOutputAfter();\n\t\t\t}\n\n\t\t\tthis.log(`download-end: ${dateHumanTimestamp()}`);\n\t\t}\n\t\t// Otherwise just close file.\n\t\telse {\n\t\t\tthis.log('already-complete: partial file already complete');\n\n\t\t\tawait new Promise(resolve => {\n\t\t\t\tfile.end(resolve);\n\t\t\t});\n\t\t}\n\n\t\tthis.log(`verify-size: ${contentLengthI}`);\n\n\t\t// Verify partial file size after download.\n\t\tconst partFileDoneStat = await fstat(partFilepath);\n\t\tif (!partFileDoneStat || !partFileDoneStat.isFile()) {\n\t\t\tthrow new Error('Failed to verify download file size');\n\t\t}\n\t\tif (partFileDoneStat.size !== contentLengthI) {\n\t\t\tconst {size} = partFileDoneStat;\n\t\t\tthrow new Error(`Unexpected download size: ${size}`);\n\t\t}\n\n\t\t// Set mtime if requested and available.\n\t\tif (dateModified && mtime) {\n\t\t\tconst time = dateModified.getTime() / 1000;\n\t\t\tthis.log(`setting-mtime: ${time}`);\n\t\t\tawait fse.utimes(partFilepath, time, time);\n\t\t}\n\n\t\t// Move partial.\n\t\tthis.log(`saving-partial: ${partFilename}`);\n\t\tawait fse.move(partFilepath, filepath);\n\n\t\t// All done.\n\t\tthis.log(`done: ${filename}`);\n\t}\n\n\t/**\n\t * Download file to a file stream.\n\t *\n\t * @param file File stream.\n\t * @param url Download URL.\n\t * @param req Request factory.\n\t * @param resume Resume offset.\n\t * @returns Stream object and a complete promise.\n\t */\n\tprotected _download(\n\t\tfile: fse.WriteStream,\n\t\turl: string,\n\t\treq: IRequestFactory,\n\t\tresume: number\n\t) {\n\t\tconst headers: {[key: string]: string} = {};\n\t\tif (resume) {\n\t\t\theaders.Range = `bytes=${resume}-`;\n\t\t}\n\t\tconst statusCodeExpected = resume ? 206 : 200;\n\n\t\tlet error: Error | null = null;\n\n\t\tconst stream = req({\n\t\t\turl,\n\t\t\theaders\n\t\t});\n\t\tstream.once('response', (response: IRequestResponse) => {\n\t\t\tconst {statusCode} = response;\n\t\t\tif (statusCode === statusCodeExpected) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstream.abort();\n\t\t\terror = new Error(`Invalid status code: ${statusCode}`);\n\t\t});\n\t\tconst complete = pipelineP(stream as any, file)\n\t\t\t.then(() => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(err => {\n\t\t\t\tthrow error || err;\n\t\t\t});\n\n\t\treturn {\n\t\t\tstream,\n\t\t\tcomplete\n\t\t};\n\t}\n\n\t/**\n\t * Get a partial name from filename.\n\t *\n\t * @param filename The filename.\n\t * @returns Partial name.\n\t */\n\tprotected _partialFilename(filename: string) {\n\t\treturn `${PARTIAL_FILE_PREFIX}${filename}`;\n\t}\n}\nexport default Download;\n"],"file":"download.mjs","sourceRoot":"../../src"}