diff --git a/types/cacache/cacache-tests.ts b/types/cacache/cacache-tests.ts new file mode 100644 index 0000000000..2315df5fd1 --- /dev/null +++ b/types/cacache/cacache-tests.ts @@ -0,0 +1,78 @@ +import * as cacache from 'cacache'; +import * as fs from 'fs'; + +const cachePath = ''; + +cacache.ls(cachePath).then(() => {}); + +cacache.ls.stream(cachePath).on('data', data => { + data; // $ExpectType any +}); + +cacache.get(cachePath, 'my-thing').then(() => {}); + +cacache.get.byDigest(cachePath, 'sha512-BaSe64HaSh').then(() => {}); + +cacache.get + .stream(cachePath, 'my-thing') + .on('metadata', metadata => { + metadata; // $ExpectType any + }) + .on('integrity', integrity => { + integrity; // $ExpectType any + }) + .pipe(fs.createWriteStream('./x.tgz')); + +cacache.get.stream.byDigest(cachePath, 'sha512-SoMeDIGest+64==').pipe(fs.createWriteStream('./x.tgz')); + +cacache.get.info(cachePath, 'my-thing').then(() => {}); + +cacache.get.hasContent(cachePath, 'sha521-NOT+IN/CACHE==').then(() => {}); + +cacache.put(cachePath, 'registry.npmjs.org|cacache@1.0.0', Buffer.from([])).then(integrity => { + integrity; // $ExpectType string +}); + +fs.createReadStream('').pipe( + cacache.put + .stream(cachePath, 'registry.npmjs.org|cacache@1.0.0') + .on('integrity', d => console.log(`integrity digest is ${d}`)), +); + +cacache.rm.all(cachePath).then(() => { + // ... +}); + +cacache.rm.entry(cachePath, 'my-thing').then(() => { + // ... +}); + +cacache.rm.content(cachePath, 'sha512-SoMeDIGest/IN+BaSE64==').then(() => { + console.log('data for my-thing is gone!'); +}); + +cacache.tmp.mkdir(cachePath).then(dir => { + dir; // $ExpectType string + // ... +}); + +cacache.tmp.mkdir(cachePath).then(dir => { + dir; // $ExpectType string + cacache.tmp.fix(cachePath).then(() => { + // ... + }); +}); + +cacache.tmp.withTmp(cachePath, dir => { + dir; // $ExpectType string +}); + +cacache.verify(cachePath).then(stats => { + console.log('cache is much nicer now! stats:', stats); +}); + +cacache.verify(cachePath).then(() => { + cacache.verify.lastRun(cachePath).then(lastTime => { + console.log('cacache.verify was last called on' + lastTime); + }); +}); diff --git a/types/cacache/en.d.ts b/types/cacache/en.d.ts new file mode 100644 index 0000000000..5105839d57 --- /dev/null +++ b/types/cacache/en.d.ts @@ -0,0 +1,306 @@ +/// + +export interface CacheObject { + /** Subresource Integrity hash for the content this entry refers to. */ + integrity: string; + /** Key the entry was looked up under. Matches the key argument. */ + key: string; + /** User-assigned metadata associated with the entry/content. */ + metadata?: any; + /** Filesystem path where content is stored, joined with cache argument. */ + path: string; + /** Timestamp the entry was first added on. */ + time: number; +} + +export namespace get { + interface HasContentObject { + size: number; + sri: { + algorithm: string; + digest: string; + options: any[]; + source: string; + }; + } + + interface Options { + integrity?: string; + memoize?: boolean; + size?: number; + } + + namespace copy { + function byDigest(cachePath: string, hash: string, dest: string, opts?: Options): Promise; + } + + namespace stream { + function byDigest(cachePath: string, hash: string, opts?: Options): NodeJS.ReadableStream; + } + + function byDigest(cachePath: string, hash: string, opts?: Options): Promise; + function copy(cachePath: string, key: string, dest: string, opts?: Options): Promise; + + /** + * Looks up a Subresource Integrity hash in the cache. If content exists + * for this `integrity`, it will return an object, with the specific single + * integrity hash that was found in sri key, and the size of the found + * content as size. If no content exists for this integrity, it will return + * `false`. + */ + function hasContent(cachePath: string, hash: string): Promise; + function hasContentnc(cachePath: string, hash: string): HasContentObject | false; + + /** + * Looks up `key` in the cache index, returning information about the entry + * if one exists. + */ + function info(cachePath: string, key: string): Promise; + + /** + * Returns a Readable Stream of the cached data identified by `key`. + * + * If there is no content identified by `key`, or if the locally-stored data + * does not pass the validity checksum, an error will be emitted. + * + * `metadata` and `integrity` events will be emitted before the stream + * closes, if you need to collect that extra data about the cached entry. + * + * A sub-function, `get.stream.byDigest` may be used for identical behavior, + * except lookup will happen by integrity hash, bypassing the index + * entirely. This version does not emit the `metadata` and `integrity` + * events at all. + */ + function stream(cachePath: string, key: string, opts?: Options): NodeJS.ReadableStream; + function sync(cachePath: string, key: string, opts?: Options): CacheObject; + function syncDigest(cachePath: string, key: string, opts?: Options): CacheObject; +} + +export namespace ls { + type Cache = Record; + + /** + * Lists info for all entries currently in the cache as a single large + * object. + * + * This works just like `ls`, except `get.info` entries are returned as + * `'data'` events on the returned stream. + */ + function stream(cachePath: string): NodeJS.ReadableStream; +} + +export namespace put { + interface Options { + /** + * Default: `['sha512']` + * + * Hashing algorithms to use when calculating the subresource integrity + * digest for inserted data. Can use any algorithm listed in + * `crypto.getHashes()` or `'omakase'`/`'お任せします'` to pick a random + * hash algorithm on each insertion. You may also use any anagram of + * `'modnar'` to use this feature. + * + * Currently only supports one algorithm at a time (i.e., an array + * length of exactly `1`). Has no effect if `opts.integrity` is present. + */ + algorithms?: string[]; + + /** + * If present, the pre-calculated digest for the inserted content. If + * this option if provided and does not match the post-insertion digest, + * insertion will fail with an `EINTEGRITY` error. + * + * `algorithms` has no effect if this option is present. + */ + integrity?: string; + + /** Arbitrary metadata to be attached to the inserted key. */ + metadata?: any; + + /** + * Default: `null` + * + * If provided, cacache will memoize the given cache insertion in + * memory, bypassing any filesystem checks for that key or digest in + * future cache fetches. Nothing will be written to the in-memory cache + * unless this option is explicitly truthy. + * + * If `opts.memoize` is an object or a `Map`-like (that is, an object + * with `get` and `set` methods), it will be written to instead of the + * global memoization cache. + * + * Reading from disk data can be forced by explicitly passing + * `memoize: false` to the reader functions, but their default will be + * to read from memory. + */ + memoize?: null | boolean; + + /** + * If provided, the data stream will be verified to check that enough + * data was passed through. If there's more or less data than expected, + * insertion will fail with an `EBADSIZE` error. + */ + size?: number; + } + + /** + * Returns a Writable Stream that inserts data written to it into the cache. + * Emits an `integrity` event with the digest of written contents when it + * succeeds. + */ + function stream(cachePath: string, key: string, opts?: Options): NodeJS.WritableStream; +} + +export namespace rm { + /** + * Clears the entire cache. Mainly by blowing away the cache directory + * itself. + */ + function all(cachePath: string): Promise; + + /** + * Removes the index entry for `key`. Content will still be accessible if + * requested directly by content address (`get.stream.byDigest`). + * + * To remove the content itself (which might still be used by other + * entries), use `rm.content`. Or, to safely vacuum any unused content, + * use `verify`. + */ + function entry(cachePath: string, key: string): Promise; + + /** + * Removes the content identified by `integrity`. Any index entries + * referring to it will not be usable again until the content is re-added + * to the cache with an identical digest. + */ + function content(cachePath: string, hash: string): Promise; +} + +export namespace tmp { + type Callback = (dir: string) => void; + interface Options { + tmpPrefix?: string; + } + + /** + * Sets the `uid` and `gid` properties on all files and folders within the + * tmp folder to match the rest of the cache. + * + * Use this after manually writing files into `tmp.mkdir` or `tmp.withTmp`. + */ + function fix(cachePath: string): Promise; + + /** + * Returns a unique temporary directory inside the cache's `tmp` dir. This + * directory will use the same safe user assignment that all the other stuff + * use. + * + * Once the directory is made, it's the user's responsibility that all files + * within are given the appropriate `gid`/`uid` ownership settings to match + * the rest of the cache. If not, you can ask cacache to do it for you by + * calling `tmp.fix()`, which will fix all tmp directory permissions. + * + * If you want automatic cleanup of this directory, use `tmp.withTmp()` + */ + function mkdir(cachePath: string, opts?: Options): Promise; + + /** + * Creates a temporary directory with `tmp.mkdir()` and calls `cb` with it. + * The created temporary directory will be removed when the return value of + * `cb()` resolves -- that is, if you return a Promise from `cb()`, the tmp + * directory will be automatically deleted once that promise completes. + * + * The same caveats apply when it comes to managing permissions for the tmp dir's contents. + */ + function withTmp(cachePath: string, opts: Options, cb: Callback): void; + function withTmp(cachePath: string, cb: Callback): void; +} + +export namespace verify { + interface Options { + /** + * Receives a formatted entry. Return false to remove it. + * Note: might be called more than once on the same entry. + */ + filter: false | string; + } + + /** + * Returns a Date representing the last time `cacache.verify` was run on + * `cache`. + */ + function lastRun(cachePath: string): Promise; +} + +export function clearMemoized(): Record; + +/** + * Returns an object with the cached data, digest, and metadata identified by + * `key`. The `data` property of this object will be a Buffer instance that + * presumably holds some data that means something to you. I'm sure you know + * what to do with it! cacache just won't care. + * + * `integrity` is a Subresource Integrity string. That is, a string that can be + * used to verify `data`, which looks like + * `-`. + * + * If there is no content identified by key, or if the locally-stored data does + * not pass the validity checksum, the promise will be rejected. + * + * A sub-function, `get.byDigest` may be used for identical behavior, except + * lookup will happen by integrity hash, bypassing the index entirely. This + * version of the function only returns data itself, without any wrapper. + * + * **Note** + * + * This function loads the entire cache entry into memory before returning it. + * If you're dealing with Very Large data, consider using `get.stream` instead. + */ +export function get(cachePath: string, key: string, options?: get.Options): Promise; + +/** + * Lists info for all entries currently in the cache as a single large object. + * Each entry in the object will be keyed by the unique index key, with + * corresponding `get.info` objects as the values. + */ +export function ls(cachePath: string): Promise; + +/** + * Inserts data passed to it into the cache. The returned Promise resolves with + * a digest (generated according to `opts.algorithms`) after the cache entry has + * been successfully written. + */ +export function put(cachePath: string, key: string, data: any, opts?: put.Options): Promise; + +/** + * Removes the index entry for `key`. Content will still be accessible if + * requested directly by content address (`get.stream.byDigest`). + * + * To remove the content itself (which might still be used by other + * entries), use `rm.content`. Or, to safely vacuum any unused content, + * use `verify`. + */ +export function rm(cachePath: string, key: string): Promise; + +/** + * Configure the language/locale used for messages and errors coming from + * cacache. The list of available locales is in the `./locales` directory in the + * project root. + */ +export function setLocale(locale: string): any; + +/** + * Checks out and fixes up your cache: + * + * - Cleans up corrupted or invalid index entries + * - Custom entry filtering options + * - Garbage collects any content entries not referenced by the index + * - Checks integrity for all content entries and removes invalid content + * - Fixes cache ownership + * - Removes the `tmp` directory in the cache and all its contents. + * + * When it's done, it'll return an object with various stats about the + * verification process, including amount of storage reclaimed, number of valid + * entries, number of entries removed, etc. + */ +export function verify(cachePath: string, opts?: verify.Options): Promise; diff --git a/types/cacache/index.d.ts b/types/cacache/index.d.ts new file mode 100644 index 0000000000..a534830b9a --- /dev/null +++ b/types/cacache/index.d.ts @@ -0,0 +1,7 @@ +// Type definitions for cacache 12.0 +// Project: https://github.com/npm/cacache#readme +// Definitions by: Florian Keller +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.1 + +export * from './en'; diff --git a/types/cacache/tsconfig.json b/types/cacache/tsconfig.json new file mode 100644 index 0000000000..279a97a1ba --- /dev/null +++ b/types/cacache/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "en.d.ts", + "cacache-tests.ts" + ] +} diff --git a/types/cacache/tslint.json b/types/cacache/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/cacache/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }