* Serializes this instance into the provided serializer context. * @param {DeserializedType} data data * @param {Context} context context object * @returns {SerializedType | Promise<SerializedType> | null} serialized data
(data, context)
| 462 | * @returns {SerializedType | Promise<SerializedType> | null} serialized data |
| 463 | */ |
| 464 | serialize(data, context) { |
| 465 | const { filename, extension = "" } = context; |
| 466 | return new Promise((resolve, reject) => { |
| 467 | mkdirp(this.fs, dirname(this.fs, filename), (err) => { |
| 468 | if (err) return reject(err); |
| 469 | |
| 470 | // It's important that we don't touch existing files during serialization |
| 471 | // because serialize may read existing files (when deserializing) |
| 472 | /** @type {Set<string>} */ |
| 473 | const allWrittenFiles = new Set(); |
| 474 | /** |
| 475 | * Processes the provided name. |
| 476 | * @param {string | false} name name |
| 477 | * @param {Buffer[]} content content |
| 478 | * @param {number} size size |
| 479 | * @returns {Promise<void>} |
| 480 | */ |
| 481 | const writeFile = async (name, content, size) => { |
| 482 | const file = name |
| 483 | ? join(this.fs, filename, `../${name}${extension}`) |
| 484 | : filename; |
| 485 | await new Promise( |
| 486 | /** |
| 487 | * Handles the callback logic for this hook. |
| 488 | * @param {(value?: undefined) => void} resolve resolve |
| 489 | * @param {(reason?: Error | null) => void} reject reject |
| 490 | */ |
| 491 | (resolve, reject) => { |
| 492 | let stream = this.fs.createWriteStream(`${file}_`); |
| 493 | /** @type {undefined | import("zlib").Gzip | import("zlib").BrotliCompress} */ |
| 494 | let compression; |
| 495 | if (file.endsWith(".gz")) { |
| 496 | compression = createGzip({ |
| 497 | chunkSize: COMPRESSION_CHUNK_SIZE, |
| 498 | level: zConstants.Z_BEST_SPEED |
| 499 | }); |
| 500 | } else if (file.endsWith(".br")) { |
| 501 | compression = createBrotliCompress({ |
| 502 | chunkSize: COMPRESSION_CHUNK_SIZE, |
| 503 | params: { |
| 504 | [zConstants.BROTLI_PARAM_MODE]: zConstants.BROTLI_MODE_TEXT, |
| 505 | [zConstants.BROTLI_PARAM_QUALITY]: 2, |
| 506 | [zConstants.BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING]: true, |
| 507 | [zConstants.BROTLI_PARAM_SIZE_HINT]: size |
| 508 | } |
| 509 | }); |
| 510 | } |
| 511 | if (compression) { |
| 512 | pipeline(compression, stream, reject); |
| 513 | stream = compression; |
| 514 | stream.on("finish", () => resolve()); |
| 515 | } else { |
| 516 | stream.on("error", (err) => reject(err)); |
| 517 | stream.on("finish", () => resolve()); |
| 518 | } |
| 519 | // split into chunks for WRITE_LIMIT_CHUNK size |
| 520 | /** @type {Buffer[]} */ |
| 521 | const chunks = []; |