diff --git a/lib/util/cache/package/file.ts b/lib/util/cache/package/file.ts index 4a6a298437d11707461e6c0ba88a29c6a05506d3..313f97b1a44da83fc6b3b23fe9a9651e91e24f6d 100644 --- a/lib/util/cache/package/file.ts +++ b/lib/util/cache/package/file.ts @@ -2,7 +2,7 @@ import cacache from 'cacache'; import { DateTime } from 'luxon'; import upath from 'upath'; import { logger } from '../../../logger'; -import { compress, decompress } from '../../compress'; +import { compressToBase64, decompressFromBase64 } from '../../compress'; function getKey(namespace: string, key: string): string { return `${namespace}-${key}`; @@ -32,7 +32,7 @@ export async function get<T = never>( if (!cachedValue.compress) { return cachedValue.value; } - const res = await decompress(cachedValue.value); + const res = await decompressFromBase64(cachedValue.value); return JSON.parse(res); } await rm(namespace, key); @@ -58,7 +58,7 @@ export async function set( getKey(namespace, key), JSON.stringify({ compress: true, - value: await compress(JSON.stringify(value)), + value: await compressToBase64(value), expiry: DateTime.local().plus({ minutes: ttlMinutes }), }), ); diff --git a/lib/util/cache/package/redis.ts b/lib/util/cache/package/redis.ts index 408e9263b084c08bc846e16bd8306f8a12aeb260..1914ea3dca5f170bf55350b5fd1195c38995d204 100644 --- a/lib/util/cache/package/redis.ts +++ b/lib/util/cache/package/redis.ts @@ -2,7 +2,7 @@ import { DateTime } from 'luxon'; import { createClient } from 'redis'; import { logger } from '../../../logger'; -import { compress, decompress } from '../../compress'; +import { compressToBase64, decompressFromBase64 } from '../../compress'; let client: ReturnType<typeof createClient> | undefined; let rprefix: string | undefined; @@ -43,7 +43,7 @@ export async function get<T = never>( if (!cachedValue.compress) { return cachedValue.value; } - const res = await decompress(cachedValue.value); + const res = await decompressFromBase64(cachedValue.value); return JSON.parse(res); } // istanbul ignore next @@ -71,7 +71,7 @@ export async function set( getKey(namespace, key), JSON.stringify({ compress: true, - value: await compress(JSON.stringify(value)), + value: await compressToBase64(value), expiry: DateTime.local().plus({ minutes: ttlMinutes }), }), { EX: redisTTL }, diff --git a/lib/util/cache/repository/impl/base.ts b/lib/util/cache/repository/impl/base.ts index e034f46bc756619ee5317f07ed5d10cb0958afb0..0a74accb69e197cce8694a7e018fa67b7b4d171f 100644 --- a/lib/util/cache/repository/impl/base.ts +++ b/lib/util/cache/repository/impl/base.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; import { GlobalConfig } from '../../../../config/global'; import { logger } from '../../../../logger'; -import { compress, decompress } from '../../../compress'; +import { compressToBase64, decompressFromBase64 } from '../../../compress'; import { hash } from '../../../hash'; import { safeStringify } from '../../../stringify'; import { CACHE_REVISION } from '../common'; @@ -41,7 +41,7 @@ export abstract class RepoCacheBase implements RepoCache { logger.debug('Repository cache fingerprint is invalid'); return; } - const jsonStr = await decompress(oldCache.payload); + const jsonStr = await decompressFromBase64(oldCache.payload); this.data = RepoCacheBase.parseData(jsonStr); this.oldHash = oldCache.hash; } @@ -80,7 +80,7 @@ export abstract class RepoCacheBase implements RepoCache { const repository = this.repository; const fingerprint = this.fingerprint; - const payload = await compress(jsonStr); + const payload = await compressToBase64(jsonStr); await this.write({ revision, diff --git a/lib/util/cache/repository/impl/local.spec.ts b/lib/util/cache/repository/impl/local.spec.ts index 3362f4034ad728b76f02a9238f56ac51b3273c53..fb30643011036d2f65cf49d857b553b7e7db3e6f 100644 --- a/lib/util/cache/repository/impl/local.spec.ts +++ b/lib/util/cache/repository/impl/local.spec.ts @@ -1,7 +1,7 @@ import { fs } from '../../../../../test/util'; import { GlobalConfig } from '../../../../config/global'; import { logger } from '../../../../logger'; -import { compress } from '../../../compress'; +import { compressToBase64 } from '../../../compress'; import { hash } from '../../../hash'; import { CACHE_REVISION } from '../common'; import type { RepoCacheRecord } from '../schema'; @@ -21,7 +21,7 @@ async function createCacheRecord( const jsonStr = JSON.stringify(data); const hashedJsonStr = hash(jsonStr); - const payload = await compress(jsonStr); + const payload = await compressToBase64(jsonStr); return { revision, diff --git a/lib/util/compress.spec.ts b/lib/util/compress.spec.ts index f458bfdc0ce3125a5d6b0a92778072a91a02c600..3c05451d83c39cf5394e095b656a5ab9435cd95e 100644 --- a/lib/util/compress.spec.ts +++ b/lib/util/compress.spec.ts @@ -1,13 +1,23 @@ -import { compress, decompress } from './compress'; +import { compressToBase64, decompressFromBase64 } from './compress'; describe('util/compress', () => { - it('works', async () => { + it('compresses strings', async () => { const input = 'foobar'; - const compressed = await compress(input); + const compressed = await compressToBase64(input); expect(compressed).toBe('iwKAZm9vYmFyAw=='); - const decompressed = await decompress(compressed); + const decompressed = await decompressFromBase64(compressed); expect(decompressed).toBe(input); }); + + it('compresses objects', async () => { + const input = { foo: 'bar' }; + + const compressed = await compressToBase64(input); + expect(compressed).toBe('CwaAeyJmb28iOiJiYXIifQM='); + + const decompressed = await decompressFromBase64(compressed); + expect(JSON.parse(decompressed)).toEqual(input); + }); }); diff --git a/lib/util/compress.ts b/lib/util/compress.ts index dd97c1aefbe6bc571d3dc7ae41627bc76409093f..5a06004247b00c329552e658999a238cce6e8af4 100644 --- a/lib/util/compress.ts +++ b/lib/util/compress.ts @@ -1,11 +1,16 @@ import { promisify } from 'node:util'; import zlib, { constants } from 'node:zlib'; +import is from '@sindresorhus/is'; const brotliCompress = promisify(zlib.brotliCompress); const brotliDecompress = promisify(zlib.brotliDecompress); -export async function compress(input: string): Promise<string> { - const buf = await brotliCompress(input, { +/** + * @deprecated + */ +export async function compressToBase64(input: unknown): Promise<string> { + const jsonStr = is.string(input) ? input : JSON.stringify(input); + const buf = await brotliCompress(jsonStr, { params: { [constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_TEXT, [constants.BROTLI_PARAM_QUALITY]: 8, @@ -14,7 +19,10 @@ export async function compress(input: string): Promise<string> { return buf.toString('base64'); } -export async function decompress(input: string): Promise<string> { +/** + * @deprecated + */ +export async function decompressFromBase64(input: string): Promise<string> { const buf = Buffer.from(input, 'base64'); const str = await brotliDecompress(buf); return str.toString('utf8');