electron-updater 6.7.3 → 6.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  import { Writable } from "stream";
2
2
  import { Operation } from "./downloadPlanBuilder";
3
+ import { ProgressInfo } from "./ProgressDifferentialDownloadCallbackTransform";
3
4
  export interface PartListDataTask {
4
5
  readonly oldFileFd: number;
5
6
  readonly tasks: Array<Operation>;
@@ -13,13 +14,19 @@ export declare class DataSplitter extends Writable {
13
14
  private readonly partIndexToTaskIndex;
14
15
  private readonly partIndexToLength;
15
16
  private readonly finishHandler;
17
+ private readonly grandTotalBytes;
18
+ private readonly onProgress?;
19
+ private start;
20
+ private nextUpdate;
21
+ private transferred;
22
+ private delta;
16
23
  partIndex: number;
17
24
  private headerListBuffer;
18
25
  private readState;
19
26
  private ignoreByteCount;
20
27
  private remainingPartDataCount;
21
28
  private readonly boundaryLength;
22
- constructor(out: Writable, options: PartListDataTask, partIndexToTaskIndex: Map<number, number>, boundary: string, partIndexToLength: Array<number>, finishHandler: () => any);
29
+ constructor(out: Writable, options: PartListDataTask, partIndexToTaskIndex: Map<number, number>, boundary: string, partIndexToLength: Array<number>, finishHandler: () => any, grandTotalBytes: number, onProgress?: ((info: ProgressInfo) => any) | undefined);
23
30
  get isFinished(): boolean;
24
31
  _write(data: Buffer, encoding: string, callback: (error?: Error) => void): void;
25
32
  private handleData;
@@ -28,13 +28,20 @@ function copyData(task, out, oldFileFd, reject, resolve) {
28
28
  });
29
29
  }
