From 0ec804fe74a3d6ad32a68dc029c9c4a155d2701c Mon Sep 17 00:00:00 2001 From: Seally Date: Wed, 23 Oct 2019 05:01:41 +0700 Subject: [PATCH] [mock-fs] Update type definitions to v4.10. (#38796) --- types/mock-fs/index.d.ts | 100 +++++----- types/mock-fs/lib/directory.d.ts | 26 +++ types/mock-fs/lib/file.d.ts | 14 ++ types/mock-fs/lib/filesystem.d.ts | 167 ++++++++++++++++ types/mock-fs/lib/index.d.ts | 3 + types/mock-fs/lib/item.d.ts | 65 +++++++ types/mock-fs/lib/symlink.d.ts | 12 ++ types/mock-fs/mock-fs-tests.ts | 304 ++++++++++++++++++++++-------- types/mock-fs/tsconfig.json | 12 +- types/mock-fs/tslint.json | 81 +------- 10 files changed, 571 insertions(+), 213 deletions(-) create mode 100644 types/mock-fs/lib/directory.d.ts create mode 100644 types/mock-fs/lib/file.d.ts create mode 100644 types/mock-fs/lib/filesystem.d.ts create mode 100644 types/mock-fs/lib/index.d.ts create mode 100644 types/mock-fs/lib/item.d.ts create mode 100644 types/mock-fs/lib/symlink.d.ts diff --git a/types/mock-fs/index.d.ts b/types/mock-fs/index.d.ts index a0877e573d..4534d88489 100644 --- a/types/mock-fs/index.d.ts +++ b/types/mock-fs/index.d.ts @@ -1,56 +1,54 @@ -// Type definitions for mock-fs 3.6.0 +// Type definitions for mock-fs 4.10 // Project: https://github.com/tschaub/mock-fs -// Definitions by: Wim Looman , Qubo +// Definitions by: Wim Looman , +// Qubo , +// Porama Ruengrairatanaroj // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -/// - - -import nodefs = require("fs"); - -declare function mock(config?: mock.Config, options?: mock.Options): void; - -declare namespace mock { - function file(config: FileConfig): File; - function directory(config: DirectoryConfig): Directory; - function symlink(config: SymlinkConfig): Symlink; - - function restore(): void; - - function fs(config?: Config, options?: Options): typeof nodefs; - - interface Config { - [path: string]: string | Buffer | File | Directory | Symlink | Config; - } - - interface Options { - createCwd?: boolean; - createTmp?: boolean; - } - - interface CommonConfig { - mode?: number; - uid?: number; - git?: number; - atime?: Date; - ctime?: Date; - mtime?: Date; - birthtime?: Date; - } - - interface FileConfig extends CommonConfig { - content: string | Buffer; - } - interface DirectoryConfig extends CommonConfig { - items: Config; - } - interface SymlinkConfig extends CommonConfig { - path: string; - } - - class File { private _file: any; } - class Directory { private _directory: any; } - class Symlink { private _symlink: any; } -} +import FileSystem = require('./lib/filesystem'); +import File = require('./lib/file'); +import Directory = require('./lib/directory'); +import SymbolicLink = require('./lib/symlink'); export = mock; + +/** + * Swap out the fs bindings for a mock file system. + * + * _Note:_ Import this file _before_ any other modules that import the `fs` + * module. + * + * @param config Mock file system configuration. + * @param options Any filesystem options. + * @param options.createCwd Create a directory for `process.cwd()` (defaults to + * `true`). + * @param options.createTmp Create a directory for `os.tmpdir()` (defaults to + * `true`). + */ +declare function mock(config?: FileSystem.DirectoryItems, options?: FileSystem.Options): void; + +declare namespace mock { + /** + * Get hold of the mocked filesystem's 'root' + * If fs hasn't currently been replaced, this will return an empty object + */ + function getMockRoot(): Directory | {}; + + /** + * Restore the fs bindings for the real file system. + */ + function restore(): void; + + /** + * Create a file factory. + */ + function file(config?: FileSystem.FileOptions): () => File; + /** + * Create a directory factory. + */ + function directory(config?: FileSystem.DirectoryOptions): () => Directory; + /** + * Create a symbolic link factory. + */ + function symlink(config: FileSystem.SymlinkOptions): () => SymbolicLink; +} diff --git a/types/mock-fs/lib/directory.d.ts b/types/mock-fs/lib/directory.d.ts new file mode 100644 index 0000000000..ad3bb974c6 --- /dev/null +++ b/types/mock-fs/lib/directory.d.ts @@ -0,0 +1,26 @@ +import Item = require('./item'); + +export = Directory; + +declare class Directory extends Item { + /** + * Add an item to the directory. + * @param name The name to give the item. + * @param item The item to add. + * @return The added item. + */ + addItem(name: string, item: T): T; + /** Get a named item (or null if none). */ + getItem(name: string): Item | null; + /** + * Remove an item. Will throw an error if not present. + * + * @param name Name of the item to remove. + * @return The orphan item. + */ + removeItem(name: string): Item; + /** Get sorted list of item names in this directory. */ + list(): string[]; + /** Get directory stats. */ + getStats(): Item.ExtendedStats; +} diff --git a/types/mock-fs/lib/file.d.ts b/types/mock-fs/lib/file.d.ts new file mode 100644 index 0000000000..279de73048 --- /dev/null +++ b/types/mock-fs/lib/file.d.ts @@ -0,0 +1,14 @@ +/// + +import Item = require('./item'); + +export = File; + +declare class File extends Item { + /** Get the file contents. */ + getContent(): Buffer; + /** Set the file contents. */ + setContent(content: string | Buffer): void; + /** Get file stats. */ + getStats(): Item.ExtendedStats; +} diff --git a/types/mock-fs/lib/filesystem.d.ts b/types/mock-fs/lib/filesystem.d.ts new file mode 100644 index 0000000000..9add3875cf --- /dev/null +++ b/types/mock-fs/lib/filesystem.d.ts @@ -0,0 +1,167 @@ +import Item = require('./item'); +import File = require('./file'); +import Directory = require('./directory'); +import SymbolicLink = require('./symlink'); + +export = FileSystem; + +declare class FileSystem { + /** + * Create a new file system. + * + * @param options Any filesystem options. + * @param options.createCwd Create a directory for `process.cwd()` (defaults + * to `true`). + * @param options.createTmp Create a directory for `os.tmpdir()` (defaults + * to `true`). + */ + constructor(options?: FileSystem.Options); + + /** Get the root directory. */ + getRoot(): Directory; + + /** + * Get a file system item. + * + * @param filepath Path to item. + * @return The item (or null if not found). + */ + getItem(filepath: string): Item; + + /** + * Configure a mock file system. + * + * @param paths Config object. + * @param options Any filesystem options. + * @param options.createCwd Create a directory for `process.cwd()` (defaults + * to `true`). + * @param options.createTmp Create a directory for `os.tmpdir()` (defaults + * to `true`). + * @return Mock file system. + */ + static create(paths?: FileSystem.DirectoryItems, options?: FileSystem.Options): FileSystem; + + /** + * Generate a factory for new files. + * + * @param config File config. + * @return Factory that creates a new file. + */ + static file(config?: FileSystem.FileOptions): () => File; + + /** + * Generate a factory for new symbolic links. + * + * @param config File config. + * @return Factory that creates a new symbolic link. + */ + static directory(config?: FileSystem.DirectoryOptions): () => Directory; + + /** + * Generate a factory for new directories. + * + * @param config File config. + * @return Factory that creates a new directory. + */ + static symlink(config: FileSystem.SymlinkOptions): () => SymbolicLink; +} + +declare namespace FileSystem { + interface DirectoryItems { + [name: string]: string | Buffer | (() => File) | (() => Directory) | (() => SymbolicLink) | DirectoryItems; + } + + interface Options { + /** + * Create a directory for `process.cwd()`. This is `true` by default. + */ + createCwd?: boolean; + /** + * Create a directory for `os.tmpdir()`. This is `true` by default. + */ + createTmp?: boolean; + } + + interface FileOptions { + /** File contents */ + content?: string | Buffer; + /** File mode (permission and sticky bits). Defaults to `0666`. */ + mode?: number; + /** The user id. Defaults to `process.getuid()`. */ + uid?: number; + /** The group id. Defaults to `process.getgid()`. */ + gid?: number; + /** + * The last file access time. Defaults to `new Date()`. Updated when + * file contents are accessed. + */ + atime?: Date; + /** + * The last file change time. Defaults to `new Date()`. Updated when + * file owner or permissions change. + */ + ctime?: Date; + /** + * The last file modification time. Defaults to `new Date()`. Updated + * when file contents change. + */ + mtime?: Date; + /** + * The time of file creation. Defaults to `new Date()`. + */ + birthtime?: Date; + } + + interface DirectoryOptions { + /** Directory mode (permission and sticky bits). Defaults to `0777`. */ + mode?: number; + /** The user id. Defaults to `process.getuid()`. */ + uid?: number; + /** The group id. Defaults to `process.getgid()`. */ + gid?: number; + /** + * The last directory access time. Defaults to `new Date()`. + */ + atime?: Date; + /** + * The last directory change time. Defaults to `new Date()`. Updated + * when owner or permissions change. + */ + ctime?: Date; + /** + * The last directory modification time. Defaults to `new Date()`. + * Updated when an item is added, removed, or renamed. + */ + mtime?: Date; + /** + * The time of directory creation. Defaults to `new Date()`. + */ + birthtime?: Date; + /** + * Directory contents. Members will generate additional files, + * directories, or symlinks. + */ + items?: DirectoryItems; + } + + interface SymlinkOptions { + /** Path to the source (required). */ + path: string; + /** Symlink mode (permission and sticky bits). Defaults to `0666`. */ + mode?: number; + /** The user id. Defaults to `process.getuid()`. */ + uid?: number; + /** The group id. Defaults to `process.getgid()`. */ + gid?: number; + /** The last symlink access time. Defaults to `new Date()`. */ + atime?: Date; + /** The last symlink change time. Defaults to `new Date()`. */ + ctime?: Date; + /** The last symlink modification time. Defaults to `new Date()`. */ + mtime?: Date; + /** The time of symlink creation. Defaults to `new Date()`. */ + birthtime?: Date; + } + + function getPathParts(filepath: string): string[]; +} diff --git a/types/mock-fs/lib/index.d.ts b/types/mock-fs/lib/index.d.ts new file mode 100644 index 0000000000..d050830e5e --- /dev/null +++ b/types/mock-fs/lib/index.d.ts @@ -0,0 +1,3 @@ +import mock = require('../index'); + +export = mock; diff --git a/types/mock-fs/lib/item.d.ts b/types/mock-fs/lib/item.d.ts new file mode 100644 index 0000000000..d82fd24d87 --- /dev/null +++ b/types/mock-fs/lib/item.d.ts @@ -0,0 +1,65 @@ +export = Item; + +/** + * A filesystem item. + */ +declare class Item { + /** Returns whether the current user has read permission. */ + canRead(): boolean; + /** Returns whether the current user has write permission. */ + canWrite(): boolean; + /** Returns whether the current user has execute permission. */ + canExecute(): boolean; + /** Get access time. */ + getATime(): Date; + /** Set access time. */ + setATime(atime: Date): void; + /** Get change time. */ + getCTime(): Date; + /** Set change time. */ + setCTime(ctime: Date): void; + /** Get birth time. */ + getBirthtime(): Date; + /** Set birth time. */ + setBirthtime(birthtime: Date): void; + /** Get modification time. */ + getMTime(): Date; + /** Set modification time. */ + setMTime(mtime: Date): void; + /** Get mode (permission only, e.g 0666). */ + getMode(): number; + /** Set mode (permission only, e.g 0666). */ + setMode(mode: number): void; + /** Get user id. */ + getUid(): number; + /** Set user id. */ + setUid(uid: number): void; + /** Get group id. */ + getGid(): number; + /** Set group id. */ + setGid(gid: number): void; + /** Get item stats. */ + getStats(): Item.Stats; +} + +declare namespace Item { + interface Stats { + dev: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + blksize: number; + ino: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } + + interface ExtendedStats extends Stats { + mode: number; + size: number; + blocks: number; + } +} diff --git a/types/mock-fs/lib/symlink.d.ts b/types/mock-fs/lib/symlink.d.ts new file mode 100644 index 0000000000..27670cc6ed --- /dev/null +++ b/types/mock-fs/lib/symlink.d.ts @@ -0,0 +1,12 @@ +import Item = require('./item'); + +export = SymbolicLink; + +declare class SymbolicLink extends Item { + /** Sets the path (relative) to the source. */ + setPath(pathname: string): void; + /** Get the path (relative) to the source. */ + getPath(): string; + /** Get symbolic link stats. */ + getStats(): Item.ExtendedStats; +} diff --git a/types/mock-fs/mock-fs-tests.ts b/types/mock-fs/mock-fs-tests.ts index 83522e1a66..b6273f0907 100644 --- a/types/mock-fs/mock-fs-tests.ts +++ b/types/mock-fs/mock-fs-tests.ts @@ -1,85 +1,231 @@ +import mock = require('mock-fs'); -var mock = require('mock-fs'); +import FileSystem = require('mock-fs/lib/filesystem'); +import Item = require('mock-fs/lib/item'); +import File = require('mock-fs/lib/file'); +import Directory = require('mock-fs/lib/directory'); +import SymbolicLink = require('mock-fs/lib/symlink'); -function a() { - mock({ - 'path/to/fake/dir': { - 'some-file.txt': 'file content here', - 'empty-dir': {/** empty directory */} - }, - 'path/to/some.png': new Buffer([8, 6, 7, 5, 3, 0, 9]), - 'some/other/path': {/** another empty directory */} - }); +// Allow empty call. +mock(); - // after a test runs - mock.restore(); -} - -function b() { - mock({ - 'path/to/file.txt': 'file content here' - }); -} - -function c() { - mock({ - foo: mock.file({ - content: 'file content here', - ctime: new Date(1), - mtime: new Date(1) - }) - }); -} - -function d() { - // note that this could also be written as - // mock({'path/to/dir': { /** config */ }}) - mock({ - path: { - to: { - dir: { - file1: 'text content', - file2: new Buffer([1, 2, 3, 4]) - } - } - } - }); -} - -function e() { - mock({ - 'some/dir': mock.directory({ - mode: parseInt("0755", 8), - items: { - file1: 'file one content', - file2: new Buffer([8, 6, 7, 5, 3, 0, 9]) - } - }) - }); -} - -function f() { - mock({ - 'some/dir': { - 'regular-file': 'file contents', - 'a-symlink': mock.symlink({ - path: 'regular-file' - }) - } - }); -} - -var mockedFS = mock.fs({ - '/file': 'blah' -}); - -if (mockedFS.readFileSync('/file', { encoding: 'utf8' }) === 'blah') { - console.log('woo'); -} +// Allow empty object. +mock({}); mock({ - 'path/to/file.txt': 'file content here' -}, { - createTmp: true, - createCwd: false + 'path/to/fake/dir': { + 'some-file.txt': 'file content here', + 'empty-dir': { + /** empty directory */ + }, + }, + 'path/to/some.png': Buffer.from([8, 6, 7, 5, 3, 0, 9]), + 'some/other/path': { + /** another empty directory */ + }, }); + +mock({ + 'path/to/file.txt': 'file content here', +}); + +mock({ + foo: mock.file({ + content: 'file content here', + ctime: new Date(1), + mtime: new Date(1), + }), +}); + +// note that this could also be written as +// mock({'path/to/dir': { /** config */ }}) +mock({ + path: { + to: { + dir: { + file1: 'text content', + file2: Buffer.from([1, 2, 3, 4]), + }, + }, + }, +}); + +mock({ + 'some/dir': mock.directory({ + mode: parseInt('0755', 8), + items: { + file1: 'file one content', + file2: Buffer.from([8, 6, 7, 5, 3, 0, 9]), + }, + }), +}); + +mock({ + 'some/dir': { + 'regular-file': 'file contents', + 'a-symlink': mock.symlink({ + path: 'regular-file', + }), + }, +}); + +mock( + { + 'path/to/file.txt': 'file content here', + }, + { + createTmp: true, + createCwd: false, + }, +); + +// Combined case to check nesting. +mock( + { + 'path/to/fake/dir': { + 'some-file.txt': 'file content here', + 'some-other-file.txt': mock.file({ + content: 'apricot banana guava', + mode: 0o766, + }), + 'my-file.txt': mock.symlink({ + path: './some-file.txt', + }), + 'empty-dir': { + /** empty directory */ + }, + }, + 'path/to/some.png': Buffer.from([8, 6, 7, 5, 3, 0, 9]), + 'some/other/path': { + /** another empty directory */ + }, + dir: mock.directory({ + mode: parseInt('0755', 8), + items: { + 'diary.txt': mock.symlink({ + path: 'diary-2019.txt', + }), + 'diary-2019.txt': 'Sunny Day in April', + }, + }), + }, + { + createTmp: true, + createCwd: false, + }, +); + +// $ExpectType string[] +FileSystem.getPathParts('path/to/some/file.txt'); + +const item = new Item(); + +function checkItem(item: Item) { + // $ExpectType boolean + item.canExecute(); + // $ExpectType boolean + item.canRead(); + // $ExpectType boolean + item.canWrite(); + + item.setATime(new Date()); + // $ExpectType Date + item.getATime(); + + item.setBirthtime(new Date()); + // $ExpectType Date + item.getBirthtime(); + + item.setCTime(new Date()); + // $ExpectType Date + item.getCTime(); + + item.setMTime(new Date()); + // $ExpectType Date + item.getMTime(); + + item.setATime(new Date()); + // $ExpectType Date + item.getATime(); + + item.setMode(0o777); + // $ExpectType number + item.getMode(); + + item.setGid(2000); + // $ExpectType number + item.getGid(); + + item.setUid(1000); + // $ExpectType number + item.getUid(); + + // $ExpectType Stats + item.getStats(); +} + +interface ExtendedItem extends Item { + getStats(): Item.ExtendedStats; +} + +function checkExtendedStats(item: ExtendedItem) { + // $ExpectType ExtendedStats + item.getStats(); + + checkItem(item); +} + +function checkFile(file: File) { + file.setContent('ob la di, ob la da'); + + // $ExpectType Buffer + file.getContent(); + + checkExtendedStats(file); +} + +function checkDirectory(dir: Directory) { + // $ExpectType File + dir.addItem('foo', new File()); + // $ExpectType Directory + dir.addItem('bar', new Directory()); + // $ExpectType SymbolicLink + dir.addItem('baz', new SymbolicLink()); + + // $ExpectType Item | null + dir.getItem('foo'); + + // $ExpectType Item + dir.removeItem('baz'); + + // $ExpectType string[] + dir.list(); + + checkExtendedStats(dir); +} + +function checkSymlink(symlink: SymbolicLink) { + symlink.setPath('./abc'); + + // $ExpectType string + symlink.getPath(); + + checkExtendedStats(symlink); +} + +checkFile(mock.file({})()); +checkFile(new File()); + +checkDirectory(mock.directory({})()); +checkDirectory(new Directory()); + +checkSymlink(mock.symlink({ path: 'blah' })()); +checkSymlink( + (() => { + const symlink = new SymbolicLink(); + symlink.setPath('blaj'); + return symlink; + })(), +); + +mock.restore(); diff --git a/types/mock-fs/tsconfig.json b/types/mock-fs/tsconfig.json index b460b4d1d1..49f2158c23 100644 --- a/types/mock-fs/tsconfig.json +++ b/types/mock-fs/tsconfig.json @@ -6,8 +6,8 @@ ], "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, "strictFunctionTypes": true, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" @@ -18,6 +18,12 @@ }, "files": [ "index.d.ts", - "mock-fs-tests.ts" + "mock-fs-tests.ts", + "lib/directory.d.ts", + "lib/file.d.ts", + "lib/filesystem.d.ts", + "lib/index.d.ts", + "lib/item.d.ts", + "lib/symlink.d.ts" ] -} \ No newline at end of file +} diff --git a/types/mock-fs/tslint.json b/types/mock-fs/tslint.json index 3d59f55fda..3db14f85ea 100644 --- a/types/mock-fs/tslint.json +++ b/types/mock-fs/tslint.json @@ -1,80 +1 @@ -{ - "extends": "dtslint/dt.json", - "rules": { - "adjacent-overload-signatures": false, - "array-type": false, - "arrow-return-shorthand": false, - "ban-types": false, - "callable-types": false, - "comment-format": false, - "dt-header": false, - "npm-naming": false, - "eofline": false, - "export-just-namespace": false, - "import-spacing": false, - "interface-name": false, - "interface-over-type-literal": false, - "jsdoc-format": false, - "max-line-length": false, - "member-access": false, - "new-parens": false, - "no-any-union": false, - "no-boolean-literal-compare": false, - "no-conditional-assignment": false, - "no-consecutive-blank-lines": false, - "no-construct": false, - "no-declare-current-package": false, - "no-duplicate-imports": false, - "no-duplicate-variable": false, - "no-empty-interface": false, - "no-for-in-array": false, - "no-inferrable-types": false, - "no-internal-module": false, - "no-irregular-whitespace": false, - "no-mergeable-namespace": false, - "no-misused-new": false, - "no-namespace": false, - "no-object-literal-type-assertion": false, - "no-padding": false, - "no-redundant-jsdoc": false, - "no-redundant-jsdoc-2": false, - "no-redundant-undefined": false, - "no-reference-import": false, - "no-relative-import-in-test": false, - "no-self-import": false, - "no-single-declare-module": false, - "no-string-throw": false, - "no-unnecessary-callback-wrapper": false, - "no-unnecessary-class": false, - "no-unnecessary-generics": false, - "no-unnecessary-qualifier": false, - "no-unnecessary-type-assertion": false, - "no-useless-files": false, - "no-var-keyword": false, - "no-var-requires": false, - "no-void-expression": false, - "no-trailing-whitespace": false, - "object-literal-key-quotes": false, - "object-literal-shorthand": false, - "one-line": false, - "one-variable-per-declaration": false, - "only-arrow-functions": false, - "prefer-conditional-expression": false, - "prefer-const": false, - "prefer-declare-function": false, - "prefer-for-of": false, - "prefer-method-signature": false, - "prefer-template": false, - "radix": false, - "semicolon": false, - "space-before-function-paren": false, - "space-within-parens": false, - "strict-export-declare-modifiers": false, - "trim-file": false, - "triple-equals": false, - "typedef-whitespace": false, - "unified-signatures": false, - "void-return": false, - "whitespace": false - } -} +{ "extends": "dtslint/dt.json" }