First upload version 0.0.1

This commit is contained in:
Neyra
2026-02-05 15:27:49 +08:00
commit 8e9b7201ed
4182 changed files with 593136 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
export default abstract class BaseDownloadEngineWriteStream {
abstract write(cursor: number, buffer: Uint8Array): Promise<void> | void;
close(): void | Promise<void>;
}

View File

@@ -0,0 +1,5 @@
export default class BaseDownloadEngineWriteStream {
close() {
}
}
//# sourceMappingURL=base-download-engine-write-stream.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"base-download-engine-write-stream.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/streams/download-engine-write-stream/base-download-engine-write-stream.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAgB,6BAA6B;IAGvD,KAAK;IACL,CAAC;CACJ"}

View File

@@ -0,0 +1,22 @@
import retry from "async-retry";
import { DownloadFile } from "../../types.js";
import BaseDownloadEngineWriteStream from "./base-download-engine-write-stream.js";
type DownloadEngineWriteStreamOptionsBrowser = {
retry?: retry.Options;
file?: DownloadFile;
};
export type DownloadEngineWriteStreamBrowserWriter = (cursor: number, buffer: Uint8Array, options: DownloadEngineWriteStreamOptionsBrowser) => Promise<void> | void;
export default class DownloadEngineWriteStreamBrowser extends BaseDownloadEngineWriteStream {
protected readonly _writer?: DownloadEngineWriteStreamBrowserWriter;
readonly options: DownloadEngineWriteStreamOptionsBrowser;
protected _memory: Uint8Array;
protected _bytesWritten: number;
get writerClosed(): boolean | 0 | undefined;
constructor(_writer?: DownloadEngineWriteStreamBrowserWriter, options?: DownloadEngineWriteStreamOptionsBrowser);
protected _ensureBuffer(length: number): Uint8Array;
write(cursor: number, buffer: Uint8Array): void | Promise<void>;
get result(): Uint8Array;
resultAsBlobURL(): string;
resultAsText(): string;
}
export {};

View File

@@ -0,0 +1,52 @@
import BaseDownloadEngineWriteStream from "./base-download-engine-write-stream.js";
import WriterIsClosedError from "./errors/writer-is-closed-error.js";
import WriterNotDefineError from "./errors/writer-not-define-error.js";
export default class DownloadEngineWriteStreamBrowser extends BaseDownloadEngineWriteStream {
_writer;
options = {};
_memory = new Uint8Array(0);
_bytesWritten = 0;
get writerClosed() {
return this.options.file?.totalSize && this._bytesWritten === this.options.file.totalSize;
}
constructor(_writer, options = {}) {
super();
this.options = options;
this._writer = _writer;
}
_ensureBuffer(length) {
if (this._memory.length >= length) {
return this._memory;
}
if (!this.options.file) {
throw new WriterNotDefineError("Writer & file is not defined, please provide a writer or file");
}
const newSize = Math.max(length, this.options.file.totalSize);
const newMemory = new Uint8Array(newSize);
newMemory.set(this._memory);
return this._memory = newMemory;
}
write(cursor, buffer) {
if (this.writerClosed) {
throw new WriterIsClosedError();
}
if (!this._writer) {
this._ensureBuffer(cursor + buffer.byteLength)
.set(buffer, cursor);
this._bytesWritten += buffer.byteLength;
return;
}
return this._writer(cursor, buffer, this.options);
}
get result() {
return this._memory;
}
resultAsBlobURL() {
const blob = new Blob([this._memory]);
return URL.createObjectURL(blob);
}
resultAsText() {
return new TextDecoder().decode(this._memory);
}
}
//# sourceMappingURL=download-engine-write-stream-browser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"download-engine-write-stream-browser.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/streams/download-engine-write-stream/download-engine-write-stream-browser.ts"],"names":[],"mappings":"AAEA,OAAO,6BAA6B,MAAM,wCAAwC,CAAC;AACnF,OAAO,mBAAmB,MAAM,oCAAoC,CAAC;AACrE,OAAO,oBAAoB,MAAM,qCAAqC,CAAC;AASvE,MAAM,CAAC,OAAO,OAAO,gCAAiC,SAAQ,6BAA6B;IACpE,OAAO,CAA0C;IACpD,OAAO,GAA4C,EAAE,CAAC;IAE5D,OAAO,GAAe,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IACxC,aAAa,GAAG,CAAC,CAAC;IAE5B,IAAW,YAAY;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;IAC9F,CAAC;IAED,YAAmB,OAAgD,EAAE,UAAmD,EAAE;QACtH,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAES,aAAa,CAAC,MAAc;QAClC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,OAAO,CAAC;QACxB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,oBAAoB,CAAC,+DAA+D,CAAC,CAAC;QACpG,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAC1C,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5B,OAAO,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;IACpC,CAAC;IAEM,KAAK,CAAC,MAAc,EAAE,MAAkB;QAC3C,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;iBACzC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACzB,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,UAAU,CAAC;YACxC,OAAO;QACX,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAEM,eAAe;QAClB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACtC,OAAO,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAEM,YAAY;QACf,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;CACJ"}

View File

@@ -0,0 +1,22 @@
import retry from "async-retry";
import BaseDownloadEngineWriteStream from "./base-download-engine-write-stream.js";
export type DownloadEngineWriteStreamOptionsNodeJS = {
retry?: retry.Options;
mode: string;
};
export default class DownloadEngineWriteStreamNodejs extends BaseDownloadEngineWriteStream {
path: string;
finalPath: string;
private _fd;
private _fileWriteFinished;
readonly options: DownloadEngineWriteStreamOptionsNodeJS;
fileSize: number;
constructor(path: string, finalPath: string, options?: Partial<DownloadEngineWriteStreamOptionsNodeJS>);
private _ensureFileOpen;
write(cursor: number, buffer: Uint8Array): Promise<void>;
ftruncate(size?: number): Promise<void>;
saveMedataAfterFile(data: any): Promise<void>;
loadMetadataAfterFileWithoutRetry(): Promise<any>;
private _writeWithoutRetry;
close(): Promise<void>;
}