30
30
  class DataSplitter extends stream_1.Writable {
31
- constructor(out, options, partIndexToTaskIndex, boundary, partIndexToLength, finishHandler) {
31
+ constructor(out, options, partIndexToTaskIndex, boundary, partIndexToLength, finishHandler, grandTotalBytes, onProgress) {
32
32
  super();
33
33
  this.out = out;
34
34
  this.options = options;
35
35
  this.partIndexToTaskIndex = partIndexToTaskIndex;
36
36
  this.partIndexToLength = partIndexToLength;
37
37
  this.finishHandler = finishHandler;
38
+ this.grandTotalBytes = grandTotalBytes;
39
+ this.onProgress = onProgress;
40
+ // properties for progress update calculations
41
+ this.start = Date.now(); // download start time used to calculate average rate
42
+ this.nextUpdate = this.start + 1000; // timestamp of next update to prevent updates more often than once per second
43
+ this.transferred = 0; // total number of bytes transferred
44
+ this.delta = 0; // number of bytes transferred since last update, reset after each update
38
45
  this.partIndex = -1;
39
46
  this.headerListBuffer = null;
40
47
  this.readState = ReadState.INIT;
@@ -54,7 +61,25 @@ class DataSplitter extends stream_1.Writable {
54
61
  console.error(`Trailing ignored data: ${data.length} bytes`);
55
62
  return;
56
63
  }
57
- this.handleData(data).then(callback).catch(callback);
64
+ this.handleData(data)
65
+ .then(() => {
66
+ if (this.onProgress) {
67
+ const now = Date.now();
68
+ if ((now >= this.nextUpdate || this.transferred === this.grandTotalBytes) && this.grandTotalBytes && (now - this.start) / 1000) {
69
+ this.nextUpdate = now + 1000;
70
+ this.onProgress({
71
+ total: this.grandTotalBytes,
72
+ delta: this.delta,
73
+ transferred: this.transferred,
74
+ percent: (this.transferred / this.grandTotalBytes) * 100,
75
+ bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),
76
+ });
77
+ this.delta = 0;
78
+ }
79
+ }
80
+ callback();
81
+ })
82
+ .catch(callback);
58
83
  }
59
84
  async handleData(chunk) {
60
85
  let start = 0;
@@ -183,6 +208,8 @@ class DataSplitter extends stream_1.Writable {
183
208
  }
184
209
  processPartData(data, start, end) {
185
210
  this.actualPartLength += end - start;
211
+ this.transferred += end - start;
212
+ this.delta += end - start;
186
213
  const out = this.out;
187
214
  if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {
188
215
  return Promise.resolve();
@@ -1 +1 @@
1
- {"version":3,"file":"DataSplitter.js","sourceRoot":"","sources":["../../src/differentialDownloader/DataSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["import { newError } from \"builder-util-runtime\"\nimport { createReadStream } from \"fs\"\nimport { Writable } from \"stream\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nconst DOUBLE_CRLF = Buffer.from(\"\\r\\n\\r\\n\")\n\nenum ReadState {\n INIT,\n HEADER,\n BODY,\n}\n\nexport interface PartListDataTask {\n readonly oldFileFd: number\n readonly tasks: Array<Operation>\n readonly start: number\n readonly end: number\n}\n\nexport function copyData(task: Operation, out: Writable, oldFileFd: number, reject: (error: Error) => void, resolve: () => void): void {\n const readStream = createReadStream(\"\", {\n fd: oldFileFd,\n autoClose: false,\n start: task.start,\n // end is inclusive\n end: task.end - 1,\n })\n readStream.on(\"error\", reject)\n readStream.once(\"end\", resolve)\n readStream.pipe(out, {\n end: false,\n })\n}\n\nexport class DataSplitter extends Writable {\n partIndex = -1\n\n private headerListBuffer: Buffer | null = null\n private readState = ReadState.INIT\n private ignoreByteCount = 0\n private remainingPartDataCount = 0\n\n private readonly boundaryLength: number\n\n constructor(\n private readonly out: Writable,\n private readonly options: PartListDataTask,\n private readonly partIndexToTaskIndex: Map<number, number>,\n boundary: string,\n private readonly partIndexToLength: Array<number>,\n private readonly finishHandler: () => any\n ) {\n super()\n\n this.boundaryLength = boundary.length + 4 /* size of \\r\\n-- */\n // first chunk doesn't start with \\r\\n\n this.ignoreByteCount = this.boundaryLength - 2\n }\n\n get isFinished(): boolean {\n return this.partIndex === this.partIndexToLength.length\n }\n\n // noinspection JSUnusedGlobalSymbols\n _write(data: Buffer, encoding: string, callback: (error?: Error) => void): void {\n if (this.isFinished) {\n console.error(`Trailing ignored data: ${data.length} bytes`)\n return\n }\n\n this.handleData(data).then(callback).catch(callback)\n }\n\n private async handleData(chunk: Buffer): Promise<undefined> {\n let start = 0\n\n if (this.ignoreByteCount !== 0 && this.remainingPartDataCount !== 0) {\n throw newError(\"Internal error\", \"ERR_DATA_SPLITTER_BYTE_COUNT_MISMATCH\")\n }\n\n if (this.ignoreByteCount > 0) {\n const toIgnore = Math.min(this.ignoreByteCount, chunk.length)\n this.ignoreByteCount -= toIgnore\n start = toIgnore\n } else if (this.remainingPartDataCount > 0) {\n const toRead = Math.min(this.remainingPartDataCount, chunk.length)\n this.remainingPartDataCount -= toRead\n await this.processPartData(chunk, 0, toRead)\n start = toRead\n }\n\n if (start === chunk.length) {\n return\n }\n\n if (this.readState === ReadState.HEADER) {\n const headerListEnd = this.searchHeaderListEnd(chunk, start)\n if (headerListEnd === -1) {\n return\n }\n\n start = headerListEnd\n this.readState = ReadState.BODY\n // header list is ignored, we don't need it\n this.headerListBuffer = null\n }\n\n while (true) {\n if (this.readState === ReadState.BODY) {\n this.readState = ReadState.INIT\n } else {\n this.partIndex++\n\n let taskIndex = this.partIndexToTaskIndex.get(this.partIndex)\n if (taskIndex == null) {\n if (this.isFinished) {\n taskIndex = this.options.end\n } else {\n throw newError(\"taskIndex is null\", \"ERR_DATA_SPLITTER_TASK_INDEX_IS_NULL\")\n }\n }\n\n const prevTaskIndex = this.partIndex === 0 ? this.options.start : this.partIndexToTaskIndex.get(this.partIndex - 1)! + 1 /* prev part is download, next maybe copy */\n if (prevTaskIndex < taskIndex) {\n await this.copyExistingData(prevTaskIndex, taskIndex)\n } else if (prevTaskIndex > taskIndex) {\n throw newError(\"prevTaskIndex must be < taskIndex\", \"ERR_DATA_SPLITTER_TASK_INDEX_ASSERT_FAILED\")\n }\n\n if (this.isFinished) {\n this.onPartEnd()\n this.finishHandler()\n return\n }\n\n start = this.searchHeaderListEnd(chunk, start)\n\n if (start === -1) {\n this.readState = ReadState.HEADER\n return\n }\n }\n\n const partLength = this.partIndexToLength[this.partIndex]\n const end = start + partLength\n const effectiveEnd = Math.min(end, chunk.length)\n await this.processPartStarted(chunk, start, effectiveEnd)\n this.remainingPartDataCount = partLength - (effectiveEnd - start)\n if (this.remainingPartDataCount > 0) {\n return\n }\n\n start = end + this.boundaryLength\n if (start >= chunk.length) {\n this.ignoreByteCount = this.boundaryLength - (chunk.length - end)\n return\n }\n }\n }\n\n private copyExistingData(index: number, end: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const w = (): void => {\n if (index === end) {\n resolve()\n return\n }\n\n const task = this.options.tasks[index]\n if (task.kind !== OperationKind.COPY) {\n reject(new Error(\"Task kind must be COPY\"))\n return\n }\n\n copyData(task, this.out, this.options.oldFileFd, reject, () => {\n index++\n w()\n })\n }\n w()\n })\n }\n\n private searchHeaderListEnd(chunk: Buffer, readOffset: number): number {\n const headerListEnd = chunk.indexOf(DOUBLE_CRLF, readOffset)\n if (headerListEnd !== -1) {\n return headerListEnd + DOUBLE_CRLF.length\n }\n\n // not all headers data were received, save to buffer\n const partialChunk = readOffset === 0 ? chunk : chunk.slice(readOffset)\n if (this.headerListBuffer == null) {\n this.headerListBuffer = partialChunk\n } else {\n this.headerListBuffer = Buffer.concat([this.headerListBuffer, partialChunk])\n }\n return -1\n }\n\n private actualPartLength = 0\n\n private onPartEnd(): void {\n const expectedLength = this.partIndexToLength[this.partIndex - 1]\n if (this.actualPartLength !== expectedLength) {\n throw newError(`Expected length: ${expectedLength} differs from actual: ${this.actualPartLength}`, \"ERR_DATA_SPLITTER_LENGTH_MISMATCH\")\n }\n this.actualPartLength = 0\n }\n\n private processPartStarted(data: Buffer, start: number, end: number): Promise<void> {\n if (this.partIndex !== 0) {\n this.onPartEnd()\n }\n return this.processPartData(data, start, end)\n }\n\n private processPartData(data: Buffer, start: number, end: number): Promise<void> {\n this.actualPartLength += end - start\n const out = this.out\n if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {\n return Promise.resolve()\n } else {\n return new Promise((resolve, reject) => {\n out.on(\"error\", reject)\n out.once(\"drain\", () => {\n out.removeListener(\"error\", reject)\n resolve()\n })\n })\n }\n }\n}\n"]}
1
+ {"version":3,"file":"DataSplitter.js","sourceRoot":"","sources":["../../src/differentialDownloader/DataSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["import { newError } from \"builder-util-runtime\"\nimport { createReadStream } from \"fs\"\nimport { Writable } from \"stream\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { ProgressInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nconst DOUBLE_CRLF = Buffer.from(\"\\r\\n\\r\\n\")\n\nenum ReadState {\n INIT,\n HEADER,\n BODY,\n}\n\nexport interface PartListDataTask {\n readonly oldFileFd: number\n readonly tasks: Array<Operation>\n readonly start: number\n readonly end: number\n}\n\nexport function copyData(task: Operation, out: Writable, oldFileFd: number, reject: (error: Error) => void, resolve: () => void): void {\n const readStream = createReadStream(\"\", {\n fd: oldFileFd,\n autoClose: false,\n start: task.start,\n // end is inclusive\n end: task.end - 1,\n })\n readStream.on(\"error\", reject)\n readStream.once(\"end\", resolve)\n readStream.pipe(out, {\n end: false,\n })\n}\n\nexport class DataSplitter extends Writable {\n // properties for progress update calculations\n private start = Date.now() // download start time used to calculate average rate\n private nextUpdate = this.start + 1000 // timestamp of next update to prevent updates more often than once per second\n private transferred = 0 // total number of bytes transferred\n private delta = 0 // number of bytes transferred since last update, reset after each update\n\n partIndex = -1\n\n private headerListBuffer: Buffer | null = null\n private readState = ReadState.INIT\n private ignoreByteCount = 0\n private remainingPartDataCount = 0\n\n private readonly boundaryLength: number\n\n constructor(\n private readonly out: Writable,\n private readonly options: PartListDataTask,\n private readonly partIndexToTaskIndex: Map<number, number>,\n boundary: string,\n private readonly partIndexToLength: Array<number>,\n private readonly finishHandler: () => any,\n private readonly grandTotalBytes: number,\n private readonly onProgress?: (info: ProgressInfo) => any\n ) {\n super()\n\n this.boundaryLength = boundary.length + 4 /* size of \\r\\n-- */\n // first chunk doesn't start with \\r\\n\n this.ignoreByteCount = this.boundaryLength - 2\n }\n\n get isFinished(): boolean {\n return this.partIndex === this.partIndexToLength.length\n }\n\n // noinspection JSUnusedGlobalSymbols\n _write(data: Buffer, encoding: string, callback: (error?: Error) => void): void {\n if (this.isFinished) {\n console.error(`Trailing ignored data: ${data.length} bytes`)\n return\n }\n\n this.handleData(data)\n .then(() => {\n if (this.onProgress) {\n const now = Date.now()\n if ((now >= this.nextUpdate || this.transferred === this.grandTotalBytes) && this.grandTotalBytes && (now - this.start) / 1000) {\n this.nextUpdate = now + 1000\n\n this.onProgress({\n total: this.grandTotalBytes,\n delta: this.delta,\n transferred: this.transferred,\n percent: (this.transferred / this.grandTotalBytes) * 100,\n bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),\n })\n this.delta = 0\n }\n }\n\n callback()\n })\n .catch(callback)\n }\n\n private async handleData(chunk: Buffer): Promise<undefined> {\n let start = 0\n\n if (this.ignoreByteCount !== 0 && this.remainingPartDataCount !== 0) {\n throw newError(\"Internal error\", \"ERR_DATA_SPLITTER_BYTE_COUNT_MISMATCH\")\n }\n\n if (this.ignoreByteCount > 0) {\n const toIgnore = Math.min(this.ignoreByteCount, chunk.length)\n this.ignoreByteCount -= toIgnore\n start = toIgnore\n } else if (this.remainingPartDataCount > 0) {\n const toRead = Math.min(this.remainingPartDataCount, chunk.length)\n this.remainingPartDataCount -= toRead\n await this.processPartData(chunk, 0, toRead)\n start = toRead\n }\n\n if (start === chunk.length) {\n return\n }\n\n if (this.readState === ReadState.HEADER) {\n const headerListEnd = this.searchHeaderListEnd(chunk, start)\n if (headerListEnd === -1) {\n return\n }\n\n start = headerListEnd\n this.readState = ReadState.BODY\n // header list is ignored, we don't need it\n this.headerListBuffer = null\n }\n\n while (true) {\n if (this.readState === ReadState.BODY) {\n this.readState = ReadState.INIT\n } else {\n this.partIndex++\n\n let taskIndex = this.partIndexToTaskIndex.get(this.partIndex)\n if (taskIndex == null) {\n if (this.isFinished) {\n taskIndex = this.options.end\n } else {\n throw newError(\"taskIndex is null\", \"ERR_DATA_SPLITTER_TASK_INDEX_IS_NULL\")\n }\n }\n\n const prevTaskIndex = this.partIndex === 0 ? this.options.start : this.partIndexToTaskIndex.get(this.partIndex - 1)! + 1 /* prev part is download, next maybe copy */\n if (prevTaskIndex < taskIndex) {\n await this.copyExistingData(prevTaskIndex, taskIndex)\n } else if (prevTaskIndex > taskIndex) {\n throw newError(\"prevTaskIndex must be < taskIndex\", \"ERR_DATA_SPLITTER_TASK_INDEX_ASSERT_FAILED\")\n }\n\n if (this.isFinished) {\n this.onPartEnd()\n this.finishHandler()\n return\n }\n\n start = this.searchHeaderListEnd(chunk, start)\n\n if (start === -1) {\n this.readState = ReadState.HEADER\n return\n }\n }\n\n const partLength = this.partIndexToLength[this.partIndex]\n const end = start + partLength\n const effectiveEnd = Math.min(end, chunk.length)\n await this.processPartStarted(chunk, start, effectiveEnd)\n this.remainingPartDataCount = partLength - (effectiveEnd - start)\n if (this.remainingPartDataCount > 0) {\n return\n }\n\n start = end + this.boundaryLength\n if (start >= chunk.length) {\n this.ignoreByteCount = this.boundaryLength - (chunk.length - end)\n return\n }\n }\n }\n\n private copyExistingData(index: number, end: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const w = (): void => {\n if (index === end) {\n resolve()\n return\n }\n\n const task = this.options.tasks[index]\n if (task.kind !== OperationKind.COPY) {\n reject(new Error(\"Task kind must be COPY\"))\n return\n }\n\n copyData(task, this.out, this.options.oldFileFd, reject, () => {\n index++\n w()\n })\n }\n w()\n })\n }\n\n private searchHeaderListEnd(chunk: Buffer, readOffset: number): number {\n const headerListEnd = chunk.indexOf(DOUBLE_CRLF, readOffset)\n if (headerListEnd !== -1) {\n return headerListEnd + DOUBLE_CRLF.length\n }\n\n // not all headers data were received, save to buffer\n const partialChunk = readOffset === 0 ? chunk : chunk.slice(readOffset)\n if (this.headerListBuffer == null) {\n this.headerListBuffer = partialChunk\n } else {\n this.headerListBuffer = Buffer.concat([this.headerListBuffer, partialChunk])\n }\n return -1\n }\n\n private actualPartLength = 0\n\n private onPartEnd(): void {\n const expectedLength = this.partIndexToLength[this.partIndex - 1]\n if (this.actualPartLength !== expectedLength) {\n throw newError(`Expected length: ${expectedLength} differs from actual: ${this.actualPartLength}`, \"ERR_DATA_SPLITTER_LENGTH_MISMATCH\")\n }\n this.actualPartLength = 0\n }\n\n private processPartStarted(data: Buffer, start: number, end: number): Promise<void> {\n if (this.partIndex !== 0) {\n this.onPartEnd()\n }\n return this.processPartData(data, start, end)\n }\n\n private processPartData(data: Buffer, start: number, end: number): Promise<void> {\n this.actualPartLength += end - start\n this.transferred += end - start\n this.delta += end - start\n const out = this.out\n if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {\n return Promise.resolve()\n } else {\n return new Promise((resolve, reject) => {\n out.on(\"error\", reject)\n out.once(\"drain\", () => {\n out.removeListener(\"error\", reject)\n resolve()\n })\n })\n }\n }\n}\n"]}
@@ -103,7 +103,6 @@ class DifferentialDownloader {
103
103
  // Create our download info transformer if we have one
104
104
  let downloadInfoTransform = undefined;
105
105
  if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {
106
- // TODO: Does not support multiple ranges (someone feel free to PR this!)
107
106
  const expectedByteCounts = [];
108
107
  let grandTotalBytes = 0;
109
108
  for (const task of tasks) {
@@ -1 +1 @@
1
- {"version":3,"file":"DifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/DifferentialDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from \"builder-util-runtime\"\nimport { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, open } from \"fs-extra\"\nimport { createWriteStream } from \"fs\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { ProgressInfo, CancellationToken } from \"builder-util-runtime\"\nimport { Logger } from \"../types\"\nimport { copyData } from \"./DataSplitter\"\nimport { URL } from \"url\"\nimport { computeOperations, Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from \"./multipleRangeDownloader\"\nimport { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nexport interface DifferentialDownloaderOptions {\n readonly oldFile: string\n readonly newUrl: URL\n readonly logger: Logger\n readonly newFile: string\n\n readonly requestHeaders: OutgoingHttpHeaders | null\n\n readonly isUseMultipleRangeRequest?: boolean\n\n readonly cancellationToken: CancellationToken\n onProgress?: (progress: ProgressInfo) => void\n}\n\nexport abstract class DifferentialDownloader {\n fileMetadataBuffer: Buffer | null = null\n\n private readonly logger: Logger\n\n // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected\n constructor(\n protected readonly blockAwareFileInfo: BlockMapDataHolder,\n readonly httpExecutor: HttpExecutor<any>,\n readonly options: DifferentialDownloaderOptions\n ) {\n this.logger = options.logger\n }\n\n createRequestOptions(): RequestOptions {\n const result = {\n headers: {\n ...this.options.requestHeaders,\n accept: \"*/*\",\n },\n }\n configureRequestUrl(this.options.newUrl, result)\n // user-agent, cache-control and other common options\n configureRequestOptions(result)\n return result\n }\n\n protected doDownload(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it\n if (oldBlockMap.version !== newBlockMap.version) {\n throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`)\n }\n\n const logger = this.logger\n const operations = computeOperations(oldBlockMap, newBlockMap, logger)\n if (logger.debug != null) {\n logger.debug(JSON.stringify(operations, null, 2))\n }\n\n let downloadSize = 0\n let copySize = 0\n for (const operation of operations) {\n const length = operation.end - operation.start\n if (operation.kind === OperationKind.DOWNLOAD) {\n downloadSize += length\n } else {\n copySize += length\n }\n }\n\n const newSize = this.blockAwareFileInfo.size\n if (downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length) !== newSize) {\n throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`)\n }\n\n logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`)\n\n return this.downloadFile(operations)\n }\n\n private downloadFile(tasks: Array<Operation>): Promise<any> {\n const fdList: Array<OpenedFile> = []\n const closeFiles = (): Promise<Array<void>> => {\n return Promise.all(\n fdList.map(openedFile => {\n return close(openedFile.descriptor).catch((e: any) => {\n this.logger.error(`cannot close file \"${openedFile.path}\": ${e}`)\n })\n })\n )\n }\n return this.doDownloadFile(tasks, fdList)\n .then(closeFiles)\n .catch((e: any) => {\n // then must be after catch here (since then always throws error)\n return closeFiles()\n .catch(closeFilesError => {\n // closeFiles never throw error, but just to be sure\n try {\n this.logger.error(`cannot close files: ${closeFilesError}`)\n } catch (errorOnLog) {\n try {\n console.error(errorOnLog)\n } catch (_ignored) {\n // ok, give up and ignore error\n }\n }\n throw e\n })\n .then(() => {\n throw e\n })\n })\n }\n\n private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {\n const oldFileFd = await open(this.options.oldFile, \"r\")\n fdList.push({ descriptor: oldFileFd, path: this.options.oldFile })\n const newFileFd = await open(this.options.newFile, \"w\")\n fdList.push({ descriptor: newFileFd, path: this.options.newFile })\n const fileOut = createWriteStream(this.options.newFile, { fd: newFileFd })\n await new Promise((resolve, reject) => {\n const streams: Array<any> = []\n\n // Create our download info transformer if we have one\n let downloadInfoTransform: ProgressDifferentialDownloadCallbackTransform | undefined = undefined\n if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {\n // TODO: Does not support multiple ranges (someone feel free to PR this!)\n const expectedByteCounts: Array<number> = []\n let grandTotalBytes = 0\n\n for (const task of tasks) {\n if (task.kind === OperationKind.DOWNLOAD) {\n expectedByteCounts.push(task.end - task.start)\n grandTotalBytes += task.end - task.start\n }\n }\n\n const progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo = {\n expectedByteCounts: expectedByteCounts,\n grandTotal: grandTotalBytes,\n }\n\n downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress)\n streams.push(downloadInfoTransform)\n }\n\n const digestTransform = new DigestTransform(this.blockAwareFileInfo.sha512)\n // to simply debug, do manual validation to allow file to be fully written\n digestTransform.isValidateOnEnd = false\n streams.push(digestTransform)\n\n // noinspection JSArrowFunctionCanBeReplacedWithShorthand\n fileOut.on(\"finish\", () => {\n ;(fileOut.close as any)(() => {\n // remove from fd list because closed successfully\n fdList.splice(1, 1)\n try {\n digestTransform.validate()\n } catch (e: any) {\n reject(e)\n return\n }\n\n resolve(undefined)\n })\n })\n\n streams.push(fileOut)\n\n let lastStream = null\n for (const stream of streams) {\n stream.on(\"error\", reject)\n if (lastStream == null) {\n lastStream = stream\n } else {\n lastStream = lastStream.pipe(stream)\n }\n }\n\n const firstStream = streams[0]\n\n let w: any\n if (this.options.isUseMultipleRangeRequest) {\n w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)\n w(0)\n return\n }\n\n let downloadOperationCount = 0\n let actualUrl: string | null = null\n this.logger.info(`Differential download: ${this.options.newUrl}`)\n\n const requestOptions = this.createRequestOptions()\n ;(requestOptions as any).redirect = \"manual\"\n\n w = (index: number): void => {\n if (index >= tasks.length) {\n if (this.fileMetadataBuffer != null) {\n firstStream.write(this.fileMetadataBuffer)\n }\n firstStream.end()\n return\n }\n\n const operation = tasks[index++]\n if (operation.kind === OperationKind.COPY) {\n // We are copying, let's not send status updates to the UI\n if (downloadInfoTransform) {\n downloadInfoTransform.beginFileCopy()\n }\n\n copyData(operation, firstStream, oldFileFd, reject, () => w(index))\n return\n }\n\n const range = `bytes=${operation.start}-${operation.end - 1}`\n requestOptions.headers!.range = range\n\n this.logger?.debug?.(`download range: ${range}`)\n\n // We are starting to download\n if (downloadInfoTransform) {\n downloadInfoTransform.beginRangeDownload()\n }\n\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n response.on(\"error\", reject)\n response.on(\"aborted\", () => {\n reject(new Error(\"response has been aborted by the server\"))\n })\n // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n if (response.statusCode >= 400) {\n reject(createHttpError(response))\n }\n\n response.pipe(firstStream, {\n end: false,\n })\n response.once(\"end\", () => {\n // Pass on that we are downloading a segment\n if (downloadInfoTransform) {\n downloadInfoTransform.endRangeDownload()\n }\n\n if (++downloadOperationCount === 100) {\n downloadOperationCount = 0\n setTimeout(() => w(index), 1000)\n } else {\n w(index)\n }\n })\n })\n request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`)\n actualUrl = redirectUrl\n configureRequestUrl(new URL(actualUrl), requestOptions)\n request.followRedirect()\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n }\n\n w(0)\n })\n }\n\n protected async readRemoteBytes(start: number, endInclusive: number): Promise<Buffer> {\n const buffer = Buffer.allocUnsafe(endInclusive + 1 - start)\n const requestOptions = this.createRequestOptions()\n requestOptions.headers!.range = `bytes=${start}-${endInclusive}`\n let position = 0\n await this.request(requestOptions, chunk => {\n chunk.copy(buffer, position)\n position += chunk.length\n })\n\n if (position !== buffer.length) {\n throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`)\n }\n return buffer\n }\n\n private request(requestOptions: RequestOptions, dataHandler: (chunk: Buffer) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n response.on(\"error\", reject)\n response.on(\"aborted\", () => {\n reject(new Error(\"response has been aborted by the server\"))\n })\n\n response.on(\"data\", dataHandler)\n response.on(\"end\", () => resolve())\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n })\n }\n}\n\nfunction formatBytes(value: number, symbol = \" KB\"): string {\n return new Intl.NumberFormat(\"en\").format((value / 1024).toFixed(2) as any) + symbol\n}\n\n// safety\nfunction removeQuery(url: string): string {\n const index = url.indexOf(\"?\")\n return index < 0 ? url : url.substring(0, index)\n}\n\ninterface OpenedFile {\n readonly descriptor: number\n readonly path: string\n}\n"]}
1
+ {"version":3,"file":"DifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/DifferentialDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from \"builder-util-runtime\"\nimport { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, open } from \"fs-extra\"\nimport { createWriteStream } from \"fs\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { ProgressInfo, CancellationToken } from \"builder-util-runtime\"\nimport { Logger } from \"../types\"\nimport { copyData } from \"./DataSplitter\"\nimport { URL } from \"url\"\nimport { computeOperations, Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from \"./multipleRangeDownloader\"\nimport { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nexport interface DifferentialDownloaderOptions {\n readonly oldFile: string\n readonly newUrl: URL\n readonly logger: Logger\n readonly newFile: string\n\n readonly requestHeaders: OutgoingHttpHeaders | null\n\n readonly isUseMultipleRangeRequest?: boolean\n\n readonly cancellationToken: CancellationToken\n onProgress?: (progress: ProgressInfo) => void\n}\n\nexport abstract class DifferentialDownloader {\n fileMetadataBuffer: Buffer | null = null\n\n private readonly logger: Logger\n\n // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected\n constructor(\n protected readonly blockAwareFileInfo: BlockMapDataHolder,\n readonly httpExecutor: HttpExecutor<any>,\n readonly options: DifferentialDownloaderOptions\n ) {\n this.logger = options.logger\n }\n\n createRequestOptions(): RequestOptions {\n const result = {\n headers: {\n ...this.options.requestHeaders,\n accept: \"*/*\",\n },\n }\n configureRequestUrl(this.options.newUrl, result)\n // user-agent, cache-control and other common options\n configureRequestOptions(result)\n return result\n }\n\n protected doDownload(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it\n if (oldBlockMap.version !== newBlockMap.version) {\n throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`)\n }\n\n const logger = this.logger\n const operations = computeOperations(oldBlockMap, newBlockMap, logger)\n if (logger.debug != null) {\n logger.debug(JSON.stringify(operations, null, 2))\n }\n\n let downloadSize = 0\n let copySize = 0\n for (const operation of operations) {\n const length = operation.end - operation.start\n if (operation.kind === OperationKind.DOWNLOAD) {\n downloadSize += length\n } else {\n copySize += length\n }\n }\n\n const newSize = this.blockAwareFileInfo.size\n if (downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length) !== newSize) {\n throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`)\n }\n\n logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`)\n\n return this.downloadFile(operations)\n }\n\n private downloadFile(tasks: Array<Operation>): Promise<any> {\n const fdList: Array<OpenedFile> = []\n const closeFiles = (): Promise<Array<void>> => {\n return Promise.all(\n fdList.map(openedFile => {\n return close(openedFile.descriptor).catch((e: any) => {\n this.logger.error(`cannot close file \"${openedFile.path}\": ${e}`)\n })\n })\n )\n }\n return this.doDownloadFile(tasks, fdList)\n .then(closeFiles)\n .catch((e: any) => {\n // then must be after catch here (since then always throws error)\n return closeFiles()\n .catch(closeFilesError => {\n // closeFiles never throw error, but just to be sure\n try {\n this.logger.error(`cannot close files: ${closeFilesError}`)\n } catch (errorOnLog) {\n try {\n console.error(errorOnLog)\n } catch (_ignored) {\n // ok, give up and ignore error\n }\n }\n throw e\n })\n .then(() => {\n throw e\n })\n })\n }\n\n private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {\n const oldFileFd = await open(this.options.oldFile, \"r\")\n fdList.push({ descriptor: oldFileFd, path: this.options.oldFile })\n const newFileFd = await open(this.options.newFile, \"w\")\n fdList.push({ descriptor: newFileFd, path: this.options.newFile })\n const fileOut = createWriteStream(this.options.newFile, { fd: newFileFd })\n await new Promise((resolve, reject) => {\n const streams: Array<any> = []\n\n // Create our download info transformer if we have one\n let downloadInfoTransform: ProgressDifferentialDownloadCallbackTransform | undefined = undefined\n if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {\n const expectedByteCounts: Array<number> = []\n let grandTotalBytes = 0\n\n for (const task of tasks) {\n if (task.kind === OperationKind.DOWNLOAD) {\n expectedByteCounts.push(task.end - task.start)\n grandTotalBytes += task.end - task.start\n }\n }\n\n const progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo = {\n expectedByteCounts: expectedByteCounts,\n grandTotal: grandTotalBytes,\n }\n\n downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress)\n streams.push(downloadInfoTransform)\n }\n\n const digestTransform = new DigestTransform(this.blockAwareFileInfo.sha512)\n // to simply debug, do manual validation to allow file to be fully written\n digestTransform.isValidateOnEnd = false\n streams.push(digestTransform)\n\n // noinspection JSArrowFunctionCanBeReplacedWithShorthand\n fileOut.on(\"finish\", () => {\n ;(fileOut.close as any)(() => {\n // remove from fd list because closed successfully\n fdList.splice(1, 1)\n try {\n digestTransform.validate()\n } catch (e: any) {\n reject(e)\n return\n }\n\n resolve(undefined)\n })\n })\n\n streams.push(fileOut)\n\n let lastStream = null\n for (const stream of streams) {\n stream.on(\"error\", reject)\n if (lastStream == null) {\n lastStream = stream\n } else {\n lastStream = lastStream.pipe(stream)\n }\n }\n\n const firstStream = streams[0]\n\n let w: any\n if (this.options.isUseMultipleRangeRequest) {\n w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)\n w(0)\n return\n }\n\n let downloadOperationCount = 0\n let actualUrl: string | null = null\n this.logger.info(`Differential download: ${this.options.newUrl}`)\n\n const requestOptions = this.createRequestOptions()\n ;(requestOptions as any).redirect = \"manual\"\n\n w = (index: number): void => {\n if (index >= tasks.length) {\n if (this.fileMetadataBuffer != null) {\n firstStream.write(this.fileMetadataBuffer)\n }\n firstStream.end()\n return\n }\n\n const operation = tasks[index++]\n if (operation.kind === OperationKind.COPY) {\n // We are copying, let's not send status updates to the UI\n if (downloadInfoTransform) {\n downloadInfoTransform.beginFileCopy()\n }\n\n copyData(operation, firstStream, oldFileFd, reject, () => w(index))\n return\n }\n\n const range = `bytes=${operation.start}-${operation.end - 1}`\n requestOptions.headers!.range = range\n\n this.logger?.debug?.(`download range: ${range}`)\n\n // We are starting to download\n if (downloadInfoTransform) {\n downloadInfoTransform.beginRangeDownload()\n }\n\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n response.on(\"error\", reject)\n response.on(\"aborted\", () => {\n reject(new Error(\"response has been aborted by the server\"))\n })\n // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n if (response.statusCode >= 400) {\n reject(createHttpError(response))\n }\n\n response.pipe(firstStream, {\n end: false,\n })\n response.once(\"end\", () => {\n // Pass on that we are downloading a segment\n if (downloadInfoTransform) {\n downloadInfoTransform.endRangeDownload()\n }\n\n if (++downloadOperationCount === 100) {\n downloadOperationCount = 0\n setTimeout(() => w(index), 1000)\n } else {\n w(index)\n }\n })\n })\n request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`)\n actualUrl = redirectUrl\n configureRequestUrl(new URL(actualUrl), requestOptions)\n request.followRedirect()\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n }\n\n w(0)\n })\n }\n\n protected async readRemoteBytes(start: number, endInclusive: number): Promise<Buffer> {\n const buffer = Buffer.allocUnsafe(endInclusive + 1 - start)\n const requestOptions = this.createRequestOptions()\n requestOptions.headers!.range = `bytes=${start}-${endInclusive}`\n let position = 0\n await this.request(requestOptions, chunk => {\n chunk.copy(buffer, position)\n position += chunk.length\n })\n\n if (position !== buffer.length) {\n throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`)\n }\n return buffer\n }\n\n private request(requestOptions: RequestOptions, dataHandler: (chunk: Buffer) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = this.httpExecutor.createRequest(requestOptions, response => {\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n response.on(\"error\", reject)\n response.on(\"aborted\", () => {\n reject(new Error(\"response has been aborted by the server\"))\n })\n\n response.on(\"data\", dataHandler)\n response.on(\"end\", () => resolve())\n })\n this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n })\n }\n}\n\nfunction formatBytes(value: number, symbol = \" KB\"): string {\n return new Intl.NumberFormat(\"en\").format((value / 1024).toFixed(2) as any) + symbol\n}\n\n// safety\nfunction removeQuery(url: string): string {\n const index = url.indexOf(\"?\")\n return index < 0 ? url : url.substring(0, index)\n}\n\ninterface OpenedFile {\n readonly descriptor: number\n readonly path: string\n}\n"]}
@@ -27,6 +27,7 @@ function executeTasksUsingMultipleRangeRequests(differentialDownloader, tasks, o
27
27
  function doExecuteTasks(differentialDownloader, options, out, resolve, reject) {
28
28
  let ranges = "bytes=";
29
29
  let partCount = 0;
30
+ let grandTotalBytes = 0;
30
31
  const partIndexToTaskIndex = new Map();
31
32
  const partIndexToLength = [];
32
33
  for (let i = options.start; i < options.end; i++) {
@@ -36,6 +37,7 @@ function doExecuteTasks(differentialDownloader, options, out, resolve, reject) {
36
37
  partIndexToTaskIndex.set(partCount, i);
37
38
  partCount++;
38
39
  partIndexToLength.push(task.end - task.start);
40
+ grandTotalBytes += task.end - task.start;
39
41
  }
40
42
  }
41
43
  if (partCount <= 1) {
@@ -81,7 +83,7 @@ function doExecuteTasks(differentialDownloader, options, out, resolve, reject) {
81
83
  reject(new Error(`Content-Type "multipart/byteranges" is expected, but got "${contentType}"`));
82
84
  return;
83
85
  }
84
- const dicer = new DataSplitter_1.DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve);
86
+ const dicer = new DataSplitter_1.DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve, grandTotalBytes, differentialDownloader.options.onProgress);
85
87
  dicer.on("error", reject);
86
88
  response.pipe(dicer);
87
89
  response.on("end", () => {
@@ -1 +1 @@
1
- {"version":3,"file":"multipleRangeDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/multipleRangeDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHttpError, safeGetHeader } from \"builder-util-runtime\"\nimport { IncomingMessage } from \"http\"\nimport { Writable } from \"stream\"\nimport { copyData, DataSplitter, PartListDataTask } from \"./DataSplitter\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nexport function executeTasksUsingMultipleRangeRequests(\n differentialDownloader: DifferentialDownloader,\n tasks: Array<Operation>,\n out: Writable,\n oldFileFd: number,\n reject: (error: Error) => void\n): (taskOffset: number) => void {\n const w = (taskOffset: number): void => {\n if (taskOffset >= tasks.length) {\n if (differentialDownloader.fileMetadataBuffer != null) {\n out.write(differentialDownloader.fileMetadataBuffer)\n }\n out.end()\n return\n }\n\n const nextOffset = taskOffset + 1000\n doExecuteTasks(\n differentialDownloader,\n {\n tasks,\n start: taskOffset,\n end: Math.min(tasks.length, nextOffset),\n oldFileFd,\n },\n out,\n () => w(nextOffset),\n reject\n )\n }\n return w\n}\n\nfunction doExecuteTasks(differentialDownloader: DifferentialDownloader, options: PartListDataTask, out: Writable, resolve: () => void, reject: (error: Error) => void): void {\n let ranges = \"bytes=\"\n let partCount = 0\n const partIndexToTaskIndex = new Map<number, number>()\n const partIndexToLength: Array<number> = []\n for (let i = options.start; i < options.end; i++) {\n const task = options.tasks[i]\n if (task.kind === OperationKind.DOWNLOAD) {\n ranges += `${task.start}-${task.end - 1}, `\n partIndexToTaskIndex.set(partCount, i)\n partCount++\n partIndexToLength.push(task.end - task.start)\n }\n }\n\n if (partCount <= 1) {\n // the only remote range - copy\n const w = (index: number): void => {\n if (index >= options.end) {\n resolve()\n return\n }\n\n const task = options.tasks[index++]\n\n if (task.kind === OperationKind.COPY) {\n copyData(task, out, options.oldFileFd, reject, () => w(index))\n } else {\n const requestOptions = differentialDownloader.createRequestOptions()\n requestOptions.headers!.Range = `bytes=${task.start}-${task.end - 1}`\n const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n response.on(\"error\", reject)\n\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n response.pipe(out, {\n end: false,\n })\n response.once(\"end\", () => w(index))\n })\n differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n }\n }\n\n w(options.start)\n return\n }\n\n const requestOptions = differentialDownloader.createRequestOptions()\n requestOptions.headers!.Range = ranges.substring(0, ranges.length - 2)\n const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n const contentType = safeGetHeader(response, \"content-type\")\n const m = /^multipart\\/.+?\\s*;\\s*boundary=(?:\"([^\"]+)\"|([^\\s\";]+))\\s*$/i.exec(contentType)\n if (m == null) {\n reject(new Error(`Content-Type \"multipart/byteranges\" is expected, but got \"${contentType}\"`))\n return\n }\n\n const dicer = new DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve)\n dicer.on(\"error\", reject)\n response.pipe(dicer)\n\n response.on(\"end\", () => {\n setTimeout(() => {\n request.abort()\n reject(new Error(\"Response ends without calling any handlers\"))\n }, 10000)\n })\n })\n differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n}\n\nexport function checkIsRangesSupported(response: IncomingMessage, reject: (error: Error) => void): boolean {\n // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n if (response.statusCode! >= 400) {\n reject(createHttpError(response))\n return false\n }\n\n if (response.statusCode !== 206) {\n const acceptRanges = safeGetHeader(response, \"accept-ranges\")\n if (acceptRanges == null || acceptRanges === \"none\") {\n reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`))\n return false\n }\n }\n return true\n}\n"]}
1
+ {"version":3,"file":"multipleRangeDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/multipleRangeDownloader.ts"],"names":[],"mappings":";;AAOA,wFA+BC;AAoFD,wDAeC;AAzID,+DAAqE;AAGrE,iDAAyE;AAEzE,+DAAgE;AAEhE,SAAgB,sCAAsC,CACpD,sBAA8C,EAC9C,KAAuB,EACvB,GAAa,EACb,SAAiB,EACjB,MAA8B;IAE9B,MAAM,CAAC,GAAG,CAAC,UAAkB,EAAQ,EAAE;QACrC,IAAI,UAAU,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/B,IAAI,sBAAsB,CAAC,kBAAkB,IAAI,IAAI,EAAE,CAAC;gBACtD,GAAG,CAAC,KAAK,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAA;YACtD,CAAC;YACD,GAAG,CAAC,GAAG,EAAE,CAAA;YACT,OAAM;QACR,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,GAAG,IAAI,CAAA;QACpC,cAAc,CACZ,sBAAsB,EACtB;YACE,KAAK;YACL,KAAK,EAAE,UAAU;YACjB,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;YACvC,SAAS;SACV,EACD,GAAG,EACH,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EACnB,MAAM,CACP,CAAA;IACH,CAAC,CAAA;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,SAAS,cAAc,CAAC,sBAA8C,EAAE,OAAyB,EAAE,GAAa,EAAE,OAAmB,EAAE,MAA8B;IACnK,IAAI,MAAM,GAAG,QAAQ,CAAA;IACrB,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,IAAI,eAAe,GAAG,CAAC,CAAA;IACvB,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAA;IACtD,MAAM,iBAAiB,GAAkB,EAAE,CAAA;IAC3C,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,mCAAa,CAAC,QAAQ,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAA;YAC3C,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;YACtC,SAAS,EAAE,CAAA;YACX,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;YAC7C,eAAe,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,+BAA+B;QAC/B,MAAM,CAAC,GAAG,CAAC,KAAa,EAAQ,EAAE;YAChC,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBACzB,OAAO,EAAE,CAAA;gBACT,OAAM;YACR,CAAC;YAED,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;YAEnC,IAAI,IAAI,CAAC,IAAI,KAAK,mCAAa,CAAC,IAAI,EAAE,CAAC;gBACrC,IAAA,uBAAQ,EAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;YAChE,CAAC;iBAAM,CAAC;gBACN,MAAM,cAAc,GAAG,sBAAsB,CAAC,oBAAoB,EAAE,CAAA;gBACpE,cAAc,CAAC,OAAQ,CAAC,KAAK,GAAG,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAA;gBACrE,MAAM,OAAO,GAAG,sBAAsB,CAAC,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE;oBAC3F,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;oBAE5B,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;wBAC9C,OAAM;oBACR,CAAC;oBAED,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;wBACjB,GAAG,EAAE,KAAK;qBACX,CAAC,CAAA;oBACF,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;gBACtC,CAAC,CAAC,CAAA;gBACF,sBAAsB,CAAC,YAAY,CAAC,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAC/E,OAAO,CAAC,GAAG,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAA;QAED,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB,OAAM;IACR,CAAC;IAED,MAAM,cAAc,GAAG,sBAAsB,CAAC,oBAAoB,EAAE,CAAA;IACpE,cAAc,CAAC,OAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACtE,MAAM,OAAO,GAAG,sBAAsB,CAAC,YAAY,CAAC,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE;QAC3F,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9C,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,IAAA,oCAAa,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QAC3D,MAAM,CAAC,GAAG,8DAA8D,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC1F,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,KAAK,CAAC,6DAA6D,WAAW,GAAG,CAAC,CAAC,CAAA;YAC9F,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,2BAAY,CAAC,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,eAAe,EAAE,sBAAsB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QACxK,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAEpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACtB,UAAU,CAAC,GAAG,EAAE;gBACd,OAAO,CAAC,KAAK,EAAE,CAAA;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC,CAAA;YACjE,CAAC,EAAE,KAAK,CAAC,CAAA;QACX,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,sBAAsB,CAAC,YAAY,CAAC,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC/E,OAAO,CAAC,GAAG,EAAE,CAAA;AACf,CAAC;AAED,SAAgB,sBAAsB,CAAC,QAAyB,EAAE,MAA8B;IAC9F,6HAA6H;IAC7H,IAAI,QAAQ,CAAC,UAAW,IAAI,GAAG,EAAE,CAAC;QAChC,MAAM,CAAC,IAAA,sCAAe,EAAC,QAAQ,CAAC,CAAC,CAAA;QACjC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,IAAA,oCAAa,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAA;QAC7D,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YACpD,MAAM,CAAC,IAAI,KAAK,CAAC,uDAAuD,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;YAChG,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { createHttpError, safeGetHeader } from \"builder-util-runtime\"\nimport { IncomingMessage } from \"http\"\nimport { Writable } from \"stream\"\nimport { copyData, DataSplitter, PartListDataTask } from \"./DataSplitter\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nexport function executeTasksUsingMultipleRangeRequests(\n differentialDownloader: DifferentialDownloader,\n tasks: Array<Operation>,\n out: Writable,\n oldFileFd: number,\n reject: (error: Error) => void\n): (taskOffset: number) => void {\n const w = (taskOffset: number): void => {\n if (taskOffset >= tasks.length) {\n if (differentialDownloader.fileMetadataBuffer != null) {\n out.write(differentialDownloader.fileMetadataBuffer)\n }\n out.end()\n return\n }\n\n const nextOffset = taskOffset + 1000\n doExecuteTasks(\n differentialDownloader,\n {\n tasks,\n start: taskOffset,\n end: Math.min(tasks.length, nextOffset),\n oldFileFd,\n },\n out,\n () => w(nextOffset),\n reject\n )\n }\n return w\n}\n\nfunction doExecuteTasks(differentialDownloader: DifferentialDownloader, options: PartListDataTask, out: Writable, resolve: () => void, reject: (error: Error) => void): void {\n let ranges = \"bytes=\"\n let partCount = 0\n let grandTotalBytes = 0\n const partIndexToTaskIndex = new Map<number, number>()\n const partIndexToLength: Array<number> = []\n for (let i = options.start; i < options.end; i++) {\n const task = options.tasks[i]\n if (task.kind === OperationKind.DOWNLOAD) {\n ranges += `${task.start}-${task.end - 1}, `\n partIndexToTaskIndex.set(partCount, i)\n partCount++\n partIndexToLength.push(task.end - task.start)\n grandTotalBytes += task.end - task.start\n }\n }\n\n if (partCount <= 1) {\n // the only remote range - copy\n const w = (index: number): void => {\n if (index >= options.end) {\n resolve()\n return\n }\n\n const task = options.tasks[index++]\n\n if (task.kind === OperationKind.COPY) {\n copyData(task, out, options.oldFileFd, reject, () => w(index))\n } else {\n const requestOptions = differentialDownloader.createRequestOptions()\n requestOptions.headers!.Range = `bytes=${task.start}-${task.end - 1}`\n const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n response.on(\"error\", reject)\n\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n response.pipe(out, {\n end: false,\n })\n response.once(\"end\", () => w(index))\n })\n differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n }\n }\n\n w(options.start)\n return\n }\n\n const requestOptions = differentialDownloader.createRequestOptions()\n requestOptions.headers!.Range = ranges.substring(0, ranges.length - 2)\n const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n if (!checkIsRangesSupported(response, reject)) {\n return\n }\n\n const contentType = safeGetHeader(response, \"content-type\")\n const m = /^multipart\\/.+?\\s*;\\s*boundary=(?:\"([^\"]+)\"|([^\\s\";]+))\\s*$/i.exec(contentType)\n if (m == null) {\n reject(new Error(`Content-Type \"multipart/byteranges\" is expected, but got \"${contentType}\"`))\n return\n }\n\n const dicer = new DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve, grandTotalBytes, differentialDownloader.options.onProgress)\n dicer.on(\"error\", reject)\n response.pipe(dicer)\n\n response.on(\"end\", () => {\n setTimeout(() => {\n request.abort()\n reject(new Error(\"Response ends without calling any handlers\"))\n }, 10000)\n })\n })\n differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n request.end()\n}\n\nexport function checkIsRangesSupported(response: IncomingMessage, reject: (error: Error) => void): boolean {\n // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n if (response.statusCode! >= 400) {\n reject(createHttpError(response))\n return false\n }\n\n if (response.statusCode !== 206) {\n const acceptRanges = safeGetHeader(response, \"accept-ranges\")\n if (acceptRanges == null || acceptRanges === \"none\") {\n reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`))\n return false\n }\n }\n return true\n}\n"]}
@@ -59,8 +59,9 @@ class GitHubProvider extends BaseGitHubProvider {
59
59
  // noinspection TypeScriptValidateJSTypes
60
60
  const hrefElement = hrefRegExp.exec(element.element("link").attribute("href"));
61
61
  // If this is null then something is wrong and skip this release
62
- if (hrefElement === null)
62
+ if (hrefElement === null) {
63
63
  continue;
64
+ }
64
65
  // This Release's Tag
65
66
  const hrefTag = hrefElement[1];
66
67
  //Get Channel from this release's tag
@@ -1 +1 @@
1
- {"version":3,"file":"GitHubProvider.js","sourceRoot":"","sources":["../../src/providers/GitHubProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GithubOptions, githubUrl, HttpError, newError, parseXml, ReleaseNoteInfo, UpdateInfo, XElement } from \"builder-util-runtime\"\nimport * as semver from \"semver\"\nimport { URL } from \"url\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nconst hrefRegExp = /\\/tag\\/([^/]+)$/\n\ninterface GithubUpdateInfo extends UpdateInfo {\n tag: string\n}\nexport abstract class BaseGitHubProvider<T extends UpdateInfo> extends Provider<T> {\n // so, we don't need to parse port (because node http doesn't support host as url does)\n protected readonly baseUrl: URL\n protected readonly baseApiUrl: URL\n\n protected constructor(\n protected readonly options: GithubOptions,\n defaultHost: string,\n runtimeOptions: ProviderRuntimeOptions\n ) {\n super({\n ...runtimeOptions,\n /* because GitHib uses S3 */\n isUseMultipleRangeRequest: false,\n })\n\n this.baseUrl = newBaseUrl(githubUrl(options, defaultHost))\n const apiHost = defaultHost === \"github.com\" ? \"api.github.com\" : defaultHost\n this.baseApiUrl = newBaseUrl(githubUrl(options, apiHost))\n }\n\n protected computeGithubBasePath(result: string): string {\n // https://github.com/electron-userland/electron-builder/issues/1903#issuecomment-320881211\n const host = this.options.host\n return host && ![\"github.com\", \"api.github.com\"].includes(host) ? `/api/v3${result}` : result\n }\n}\n\nexport class GitHubProvider extends BaseGitHubProvider<GithubUpdateInfo> {\n constructor(\n protected readonly options: GithubOptions,\n private readonly updater: AppUpdater,\n runtimeOptions: ProviderRuntimeOptions\n ) {\n super(options, \"github.com\", runtimeOptions)\n }\n\n private get channel(): string {\n const result = this.updater.channel || this.options.channel\n return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n }\n\n async getLatestVersion(): Promise<GithubUpdateInfo> {\n const cancellationToken = new CancellationToken()\n\n const feedXml: string = (await this.httpRequest(\n newUrlFromBase(`${this.basePath}.atom`, this.baseUrl),\n {\n accept: \"application/xml, application/atom+xml, text/xml, */*\",\n },\n cancellationToken\n ))!\n\n const feed = parseXml(feedXml)\n // noinspection TypeScriptValidateJSTypes\n let latestRelease = feed.element(\"entry\", false, `No published versions on GitHub`)\n let tag: string | null = null\n try {\n if (this.updater.allowPrerelease) {\n const currentChannel = this.updater?.channel || (semver.prerelease(this.updater.currentVersion)?.[0] as string) || null\n\n if (currentChannel === null) {\n // noinspection TypeScriptValidateJSTypes\n tag = hrefRegExp.exec(latestRelease.element(\"link\").attribute(\"href\"))![1]\n } else {\n for (const element of feed.getElements(\"entry\")) {\n // noinspection TypeScriptValidateJSTypes\n const hrefElement = hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))!\n\n // If this is null then something is wrong and skip this release\n if (hrefElement === null) continue\n\n // This Release's Tag\n const hrefTag = hrefElement[1]\n //Get Channel from this release's tag\n const hrefChannel = (semver.prerelease(hrefTag)?.[0] as string) || null\n\n const shouldFetchVersion = !currentChannel || [\"alpha\", \"beta\"].includes(currentChannel)\n const isCustomChannel = hrefChannel !== null && ![\"alpha\", \"beta\"].includes(String(hrefChannel))\n // Allow moving from alpha to beta but not down\n const channelMismatch = currentChannel === \"beta\" && hrefChannel === \"alpha\"\n\n if (shouldFetchVersion && !isCustomChannel && !channelMismatch) {\n tag = hrefTag\n break\n }\n\n const isNextPreRelease = hrefChannel && hrefChannel === currentChannel\n if (isNextPreRelease) {\n tag = hrefTag\n break\n }\n }\n }\n } else {\n tag = await this.getLatestTagName(cancellationToken)\n for (const element of feed.getElements(\"entry\")) {\n // noinspection TypeScriptValidateJSTypes\n if (hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))![1] === tag) {\n latestRelease = element\n break\n }\n }\n }\n } catch (e: any) {\n throw newError(`Cannot parse releases feed: ${e.stack || e.message},\\nXML:\\n${feedXml}`, \"ERR_UPDATER_INVALID_RELEASE_FEED\")\n }\n\n if (tag == null) {\n throw newError(`No published versions on GitHub`, \"ERR_UPDATER_NO_PUBLISHED_VERSIONS\")\n }\n\n let rawData: string\n let channelFile = \"\"\n let channelFileUrl: any = \"\"\n const fetchData = async (channelName: string) => {\n channelFile = getChannelFilename(channelName)\n channelFileUrl = newUrlFromBase(this.getBaseDownloadPath(String(tag), channelFile), this.baseUrl)\n const requestOptions = this.createRequestOptions(channelFileUrl)\n try {\n return (await this.executor.request(requestOptions, cancellationToken))!\n } catch (e: any) {\n if (e instanceof HttpError && e.statusCode === 404) {\n throw newError(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n }\n throw e\n }\n }\n\n try {\n let channel = this.channel\n if (this.updater.allowPrerelease && semver.prerelease(tag)?.[0]) {\n channel = this.getCustomChannelName(String(semver.prerelease(tag)?.[0]))\n }\n rawData = await fetchData(channel)\n } catch (e: any) {\n if (this.updater.allowPrerelease) {\n // Allow fallback to `latest.yml`\n rawData = await fetchData(this.getDefaultChannelName())\n } else {\n throw e\n }\n }\n\n const result = parseUpdateInfo(rawData, channelFile, channelFileUrl)\n if (result.releaseName == null) {\n result.releaseName = latestRelease.elementValueOrEmpty(\"title\")\n }\n\n if (result.releaseNotes == null) {\n result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease)\n }\n return {\n tag: tag,\n ...result,\n }\n }\n\n private async getLatestTagName(cancellationToken: CancellationToken): Promise<string | null> {\n const options = this.options\n // do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise\n const url =\n options.host == null || options.host === \"github.com\"\n ? newUrlFromBase(`${this.basePath}/latest`, this.baseUrl)\n : new URL(`${this.computeGithubBasePath(`/repos/${options.owner}/${options.repo}/releases`)}/latest`, this.baseApiUrl)\n try {\n const rawData = await this.httpRequest(url, { Accept: \"application/json\" }, cancellationToken)\n if (rawData == null) {\n return null\n }\n\n const releaseInfo: GithubReleaseInfo = JSON.parse(rawData)\n return releaseInfo.tag_name\n } catch (e: any) {\n throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n }\n }\n\n private get basePath(): string {\n return `/${this.options.owner}/${this.options.repo}/releases`\n }\n\n resolveFiles(updateInfo: GithubUpdateInfo): Array<ResolvedUpdateFileInfo> {\n // still replace space to - due to backward compatibility\n return resolveFiles(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, \"-\")))\n }\n\n private getBaseDownloadPath(tag: string, fileName: string): string {\n return `${this.basePath}/download/${tag}/${fileName}`\n }\n}\n\ninterface GithubReleaseInfo {\n readonly tag_name: string\n}\n\nfunction getNoteValue(parent: XElement): string {\n const result = parent.elementValueOrEmpty(\"content\")\n // GitHub reports empty notes as <content>No content.</content>\n return result === \"No content.\" ? \"\" : result\n}\n\nexport function computeReleaseNotes(currentVersion: semver.SemVer, isFullChangelog: boolean, feed: XElement, latestRelease: any): string | Array<ReleaseNoteInfo> | null {\n if (!isFullChangelog) {\n return getNoteValue(latestRelease)\n }\n\n const releaseNotes: Array<ReleaseNoteInfo> = []\n for (const release of feed.getElements(\"entry\")) {\n // noinspection TypeScriptValidateJSTypes\n const versionRelease = /\\/tag\\/v?([^/]+)$/.exec(release.element(\"link\").attribute(\"href\"))![1]\n if (semver.lt(currentVersion, versionRelease)) {\n releaseNotes.push({\n version: versionRelease,\n note: getNoteValue(release),\n })\n }\n }\n return releaseNotes.sort((a, b) => semver.rcompare(a.version, b.version))\n}\n"]}
1
+ {"version":3,"file":"GitHubProvider.js","sourceRoot":"","sources":["../../src/providers/GitHubProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GithubOptions, githubUrl, HttpError, newError, parseXml, ReleaseNoteInfo, UpdateInfo, XElement } from \"builder-util-runtime\"\nimport * as semver from \"semver\"\nimport { URL } from \"url\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nconst hrefRegExp = /\\/tag\\/([^/]+)$/\n\ninterface GithubUpdateInfo extends UpdateInfo {\n tag: string\n}\nexport abstract class BaseGitHubProvider<T extends UpdateInfo> extends Provider<T> {\n // so, we don't need to parse port (because node http doesn't support host as url does)\n protected readonly baseUrl: URL\n protected readonly baseApiUrl: URL\n\n protected constructor(\n protected readonly options: GithubOptions,\n defaultHost: string,\n runtimeOptions: ProviderRuntimeOptions\n ) {\n super({\n ...runtimeOptions,\n /* because GitHib uses S3 */\n isUseMultipleRangeRequest: false,\n })\n\n this.baseUrl = newBaseUrl(githubUrl(options, defaultHost))\n const apiHost = defaultHost === \"github.com\" ? \"api.github.com\" : defaultHost\n this.baseApiUrl = newBaseUrl(githubUrl(options, apiHost))\n }\n\n protected computeGithubBasePath(result: string): string {\n // https://github.com/electron-userland/electron-builder/issues/1903#issuecomment-320881211\n const host = this.options.host\n return host && ![\"github.com\", \"api.github.com\"].includes(host) ? `/api/v3${result}` : result\n }\n}\n\nexport class GitHubProvider extends BaseGitHubProvider<GithubUpdateInfo> {\n constructor(\n protected readonly options: GithubOptions,\n private readonly updater: AppUpdater,\n runtimeOptions: ProviderRuntimeOptions\n ) {\n super(options, \"github.com\", runtimeOptions)\n }\n\n private get channel(): string {\n const result = this.updater.channel || this.options.channel\n return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n }\n\n async getLatestVersion(): Promise<GithubUpdateInfo> {\n const cancellationToken = new CancellationToken()\n\n const feedXml: string = (await this.httpRequest(\n newUrlFromBase(`${this.basePath}.atom`, this.baseUrl),\n {\n accept: \"application/xml, application/atom+xml, text/xml, */*\",\n },\n cancellationToken\n ))!\n\n const feed = parseXml(feedXml)\n // noinspection TypeScriptValidateJSTypes\n let latestRelease = feed.element(\"entry\", false, `No published versions on GitHub`)\n let tag: string | null = null\n try {\n if (this.updater.allowPrerelease) {\n const currentChannel = this.updater?.channel || (semver.prerelease(this.updater.currentVersion)?.[0] as string) || null\n\n if (currentChannel === null) {\n // noinspection TypeScriptValidateJSTypes\n tag = hrefRegExp.exec(latestRelease.element(\"link\").attribute(\"href\"))![1]\n } else {\n for (const element of feed.getElements(\"entry\")) {\n // noinspection TypeScriptValidateJSTypes\n const hrefElement = hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))!\n\n // If this is null then something is wrong and skip this release\n if (hrefElement === null) {\n continue\n }\n\n // This Release's Tag\n const hrefTag = hrefElement[1]\n //Get Channel from this release's tag\n const hrefChannel = (semver.prerelease(hrefTag)?.[0] as string) || null\n\n const shouldFetchVersion = !currentChannel || [\"alpha\", \"beta\"].includes(currentChannel)\n const isCustomChannel = hrefChannel !== null && ![\"alpha\", \"beta\"].includes(String(hrefChannel))\n // Allow moving from alpha to beta but not down\n const channelMismatch = currentChannel === \"beta\" && hrefChannel === \"alpha\"\n\n if (shouldFetchVersion && !isCustomChannel && !channelMismatch) {\n tag = hrefTag\n break\n }\n\n const isNextPreRelease = hrefChannel && hrefChannel === currentChannel\n if (isNextPreRelease) {\n tag = hrefTag\n break\n }\n }\n }\n } else {\n tag = await this.getLatestTagName(cancellationToken)\n for (const element of feed.getElements(\"entry\")) {\n // noinspection TypeScriptValidateJSTypes\n if (hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))![1] === tag) {\n latestRelease = element\n break\n }\n }\n }\n } catch (e: any) {\n throw newError(`Cannot parse releases feed: ${e.stack || e.message},\\nXML:\\n${feedXml}`, \"ERR_UPDATER_INVALID_RELEASE_FEED\")\n }\n\n if (tag == null) {\n throw newError(`No published versions on GitHub`, \"ERR_UPDATER_NO_PUBLISHED_VERSIONS\")\n }\n\n let rawData: string\n let channelFile = \"\"\n let channelFileUrl: any = \"\"\n const fetchData = async (channelName: string) => {\n channelFile = getChannelFilename(channelName)\n channelFileUrl = newUrlFromBase(this.getBaseDownloadPath(String(tag), channelFile), this.baseUrl)\n const requestOptions = this.createRequestOptions(channelFileUrl)\n try {\n return (await this.executor.request(requestOptions, cancellationToken))!\n } catch (e: any) {\n if (e instanceof HttpError && e.statusCode === 404) {\n throw newError(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n }\n throw e\n }\n }\n\n try {\n let channel = this.channel\n if (this.updater.allowPrerelease && semver.prerelease(tag)?.[0]) {\n channel = this.getCustomChannelName(String(semver.prerelease(tag)?.[0]))\n }\n rawData = await fetchData(channel)\n } catch (e: any) {\n if (this.updater.allowPrerelease) {\n // Allow fallback to `latest.yml`\n rawData = await fetchData(this.getDefaultChannelName())\n } else {\n throw e\n }\n }\n\n const result = parseUpdateInfo(rawData, channelFile, channelFileUrl)\n if (result.releaseName == null) {\n result.releaseName = latestRelease.elementValueOrEmpty(\"title\")\n }\n\n if (result.releaseNotes == null) {\n result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease)\n }\n return {\n tag: tag,\n ...result,\n }\n }\n\n private async getLatestTagName(cancellationToken: CancellationToken): Promise<string | null> {\n const options = this.options\n // do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise\n const url =\n options.host == null || options.host === \"github.com\"\n ? newUrlFromBase(`${this.basePath}/latest`, this.baseUrl)\n : new URL(`${this.computeGithubBasePath(`/repos/${options.owner}/${options.repo}/releases`)}/latest`, this.baseApiUrl)\n try {\n const rawData = await this.httpRequest(url, { Accept: \"application/json\" }, cancellationToken)\n if (rawData == null) {\n return null\n }\n\n const releaseInfo: GithubReleaseInfo = JSON.parse(rawData)\n return releaseInfo.tag_name\n } catch (e: any) {\n throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n }\n }\n\n private get basePath(): string {\n return `/${this.options.owner}/${this.options.repo}/releases`\n }\n\n resolveFiles(updateInfo: GithubUpdateInfo): Array<ResolvedUpdateFileInfo> {\n // still replace space to - due to backward compatibility\n return resolveFiles(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, \"-\")))\n }\n\n private getBaseDownloadPath(tag: string, fileName: string): string {\n return `${this.basePath}/download/${tag}/${fileName}`\n }\n}\n\ninterface GithubReleaseInfo {\n readonly tag_name: string\n}\n\nfunction getNoteValue(parent: XElement): string {\n const result = parent.elementValueOrEmpty(\"content\")\n // GitHub reports empty notes as <content>No content.</content>\n return result === \"No content.\" ? \"\" : result\n}\n\nexport function computeReleaseNotes(currentVersion: semver.SemVer, isFullChangelog: boolean, feed: XElement, latestRelease: any): string | Array<ReleaseNoteInfo> | null {\n if (!isFullChangelog) {\n return getNoteValue(latestRelease)\n }\n\n const releaseNotes: Array<ReleaseNoteInfo> = []\n for (const release of feed.getElements(\"entry\")) {\n // noinspection TypeScriptValidateJSTypes\n const versionRelease = /\\/tag\\/v?([^/]+)$/.exec(release.element(\"link\").attribute(\"href\"))![1]\n if (semver.lt(currentVersion, versionRelease)) {\n releaseNotes.push({\n version: versionRelease,\n note: getNoteValue(release),\n })\n }\n }\n return releaseNotes.sort((a, b) => semver.rcompare(a.version, b.version))\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-updater",
3
- "version": "6.7.3",
3
+ "version": "6.8.1",
4
4
  "description": "Cross platform updater for electron applications",
5
5
  "main": "out/main.js",
6
6
  "author": "Vladimir Krivosheev",