feat: automation for models downloading

This commit is contained in:
Neko Ayaka
2024-12-02 14:59:13 +08:00
parent 0bbdb0c741
commit 43623a6d3f
6 changed files with 111 additions and 31 deletions
+5 -6
View File
@@ -5,12 +5,8 @@ export function rejectIfError<E = unknown>(error: E | undefined, reject: (error?
}
}
export function onError<E = unknown>(reject: (error?: E) => void, handler?: (error?: E) => void) {
return (error?: E) => rejectIfError(error, reject, handler)
}
export function resolveWhenNoError<R = void, E = unknown>(reject: (error?: E) => void, resolve: (result?: R) => void) {
return (err: E) => {
return (err?: E) => {
if (err) {
reject(err)
}
@@ -20,6 +16,10 @@ export function resolveWhenNoError<R = void, E = unknown>(reject: (error?: E) =>
}
}
export function onError<E = unknown>(reject: (error?: E) => void, handler?: (error?: E) => void) {
return (error?: E) => rejectIfError(error, reject, handler)
}
export function noError<
T,
U extends unknown[],
@@ -33,7 +33,6 @@ export function noError<
rejectIfError(err, reject)
return
}
return fn(...args)
}
}
+14 -7
View File
@@ -6,13 +6,20 @@ export async function exists(path: string) {
return true
}
catch (error) {
if (!(error instanceof Error))
throw error
if (!('code' in error))
throw error
if (error.code !== 'ENOENT')
throw error
if (isENOENTError(error))
return false
return false
throw error
}
}
export function isENOENTError(error: unknown): boolean {
if (!(error instanceof Error))
return false
if (!('code' in error))
return false
if (error.code !== 'ENOENT')
return false
return true
}
+28 -7
View File
@@ -1,6 +1,6 @@
import type { Buffer } from 'node:buffer'
import { createWriteStream, mkdirSync } from 'node:fs'
import { join } from 'node:path'
import { createWriteStream, existsSync, mkdirSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fromBuffer } from 'yauzl'
import { noError, onError, resolveWhenNoError } from './errors'
@@ -21,6 +21,8 @@ import { noError, onError, resolveWhenNoError } from './errors'
*/
export async function unzip(buffer: Buffer, target: string) {
return new Promise<void>((resolve, reject) => {
let pendingWrites = 0
fromBuffer(buffer, { lazyEntries: true }, noError(reject, (zipFile) => {
// This is the key. We start by reading the first entry.
zipFile.readEntry()
@@ -29,26 +31,45 @@ export async function unzip(buffer: Buffer, target: string) {
// to disk. Then call zipFile.readEntry() again to
// trigger the next cycle.
zipFile.on('entry', (entry) => {
// Directories
// Directories
if (/\/$/.test(entry.fileName)) {
// Create the directory then read the next entry.
mkdirSync(join(target, entry.fileName))
// Create the directory then read the next entry.
mkdirSync(join(target, entry.fileName), { recursive: true })
zipFile.readEntry()
return
}
// Files
const dir = dirname(join(target, entry.fileName))
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true })
}
// Write the file to disk.
pendingWrites++
zipFile.openReadStream(entry, noError(reject, (readStream) => {
const file = createWriteStream(join(target, entry.fileName))
readStream.pipe(file)
// Handle errors
file.on('error', onError(reject, zipFile.close))
file.on('error', (err) => {
pendingWrites--
zipFile.close()
reject(err)
})
// Wait until the file is finished writing, then read the next entry.
file.on('finish', () => file.close(() => { zipFile.readEntry() }))
file.on('finish', () => {
file.close(() => {
pendingWrites--
if (pendingWrites === 0) {
resolve()
}
zipFile.readEntry()
})
})
}))
})