View File

@@ -0,0 +1,104 @@
import fs from "fs/promises";
import fsExtra from "fs-extra";
import retry from "async-retry";
import { withLock } from "lifecycle-utils";
import BaseDownloadEngineWriteStream from "./base-download-engine-write-stream.js";
import WriterIsClosedError from "./errors/writer-is-closed-error.js";
const DEFAULT_OPTIONS = {
mode: "r+"
};
const NOT_ENOUGH_SPACE_ERROR_CODE = "ENOSPC";
export default class DownloadEngineWriteStreamNodejs extends BaseDownloadEngineWriteStream {
path;
finalPath;
_fd = null;
_fileWriteFinished = false;
options;
fileSize = 0;
constructor(path, finalPath, options = {}) {
super();
this.path = path;
this.finalPath = finalPath;
this.options = { ...DEFAULT_OPTIONS, ...options };
}
async _ensureFileOpen() {
return await withLock(this, "_lock", async () => {
if (this._fd) {
return this._fd;
}
return await retry(async () => {
await fsExtra.ensureFile(this.path);
return this._fd = await fs.open(this.path, this.options.mode);
}, this.options.retry);
});
}
async write(cursor, buffer) {
let throwError = false;
await retry(async () => {
try {
return await this._writeWithoutRetry(cursor, buffer);
}
catch (error) {
if (error?.code === NOT_ENOUGH_SPACE_ERROR_CODE) {
throwError = error;
return;
}
throw error;
}
}, this.options.retry);
if (throwError) {
throw throwError;
}
}
async ftruncate(size = this.fileSize) {
this._fileWriteFinished = true;
await retry(async () => {
const fd = await this._ensureFileOpen();
await fd.truncate(size);
}, this.options.retry);
}
async saveMedataAfterFile(data) {
if (this._fileWriteFinished) {
throw new WriterIsClosedError();
}
const jsonString = JSON.stringify(data);
const encoder = new TextEncoder();
const uint8Array = encoder.encode(jsonString);
await this.write(this.fileSize, uint8Array);
}
async loadMetadataAfterFileWithoutRetry() {
if (!await fsExtra.pathExists(this.path)) {
return;
}
const fd = await this._ensureFileOpen();
try {
const state = await fd.stat();
const metadataSize = state.size - this.fileSize;
if (metadataSize <= 0) {
return;
}
const metadataBuffer = Buffer.alloc(metadataSize);
await fd.read(metadataBuffer, 0, metadataSize, this.fileSize);
const decoder = new TextDecoder();
const metadataString = decoder.decode(metadataBuffer);
try {
return JSON.parse(metadataString);
}
catch { }
}
finally {
this._fd = null;
await fd.close();
}
}
async _writeWithoutRetry(cursor, buffer) {
const fd = await this._ensureFileOpen();
const { bytesWritten } = await fd.write(buffer, 0, buffer.length, cursor);
return bytesWritten;
}
async close() {
await this._fd?.close();
this._fd = null;
}
}
//# sourceMappingURL=download-engine-write-stream-nodejs.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"download-engine-write-stream-nodejs.js","sourceRoot":"","sources":["../../../../../src/download/download-engine/streams/download-engine-write-stream/download-engine-write-stream-nodejs.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,4 @@
import IpullError from "../../../../../errors/ipull-error.js";
export default class WriterError extends IpullError {
constructor(message?: string);
}

View File

@@ -0,0 +1,7 @@
import IpullError from "../../../../../errors/ipull-error.js";
export default class WriterError extends IpullError {
constructor(message = "Writer error") {
super(message);
}
}
//# sourceMappingURL=writer-error.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"writer-error.js","sourceRoot":"","sources":["../../../../../../src/download/download-engine/streams/download-engine-write-stream/errors/writer-error.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,sCAAsC,CAAC;AAE9D,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,UAAU;IAC/C,YAAY,OAAO,GAAG,cAAc;QAChC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;CACJ"}

View File

@@ -0,0 +1,4 @@
import WriterError from "./writer-error.js";
export default class WriterIsClosedError extends WriterError {
constructor(message?: string);
}

View File

@@ -0,0 +1,7 @@
import WriterError from "./writer-error.js";
export default class WriterIsClosedError extends WriterError {
constructor(message = "Writer is closed") {
super(message);
}
}
//# sourceMappingURL=writer-is-closed-error.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"writer-is-closed-error.js","sourceRoot":"","sources":["../../../../../../src/download/download-engine/streams/download-engine-write-stream/errors/writer-is-closed-error.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,WAAW;IACxD,YAAY,OAAO,GAAG,kBAAkB;QACpC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;CACJ"}

View File

@@ -0,0 +1,4 @@
import WriterError from "./writer-error.js";
export default class WriterNotDefineError extends WriterError {
constructor(message?: string);
}

View File

@@ -0,0 +1,7 @@
import WriterError from "./writer-error.js";
export default class WriterNotDefineError extends WriterError {
constructor(message = "Writer is not defined") {
super(message);
}
}
//# sourceMappingURL=writer-not-define-error.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"writer-not-define-error.js","sourceRoot":"","sources":["../../../../../../src/download/download-engine/streams/download-engine-write-stream/errors/writer-not-define-error.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,WAAW;IACzD,YAAY,OAAO,GAAG,uBAAuB;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;CACJ"}