diff --git a/CHANGELOG.md b/CHANGELOG.md index db5c848..44ba693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). #### Security +## [2.4.0] - 2023-06-27 +#### Added +- multiple path hashing options (thanks @trevor-vaughan) + + ## [2.3.0] - 2023-05-22 #### Added - `ttl` (time to live) to expire caches (thanks @douglaslinsmeyer) diff --git a/README.md b/README.md index 787bac3..0267ced 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,16 @@ A super-fast, promise-based cache that reads and writes to the file-system. npm install --save file-system-cache +Import + +```ts +import Cache from 'file-system-cache'; + + // or ↑↓ (equivalent) + +import { Cache } from 'file-system-cache'; +``` + ## Usage (API) Create an instance of the cache optionally giving it a folder location to store files within. @@ -17,9 +27,10 @@ Create an instance of the cache optionally giving it a folder location to store import Cache from "file-system-cache"; const cache = Cache({ - basePath: "./.cache", // Optional. Path where cache files are stored (default). - ns: "my-namespace", // Optional. A grouping namespace for items. - ttl: 60 // Optional. A time-to-live for how long the cached item is valid (secs). + basePath: "./.cache", // (optional) Path where cache files are stored (default). + ns: "my-namespace", // (optional) A grouping namespace for items. + hash: "sha1" // (optional) A hashing algorithm used within the cache key. + ttl: 60 // (optional) A time-to-live (in secs) on how long an item remains cached. }); ``` diff --git a/package.json b/package.json index 98f0050..13547e6 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,29 @@ { "name": "file-system-cache", - "version": "2.3.0", + "version": "2.4.0", "description": "A super-fast, promise-based cache that reads and writes to the file-system.", "main": "./lib/index.js", "scripts": { "test": "ts-mocha -p tsconfig.json src/**/*.TEST.ts", "build": "tsc", - "prepublish": "npm test && npm run build" + "prepublish": "npm test && npm run build", + "gen:hashtype": "ts-node-esm -T ./script.ts/generate-hashtype.ts" }, "dependencies": { "fs-extra": "11.1.1", "ramda": "0.29.0" }, "devDependencies": { - "@types/chai": "4.3.4", + "@types/chai": "4.3.5", "@types/expect": "24.3.0", "@types/fs-extra": "11.0.1", "@types/mocha": "10.0.1", - "@types/ramda": "0.29.1", + "@types/ramda": "0.29.2", "chai": "4.3.7", "mocha": "10.2.0", "ts-mocha": "10.0.0", - "typescript": "5.0.4" + "ts-node": "10.9.1", + "typescript": "5.1.3" }, "repository": { "type": "git", diff --git a/script.ts/generate-hashtype.ts b/script.ts/generate-hashtype.ts new file mode 100644 index 0000000..6a55d24 --- /dev/null +++ b/script.ts/generate-hashtype.ts @@ -0,0 +1,45 @@ +#!/usr/bin/env ts-node +import { crypto, fs, fsPath } from '../src/common'; + +const HashUnionType = { + /** + * Generate the union type. + */ + generate() { + const names = crypto.getHashes().map((hash) => `'${hash}'`); + const type = `export type HashAlgorithm = \n | ${names.join('\n | ')};`; + + const nameArray = `[\n ${names.join(',\n ')}];`; + const constants = `export const hashAlgorithms: t.HashAlgorithm[] = ${nameArray}`; + return { type, constants }; + }, + + /** + * Generate and save the type definition file. + */ + update() { + const header = ` +/** + * Generated file - do not edit. + * See: + * - generator: script.ts/generate-hashtype.ts + * - command: yarn run gen:hashtype + */ +` + .substring(1) + .slice(0, -1); + + const { type, constants } = HashUnionType.generate(); + const typeDef = `${header}\n${type}\n`; + const importT = `import { type t } from '../common.t';`; + const constDef = `${header}\n${importT}\n\n${constants}\n`; + + fs.writeFileSync(fsPath.resolve('./src/types.hashes.ts'), typeDef); + fs.writeFileSync(fsPath.resolve('./src/common/const.hashes.ts'), constDef); + }, +}; + +/** + * Run + */ +HashUnionType.update(); diff --git a/src/FileSystemCache.ts b/src/FileSystemCache.ts index ef235e8..937a3b4 100644 --- a/src/FileSystemCache.ts +++ b/src/FileSystemCache.ts @@ -1,21 +1,23 @@ -import { R, fs, Util } from './common'; - -export type FileSystemCacheOptions = { - basePath?: string; - ns?: any; - extension?: string; - ttl?: number; -}; +import { R, Util, fs, hashAlgorithms, type t } from './common'; /** * A cache that read/writes to a specific part of the file-system. */ export class FileSystemCache { - basePath: string; - ns?: any; - extension?: string; + /** + * The list of all available hash algorithms. + */ + static hashAlgorithms: t.HashAlgorithm[] = hashAlgorithms; + + /** + * Instance. + */ + readonly basePath: string; + readonly ns?: any; + readonly extension?: string; + readonly hash: t.HashAlgorithm; + readonly ttl: number; basePathExists?: boolean; - ttl: number; /** * Constructor. @@ -28,15 +30,23 @@ export class FileSystemCache { * - extension: An optional file-extension for paths. * - ttl: The default time-to-live for cached values in seconds. * Default: 0 (never expires) + * - hash: The hashing algorithm to use when generating cache keys. + * Default: "sha1" */ - constructor(options: FileSystemCacheOptions = {}) { + constructor(options: t.FileSystemCacheOptions = {}) { this.basePath = formatPath(options.basePath); - this.ns = Util.hash(options.ns); - this.ttl = typeof options.ttl === 'undefined' ? 0 : options.ttl; + this.hash = options.hash ?? 'sha1'; + this.ns = Util.hash(this.hash, options.ns); + this.ttl = options.ttl ?? 0; if (Util.isString(options.extension)) this.extension = options.extension; + if (Util.isFileSync(this.basePath)) { throw new Error(`The basePath '${this.basePath}' is a file. It should be a folder.`); } + + if (!Util.hashExists(this.hash)) { + throw new Error(`Hash does not exist: ${this.hash}`); + } } /** @@ -45,7 +55,7 @@ export class FileSystemCache { */ public path(key: string): string { if (Util.isNothing(key)) throw new Error(`Path requires a cache key.`); - let name = Util.hash(key); + let name = Util.hash(this.hash, key); if (this.ns) name = `${this.ns}-${name}`; if (this.extension) name = `${name}.${this.extension.replace(/^\./, '')}`; return `${this.basePath}/${name}`; diff --git a/src/common.t.ts b/src/common.t.ts new file mode 100644 index 0000000..1afab57 --- /dev/null +++ b/src/common.t.ts @@ -0,0 +1,2 @@ +import type * as t from './types'; +export type { t }; diff --git a/src/common/const.hashes.ts b/src/common/const.hashes.ts new file mode 100644 index 0000000..d51ca2e --- /dev/null +++ b/src/common/const.hashes.ts @@ -0,0 +1,61 @@ +/** + * Generated file - do not edit. + * See: + * - generator: script.ts/generate-hashtype.ts + * - command: yarn run gen:hashtype + */ +import { type t } from '../common.t'; + +export const hashAlgorithms: t.HashAlgorithm[] = [ + 'RSA-MD5', + 'RSA-RIPEMD160', + 'RSA-SHA1', + 'RSA-SHA1-2', + 'RSA-SHA224', + 'RSA-SHA256', + 'RSA-SHA3-224', + 'RSA-SHA3-256', + 'RSA-SHA3-384', + 'RSA-SHA3-512', + 'RSA-SHA384', + 'RSA-SHA512', + 'RSA-SHA512/224', + 'RSA-SHA512/256', + 'RSA-SM3', + 'blake2b512', + 'blake2s256', + 'id-rsassa-pkcs1-v1_5-with-sha3-224', + 'id-rsassa-pkcs1-v1_5-with-sha3-256', + 'id-rsassa-pkcs1-v1_5-with-sha3-384', + 'id-rsassa-pkcs1-v1_5-with-sha3-512', + 'md5', + 'md5-sha1', + 'md5WithRSAEncryption', + 'ripemd', + 'ripemd160', + 'ripemd160WithRSA', + 'rmd160', + 'sha1', + 'sha1WithRSAEncryption', + 'sha224', + 'sha224WithRSAEncryption', + 'sha256', + 'sha256WithRSAEncryption', + 'sha3-224', + 'sha3-256', + 'sha3-384', + 'sha3-512', + 'sha384', + 'sha384WithRSAEncryption', + 'sha512', + 'sha512-224', + 'sha512-224WithRSAEncryption', + 'sha512-256', + 'sha512-256WithRSAEncryption', + 'sha512WithRSAEncryption', + 'shake128', + 'shake256', + 'sm3', + 'sm3WithRSAEncryption', + 'ssl3-md5', + 'ssl3-sha1']; diff --git a/src/common/index.ts b/src/common/index.ts index 770b333..6eeee58 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -1,4 +1,7 @@ -import * as Util from './Util'; +import * as Util from './util'; -export { Util }; +export * from './const.hashes'; export * from './libs'; +export { Util }; + +export { type t } from '../common.t'; diff --git a/src/common/libs.ts b/src/common/libs.ts index 9c26e98..3c0a06d 100644 --- a/src/common/libs.ts +++ b/src/common/libs.ts @@ -1,6 +1,6 @@ -import R from 'ramda'; +import crypto from 'crypto'; import fs from 'fs-extra'; import fsPath from 'path'; -import crypto from 'crypto'; +import R from 'ramda'; -export { R, fs, fsPath, crypto }; +export { R, crypto, fs, fsPath }; diff --git a/src/common/Util.ts b/src/common/util.ts similarity index 89% rename from src/common/Util.ts rename to src/common/util.ts index 112a968..2f3554b 100644 --- a/src/common/Util.ts +++ b/src/common/util.ts @@ -1,4 +1,5 @@ -import { R, fs, fsPath, crypto } from './libs'; +import { type t } from '../common.t'; +import { R, crypto, fs, fsPath } from './libs'; export const isNothing = (value: any) => R.isNil(value) || R.isEmpty(value); export const isString = R.is(String); @@ -39,15 +40,19 @@ export const filePathsP = async (basePath: string, ns: string): Promise { +export const hash = (algorithm: t.HashAlgorithm, ...values: any[]) => { if (R.pipe(compact, R.isEmpty)(values)) return undefined; - const resultHash = crypto.createHash('sha1'); + const resultHash = crypto.createHash(algorithm); const addValue = (value: any) => resultHash.update(value); const addValues = R.forEach(addValue); R.pipe(toStringArray, addValues)(values); return resultHash.digest('hex'); }; +export const hashExists = (algorithm: t.HashAlgorithm) => { + return crypto.getHashes().includes(algorithm); +}; + /** * Retrieve a value from the given path. */ diff --git a/src/index.ts b/src/index.ts index 8037aec..87ab277 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,8 @@ -import { FileSystemCache, FileSystemCacheOptions } from './FileSystemCache'; +import { type t } from './common'; +import { FileSystemCache } from './FileSystemCache'; /** * Default entry function. */ -export default (options?: FileSystemCacheOptions) => new FileSystemCache(options); -export { FileSystemCache }; +export default (options?: t.FileSystemCacheOptions) => new FileSystemCache(options); +export { FileSystemCache, FileSystemCache as Cache }; diff --git a/src/test/cache.TEST.ts b/src/test/cache.TEST.ts index 373a948..a4d7759 100644 --- a/src/test/cache.TEST.ts +++ b/src/test/cache.TEST.ts @@ -1,9 +1,25 @@ -import { expect, fs, fsPath, FileSystemCache, Util, basePath } from './common'; +import { FileSystemCache, Util, basePath, expect, fs, fsPath, type t } from './common'; -const ABSOLUTE_BASE_PATH = fsPath.resolve(basePath); +const BASE_PATH = fsPath.resolve(basePath); -describe('FileSystemCache', function () { - describe('basePath', function () { +describe('FileSystemCache', () => { + describe('constructor', () => { + it('defaults', () => { + const cache = new FileSystemCache(); + expect(cache.hash).to.eql('sha1'); + expect(cache.ttl).to.eql(0); + expect(cache.ns).to.eql(undefined); + expect(cache.extension).to.eql(undefined); + }); + + it('throw: hash not supported', async () => { + const hash = '404-no-exist' as any; + const fn = () => new FileSystemCache({ hash }); + expect(fn).to.throw(/Hash does not exist/); + }); + }); + + describe('basePath', () => { it("has a default path of '/.cache'", () => { const cache = new FileSystemCache(); expect(cache.basePath).to.equal(fsPath.resolve('./.cache')); @@ -29,7 +45,7 @@ describe('FileSystemCache', function () { }); }); - describe('ns (namespace)', function () { + describe('ns (namespace)', () => { it('has no namespace by default', () => { expect(new FileSystemCache().ns).to.equal(undefined); expect(new FileSystemCache([] as any).ns).to.equal(undefined); @@ -37,50 +53,76 @@ describe('FileSystemCache', function () { }); it('creates a namespace hash with a single value', () => { - const cache = new FileSystemCache({ ns: 'foo' }); - expect(cache.ns).to.equal(Util.hash('foo')); + const cache1 = new FileSystemCache({ ns: 'foo' }); + const cache2 = new FileSystemCache({ ns: 'foo', hash: 'sha256' }); + const cache3 = new FileSystemCache({ ns: 'foo', hash: 'sha512' }); + expect(cache1.ns).to.equal(Util.hash('sha1', 'foo')); + expect(cache2.ns).to.equal(Util.hash('sha256', 'foo')); + expect(cache3.ns).to.equal(Util.hash('sha512', 'foo')); }); it('creates a namespace hash with several values', () => { - const cache = new FileSystemCache({ ns: ['foo', 123] }); - expect(cache.ns).to.equal(Util.hash('foo', 123)); + const cache1 = new FileSystemCache({ ns: ['foo', 123] }); + const cache2 = new FileSystemCache({ ns: ['foo', 123], hash: 'sha256' }); + const cache3 = new FileSystemCache({ ns: ['foo', 123], hash: 'sha512' }); + expect(cache1.ns).to.equal(Util.hash('sha1', 'foo', 123)); + expect(cache2.ns).to.equal(Util.hash('sha256', 'foo', 123)); + expect(cache3.ns).to.equal(Util.hash('sha512', 'foo', 123)); }); }); - describe('path', function () { + describe('path', () => { it('throws if no key is provided', () => { const cache = new FileSystemCache({ basePath }); expect(() => (cache as any).path()).to.throw(); }); it('returns a path with no namespace', () => { - const key = 'foo'; - const cache = new FileSystemCache({ basePath }); - const path = `${ABSOLUTE_BASE_PATH}/${Util.hash(key)}`; - expect(cache.path(key)).to.equal(path); + const test = (hash: t.HashAlgorithm) => { + const key = 'foo'; + const cache = new FileSystemCache({ basePath, hash }); + const path = `${BASE_PATH}/${Util.hash(hash, key)}`; + expect(cache.path(key)).to.equal(path); + }; + + test('sha1'); + test('sha256'); + test('sha512'); }); it('returns a path with a namespace', () => { - const key = 'foo'; - const ns = [1, 2]; - const cache = new FileSystemCache({ basePath, ns: ns }); - const path = `${ABSOLUTE_BASE_PATH}/${Util.hash(ns)}-${Util.hash(key)}`; - expect(cache.path(key)).to.equal(path); + const test = (hash: t.HashAlgorithm) => { + const key = 'foo'; + const ns = [1, 2]; + const cache = new FileSystemCache({ basePath, ns, hash }); + const path = `${BASE_PATH}/${Util.hash(hash, ns)}-${Util.hash(hash, key)}`; + expect(cache.path(key)).to.equal(path); + }; + + test('sha1'); + test('sha256'); + test('sha512'); }); it('returns a path with a file extension', () => { - const key = 'foo'; - const path = `${ABSOLUTE_BASE_PATH}/${Util.hash(key)}.styl`; - let cache; - cache = new FileSystemCache({ basePath, extension: 'styl' }); - expect(cache.path(key)).to.equal(path); - - cache = new FileSystemCache({ basePath, extension: '.styl' }); - expect(cache.path(key)).to.equal(path); + const test = (hash: t.HashAlgorithm) => { + const key = 'foo'; + const path = `${BASE_PATH}/${Util.hash(hash, key)}.styl`; + let cache; + cache = new FileSystemCache({ basePath, hash, extension: 'styl' }); + expect(cache.path(key)).to.equal(path); + + cache = new FileSystemCache({ basePath, hash, extension: '.styl' }); + expect(cache.path(key)).to.equal(path); + }; + + test('sha1'); + test('sha256'); + test('sha512'); }); }); - describe('ensureBasePath()', function () { + describe('ensureBasePath()', () => { it('creates the base path', (done) => { const cache = new FileSystemCache({ basePath }); expect(fs.existsSync(cache.basePath)).to.equal(false); diff --git a/src/test/cache.expires.TEST.ts b/src/test/cache.expires.TEST.ts index 029aa1b..7ef3870 100644 --- a/src/test/cache.expires.TEST.ts +++ b/src/test/cache.expires.TEST.ts @@ -1,51 +1,47 @@ -import { expect, FileSystemCache, basePath } from './common'; +import { FileSystemCache, basePath, expect } from './common'; function sleep(seconds: number): Promise { return new Promise((resolve) => { setTimeout(resolve, seconds * 1000); }); -} +} describe('expires', async function () { this.timeout(3000); + it('cache doesnt expire (various types)', (done) => { const cache1 = new FileSystemCache({ basePath, ttl: 10 }); const cache2 = new FileSystemCache({ basePath, ttl: 10 }); - + cache1.set('foo-1', 'bar-1'); cache1.set('foo-2', 'bar-2', 0); - cache1.set('foo-3', 'bar-3', 10) - .then(() => { - cache2.get('foo') - .then((result) => { - sleep(1).then(() => { - expect(result).to.equal('bar') - }) - }) - .then(() => { - cache2.get('foo-2').then((result) => expect(result).to.equal('bar-2')); - cache2.get('foo-3').then((result) => expect(result).to.equal('bar-3')); - }) - .finally(() => done()); - }); - + cache1.set('foo-3', 'bar-3', 10).then(() => { + cache2 + .get('foo') + .then((result) => { + sleep(1).then(() => expect(result).to.equal('bar')); + }) + .then(() => { + cache2.get('foo-2').then((result) => expect(result).to.equal('bar-2')); + cache2.get('foo-3').then((result) => expect(result).to.equal('bar-3')); + }) + .finally(() => done()); + }); }); it('cache expires (various types)', (done) => { - const cache1 = new FileSystemCache({ basePath, ttl: 1 }); - const cache2 = new FileSystemCache({ basePath, ttl: 1 }); - cache1.set('number', 123) + const cache1 = new FileSystemCache({ basePath, ttl: 0.5 }); + const cache2 = new FileSystemCache({ basePath, ttl: 0.5 }); + cache1.set('number', 123); cache1.set('object', { foo: 456 }, 1).then(() => { - sleep(2).then(() => { - cache2.get('number') - .then((result) => expect(result).to.equal(undefined)) - cache2.get('object') + sleep(1).then(() => { + cache2.get('number').then((result) => expect(result).to.equal(undefined)); + cache2 + .get('object') .then((result) => expect(result).to.equal(undefined)) .finally(() => done()) - .catch((err) => console.error(err));; + .catch((err) => console.error(err)); }); }); }); - - }); diff --git a/src/test/common.ts b/src/test/common.ts index 330ceec..bd439f5 100644 --- a/src/test/common.ts +++ b/src/test/common.ts @@ -1,9 +1,8 @@ import { expect } from 'chai'; -import { fs, fsPath, Util } from '../common'; import { FileSystemCache } from '..'; +import { Util, crypto, fs, fsPath, type t } from '../common'; -export { FileSystemCache, fs, fsPath, Util, expect }; - +export { FileSystemCache, Util, crypto, expect, fs, fsPath, type t }; export const basePath = './.tmp'; const deleteFolder = () => fs.removeSync(fsPath.resolve(basePath)); diff --git a/src/test/funcs.TEST.ts b/src/test/funcs.TEST.ts deleted file mode 100644 index f8c7317..0000000 --- a/src/test/funcs.TEST.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { expect, Util } from './common'; - -describe('util.hash', function () { - it("does not hash 'nothing' (undefined)", () => { - expect(Util.hash()).to.equal(undefined); - expect(Util.hash(null)).to.equal(undefined); - expect(Util.hash(null, undefined)).to.equal(undefined); - expect(Util.hash(null, [undefined, null])).to.equal(undefined); - }); - - it('returns a hash of multiple values', () => { - const result = Util.hash('one', undefined, [3, 4], 2); - expect(result).to.equal('0f161cb21daaa15962c1085855fe19dcb9df67e9'); - }); - - it('returns a hash of a single value', () => { - const result = Util.hash('one'); - expect(result).to.equal('443b7f970b6c6af26c392534c0a28ed4ad00a30e'); - }); - - it('returns a hash from an array', () => { - const result1 = Util.hash('one', 'two'); - const result2 = Util.hash(['one', 'two']); - expect(result1).to.equal('7fc87660c49692a9b11b02cb23cc478771ca3e3f'); - expect(result1).to.equal(result2); - }); -}); diff --git a/src/test/util.TEST.ts b/src/test/util.TEST.ts index 4b003db..e3e82d7 100644 --- a/src/test/util.TEST.ts +++ b/src/test/util.TEST.ts @@ -1,4 +1,4 @@ -import { expect, Util } from './common'; +import { FileSystemCache, Util, crypto, expect, type t } from './common'; describe('common/util', () => { it('compact', () => { @@ -6,4 +6,52 @@ describe('common/util', () => { const res = Util.compact(input); expect(res).to.eql(['one', 'two', 'three']); }); + + describe('util.hash', () => { + it("does not hash 'nothing' (undefined)", () => { + const test = (algorithm: t.HashAlgorithm) => { + expect(Util.hash(algorithm)).to.equal(undefined); + expect(Util.hash(algorithm, null)).to.equal(undefined); + expect(Util.hash(algorithm, null, undefined)).to.equal(undefined); + expect(Util.hash(algorithm, null, [undefined, null])).to.equal(undefined); + }; + FileSystemCache.hashAlgorithms.forEach(test); + }); + + it('returns a hash of multiple values', () => { + const test = (algorithm: t.HashAlgorithm, expected: string) => { + const result = Util.hash(algorithm, 'one', undefined, [3, 4], 2); + expect(result).to.equal(expected); + }; + test('sha1', '0f161cb21daaa15962c1085855fe19dcb9df67e9'); + test('sha256', 'c637bf7b330a578cd63a36d1d68c2345959591784dc08d35f249eb596de29c42'); + }); + + it('returns a hash of a single value', () => { + const test = (algorithm: t.HashAlgorithm, expected: string) => { + const result = Util.hash(algorithm, 'one'); + expect(result).to.equal(expected); + }; + test('sha1', '443b7f970b6c6af26c392534c0a28ed4ad00a30e'); + test('sha256', '49e9fcfb5617aad332d56d58ffd0c7020d29ec1d0d0a03b7d7c47f268820acf3'); + }); + + it('returns a hash from an array', () => { + const test = (algorithm: t.HashAlgorithm, expected: string) => { + const result1 = Util.hash(algorithm, 'one', 'two'); + const result2 = Util.hash(algorithm, ['one', 'two']); + expect(result1).to.equal(expected); + expect(result1).to.equal(result2); + }; + test('sha1', '7fc87660c49692a9b11b02cb23cc478771ca3e3f'); + test('sha256', 'c7d71a7239fceefe30f084ed730d02f609fe63024dc5cf57c674052efedd96ff'); + }); + }); + + describe('util.hash (generator)', () => { + it('hashes constant matches node', () => { + const hashes = crypto.getHashes(); + FileSystemCache.hashAlgorithms.forEach((name) => expect(hashes).to.include(name)); + }); + }); }); diff --git a/src/types.hashes.ts b/src/types.hashes.ts new file mode 100644 index 0000000..738905e --- /dev/null +++ b/src/types.hashes.ts @@ -0,0 +1,59 @@ +/** + * Generated file - do not edit. + * See: + * - generator: script.ts/generate-hashtype.ts + * - command: yarn run gen:hashtype + */ +export type HashAlgorithm = + | 'RSA-MD5' + | 'RSA-RIPEMD160' + | 'RSA-SHA1' + | 'RSA-SHA1-2' + | 'RSA-SHA224' + | 'RSA-SHA256' + | 'RSA-SHA3-224' + | 'RSA-SHA3-256' + | 'RSA-SHA3-384' + | 'RSA-SHA3-512' + | 'RSA-SHA384' + | 'RSA-SHA512' + | 'RSA-SHA512/224' + | 'RSA-SHA512/256' + | 'RSA-SM3' + | 'blake2b512' + | 'blake2s256' + | 'id-rsassa-pkcs1-v1_5-with-sha3-224' + | 'id-rsassa-pkcs1-v1_5-with-sha3-256' + | 'id-rsassa-pkcs1-v1_5-with-sha3-384' + | 'id-rsassa-pkcs1-v1_5-with-sha3-512' + | 'md5' + | 'md5-sha1' + | 'md5WithRSAEncryption' + | 'ripemd' + | 'ripemd160' + | 'ripemd160WithRSA' + | 'rmd160' + | 'sha1' + | 'sha1WithRSAEncryption' + | 'sha224' + | 'sha224WithRSAEncryption' + | 'sha256' + | 'sha256WithRSAEncryption' + | 'sha3-224' + | 'sha3-256' + | 'sha3-384' + | 'sha3-512' + | 'sha384' + | 'sha384WithRSAEncryption' + | 'sha512' + | 'sha512-224' + | 'sha512-224WithRSAEncryption' + | 'sha512-256' + | 'sha512-256WithRSAEncryption' + | 'sha512WithRSAEncryption' + | 'shake128' + | 'shake256' + | 'sm3' + | 'sm3WithRSAEncryption' + | 'ssl3-md5' + | 'ssl3-sha1'; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..8c2b8da --- /dev/null +++ b/src/types.ts @@ -0,0 +1,10 @@ +import type { HashAlgorithm } from './types.hashes'; +export type { HashAlgorithm }; + +export type FileSystemCacheOptions = { + basePath?: string; + ns?: any; + ttl?: number; + hash?: HashAlgorithm; + extension?: string; +}; diff --git a/yarn.lock b/yarn.lock index f140a96..18e374b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,13 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@jest/expect-utils@^29.5.0": version "29.5.0" resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.5.0.tgz#f74fad6b6e20f924582dc8ecbf2cb800fe43a036" @@ -49,15 +56,53 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@sinclair/typebox@^0.25.16": version "0.25.24" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== -"@types/chai@4.3.4": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/chai@4.3.5": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== "@types/expect@24.3.0": version "24.3.0" @@ -115,12 +160,12 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.2.tgz#c2a1383cc392aee13d1eba7082d951df54aed04a" integrity sha512-iXqchnHr5CvfO+s/H5/Ji7fNak5bxb2Q2Fadq54sVhXRvEBRZAEyvVs3keVPS0xQNTnhLtxc5QDNXKyzSRpyKA== -"@types/ramda@0.29.1": - version "0.29.1" - resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.29.1.tgz#c3d3842b9bc4aa5fbe03e90faa0c3eff9ba0f9f4" - integrity sha512-Ff5RRG9YRqMgWOqZVVavSjGEvYHUnXnGF0YPGbzIWhB3o8qiccSJZlFX2z8qm3G1H/IC5w0ozHmlezUeQCtGfQ== +"@types/ramda@0.29.2": + version "0.29.2" + resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.29.2.tgz#b50d52c3958b0988356bc881bf77aadbd2e33651" + integrity sha512-JxvBGR3G4gV3RTOBugVHAAOD6iiv2WjlJ8BHr0s7KALdPpx2l+didoTuoJMmrA0eqpUaCm/slKP4TmxMRihd8g== dependencies: - types-ramda "^0.29.2" + types-ramda "^0.29.3" "@types/stack-utils@^2.0.0": version "2.0.1" @@ -139,6 +184,16 @@ dependencies: "@types/yargs-parser" "*" +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -176,6 +231,11 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -331,6 +391,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + debug@4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -365,6 +430,11 @@ diff@^3.1.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -906,6 +976,25 @@ ts-mocha@10.0.0: optionalDependencies: tsconfig-paths "^3.5.0" +ts-node@10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + ts-node@7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" @@ -940,23 +1029,28 @@ type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -types-ramda@^0.29.2: - version "0.29.2" - resolved "https://registry.yarnpkg.com/types-ramda/-/types-ramda-0.29.2.tgz#2bf33863a51498b43f616cd8cd98227efe9109eb" - integrity sha512-HpLcR0ly2EfXQwG8VSI5ov6ml7PvtT+u+cp+7lZLu7q4nhnPDVW+rUTC1uy/SNs4aAyTUXri5M/LyhgvjEXJDg== +types-ramda@^0.29.3: + version "0.29.3" + resolved "https://registry.yarnpkg.com/types-ramda/-/types-ramda-0.29.3.tgz#0a611b4d414bf7c51ba417c3fd3352985b0de97f" + integrity sha512-6z8/UCI5/kRorQ91Mo+TUXImHpGAhmhg8ZIdT/tNrG+xSQvDwJXYyT5Nlw2U5VpoKetUZVqQXYYLQyq5Bzccsg== dependencies: ts-toolbelt "^9.6.0" -typescript@5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" - integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +typescript@5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" + integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" @@ -1014,6 +1108,11 @@ yargs@16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yn@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"