@arcane-utils/storage
v1.4.1
Published
Storage helper functions.
Readme
@arcane-utils/storage
Running the tests
The tests hit a real bucket, so they need credentials/adscale_staging_service_account.json to be reachable from this folder.
Use a symlink to keep one version of the credentials:
ln -s ../../credentials arcane-utils/storage/credentials.
npm test runs Jest with NODE_OPTIONS=--experimental-vm-modules. The flag is required,
not optional: @google-cloud/storage 8 depends on teeny-request 11, which reaches the
ESM-only node-fetch 3 through a dynamic import(). Jest's CommonJS runtime cannot execute
that import without the flag, and the suite fails to start with:
TypeError: A dynamic import callback was invoked without --experimental-vm-modulesPointing node-fetch at a CommonJS build with moduleNameMapper does not help, because the
error comes from Node's vm import callback before the specifier is ever resolved. Transforming
teeny-request so TypeScript rewrites its import() into require() does work without the
flag, but it makes the tests exercise node-fetch 2 while production uses 3, which is a poor
trade for an integration suite. Drop the flag once teeny-request stops loading node-fetch
dynamically, or once these tests no longer run under Jest's CommonJS runtime.
CHANGE LOG
v1.4.1
Fix createResumableReadStream splicing two versions of an object overwritten mid-read:
- pins every request, the first one included, to the generation of the metadata the size and crc32c come from. A resume used to read whatever version was live, which surfaced as
Request range not satisfiable(416) when the new version was shorter, or as aCONTENT_DOWNLOAD_MISMATCHafter the whole read - fails with
OBJECT_REPLACEDas soon as that generation is gone (overwritten or deleted, since GCS drops it at once without object versioning), instead of reading on
v1.4.0
Add createResumableReadStream, a drop-in replacement for file.createReadStream() on whole-object reads of large files:
- resumes with a Range request from the last byte received after a transient cut (
Error: aborted, ECONNRESET, 5xx, premature close), which @google-cloud/storage 8 now surfaces instead of hanging - gives up after
maxResumesWithoutProgress(default 5) consecutive failures without a new byte, backing off from 1s up to 32s; any progress resets the count - verifies every byte, resumed ones included, against the object's crc32c with the native
@node-rs/crc32(new dependency). On mismatch the stream errors withCONTENT_DOWNLOAD_MISMATCHinstead of ending, so a pipeline into an upload never finalizes it; an object without crc32c fails withCRC32C_NOT_AVAILABLE - reads stored bytes so offsets and crc32c line up on
contentEncoding: gzipobjects, then gunzips them unlessdecompress: false - closes the in-flight download as soon as the consumer destroys the stream, even while it is stalled
v1.3.2
Point @arcane-utils/error at ^1.1.20 Use caret ranges for @arcane-utils dependencies, so a published patch or minor is picked up without a manual sweep of every package
v1.3.1
Security: bump uuid to 11.1.1 (AIKIDO-2026-10892) Security: bump @google-cloud/storage to 8.1.0, clearing the gaxios, retry-request and teeny-request advisories carried by 7.19.0 Requires node 22, matching the publish workflows Update build/test tooling (typescript 5.9.3, tsup 8.5.1, ts-jest 29.4.12)
v1.3.0
Bump version of google-cloud/storage (Min 7.8.0, current now 7.19.0)
- Allow the fix of stream-shift
v1.2.5
Use commonjs module
v1.2.4
Use unique id on temp files to combine big files
v1.2.3
Use File object (previously path) for output file on concatenateSubFiles
v1.2.2
Stop deleting input files when less than 32 files
v1.2.1
Stop deleting input files in concatenateSubFiles
v1.2.0
Add concatenateSubFiles and deleteFiles functions
v1.1.12
Finally make package functional after many tries
v1.0.1
Expose google package lib.
v1.0.0
Init component.
