Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add "mode" for typescript reporter #429

Merged
merged 1 commit into from
May 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,16 @@ Options passed to the plugin constructor will overwrite options from the cosmico

Options for the TypeScript checker (`typescript` option object).

| Name | Type | Default value | Description |
| -------------------- | --------- | ------------------------------------------------------------------------- | ----------- |
| `enabled` | `boolean` | `true` | If `true`, it enables TypeScript checker. |
| `memoryLimit` | `number` | `2048` | Memory limit for the checker process in MB. If the process exits with the allocation failed error, try to increase this number. |
| `tsconfig` | `string` | `'tsconfig.json'` | Path to the `tsconfig.json` file (path relative to the `compiler.options.context` or absolute path) |
| `build` | `boolean` | `false` | The equivalent of the `--build` flag for the `tsc` command. To enable `incremental` mode, set it in the `tsconfig.json` file. _Note that this plugin doesn't emit any files even in the `build` mode._ |
| `compilerOptions` | `object` | `{ skipLibCheck: true, skipDefaultLibCheck: true }` | These options will overwrite compiler options from the `tsconfig.json` file. |
| `diagnosticsOptions` | `object` | `{ syntactic: false, semantic: true, declaration: false, global: false }` | Settings to select which diagnostics do we want to perform. |
| `extensions` | `object` | `{}` | See [TypeScript extensions options](#typescript-extensions-options). |
| Name | Type | Default value | Description |
| -------------------- | --------------------- | ------------------------------------------------------------------------- | ----------- |
| `enabled` | `boolean` | `true` | If `true`, it enables TypeScript checker. |
| `memoryLimit` | `number` | `2048` | Memory limit for the checker process in MB. If the process exits with the allocation failed error, try to increase this number. |
| `tsconfig` | `string` | `'tsconfig.json'` | Path to the `tsconfig.json` file (path relative to the `compiler.options.context` or absolute path) |
| `build` | `boolean` | `false` | If truthy, it's the equivalent of the `--build` flag for the `tsc` command. |
| `mode` | `'readonly'` or `'write-tsbuildinfo'` or `'write-references'` | `'readonly'` | If you use the `babel-loader`, it's recommended to use `write-references` mode to improve initial compilation time. If you use `ts-loader`, it's recommended to use `readonly` mode to not overwrite filed emitted by `ts-loader`. |
| `compilerOptions` | `object` | `{ skipLibCheck: true, skipDefaultLibCheck: true }` | These options will overwrite compiler options from the `tsconfig.json` file. |
| `diagnosticsOptions` | `object` | `{ syntactic: false, semantic: true, declaration: false, global: false }` | Settings to select which diagnostics do we want to perform. |
| `extensions` | `object` | `{}` | See [TypeScript extensions options](#typescript-extensions-options). |

#### TypeScript extensions options

Expand Down
5 changes: 5 additions & 0 deletions src/ForkTsCheckerWebpackPluginOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@
"type": "boolean",
"description": "The equivalent of the `--build` flag from the `tsc`."
},
"mode": {
"type": "string",
"enum": ["readonly", "write-tsbuildinfo", "write-references"],
"description": "`readonly` keeps all emitted files in memory, `write-tsbuildinfo` which writes only .tsbuildinfo files and `write-references` which writes both .tsbuildinfo and referenced projects output"
},
"incremental": {
"type": "boolean",
"description": "The equivalent of the `--incremental` flag from the `tsc`."
Expand Down
2 changes: 2 additions & 0 deletions src/typescript-reporter/TypeScriptReporterConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface TypeScriptReporterConfiguration {
memoryLimit: number;
tsconfig: string;
build: boolean;
mode: 'readonly' | 'write-tsbuildinfo' | 'write-references';
compilerOptions: Partial<ts.CompilerOptions>;
diagnosticOptions: TypeScriptDiagnosticsOptions;
extensions: {
Expand Down Expand Up @@ -53,6 +54,7 @@ function createTypeScriptReporterConfiguration(
enabled: options !== false,
memoryLimit: 2048,
build: false,
mode: 'readonly',
...(typeof options === 'object' ? options : {}),
tsconfig: tsconfig,
compilerOptions: compilerOptions,
Expand Down
1 change: 1 addition & 0 deletions src/typescript-reporter/TypeScriptReporterOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type TypeScriptReporterOptions =
memoryLimit?: number;
tsconfig?: string;
build?: boolean;
mode?: 'readonly' | 'write-tsbuildinfo' | 'write-references';
compilerOptions?: object;
diagnosticOptions?: Partial<TypeScriptDiagnosticsOptions>;
extensions?: {
Expand Down
26 changes: 26 additions & 0 deletions src/typescript-reporter/file-system/FileSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// eslint-disable-next-line node/no-unsupported-features/node-builtins
import { Dirent, Stats } from 'fs';

/**
* Interface to abstract file system implementation details.
*/
interface FileSystem {
// read
exists(path: string): boolean;
readFile(path: string, encoding?: string): string | undefined;
readDir(path: string): Dirent[];
readStats(path: string): Stats | undefined;
realPath(path: string): string;
normalizePath(path: string): string;

// write
writeFile(path: string, data: string): void;
deleteFile(path: string): void;
createDir(path: string): void;
updateTimes(path: string, atime: Date, mtime: Date): void;

// cache
clearCache(): void;
}

export { FileSystem };
145 changes: 145 additions & 0 deletions src/typescript-reporter/file-system/PassiveFileSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { dirname, normalize } from 'path';
import { fs as mem } from 'memfs';
import { FileSystem } from './FileSystem';
// eslint-disable-next-line node/no-unsupported-features/node-builtins
import { Dirent, Stats } from 'fs';

/**
* It's an implementation of FileSystem interface which reads from the real file system, but write to the in-memory file system.
*
* @param caseSensitive
* @param realFileSystem
*/
function createPassiveFileSystem(caseSensitive = false, realFileSystem: FileSystem): FileSystem {
function normalizePath(path: string): string {
return caseSensitive ? normalize(path) : normalize(path).toLowerCase();
}

function memExists(path: string): boolean {
return mem.existsSync(normalizePath(path));
}

function memReadStats(path: string): Stats | undefined {
return memExists(path) ? mem.statSync(normalizePath(path)) : undefined;
}

function memReadFile(path: string, encoding?: string): string | undefined {
if (memExists(path)) {
return mem
.readFileSync(normalizePath(path), { encoding: encoding as BufferEncoding })
.toString();
}
}

function memReadDir(path: string): Dirent[] {
if (memExists(path)) {
return mem.readdirSync(normalizePath(path), { withFileTypes: true }) as Dirent[];
}

return [];
}

function exists(path: string) {
return realFileSystem.exists(path) || memExists(path);
}

function readFile(path: string, encoding?: string) {
const fsStats = realFileSystem.readStats(path);
const memStats = memReadStats(path);

if (fsStats && memStats) {
return fsStats.mtimeMs > memStats.mtimeMs
? realFileSystem.readFile(path, encoding)
: memReadFile(path, encoding);
} else if (fsStats) {
return realFileSystem.readFile(path, encoding);
} else if (memStats) {
return memReadFile(path, encoding);
}
}

function readDir(path: string) {
const fsDirents = realFileSystem.readDir(path);
const memDirents = memReadDir(path);

// merge list of dirents from fs and mem
return fsDirents
.filter((fsDirent) => !memDirents.some((memDirent) => memDirent.name === fsDirent.name))
.concat(memDirents);
}

function readStats(path: string) {
const fsStats = realFileSystem.readStats(path);
const memStats = memReadStats(path);

if (fsStats && memStats) {
return fsStats.mtimeMs > memStats.mtimeMs ? fsStats : memStats;
} else if (fsStats) {
return fsStats;
} else if (memStats) {
return memStats;
}
}

function createDir(path: string) {
mem.mkdirSync(normalizePath(path), { recursive: true });
}

function writeFile(path: string, data: string) {
if (!memExists(dirname(path))) {
createDir(dirname(path));
}

mem.writeFileSync(normalizePath(path), data);
}

function deleteFile(path: string) {
if (memExists(path)) {
mem.unlinkSync(normalizePath(path));
}
}

function updateTimes(path: string, atime: Date, mtime: Date) {
if (memExists(path)) {
mem.utimesSync(normalizePath(path), atime, mtime);
}
}

return {
exists(path: string) {
return exists(realFileSystem.realPath(path));
},
readFile(path: string, encoding?: string) {
return readFile(realFileSystem.realPath(path), encoding);
},
readDir(path: string) {
return readDir(realFileSystem.realPath(path));
},
readStats(path: string) {
return readStats(realFileSystem.realPath(path));
},
realPath(path: string) {
return realFileSystem.realPath(path);
},
normalizePath(path: string) {
return normalizePath(path);
},
writeFile(path: string, data: string) {
writeFile(realFileSystem.realPath(path), data);
},
deleteFile(path: string) {
deleteFile(realFileSystem.realPath(path));
},
createDir(path: string) {
createDir(realFileSystem.realPath(path));
},
updateTimes(path: string, atime: Date, mtime: Date) {
updateTimes(realFileSystem.realPath(path), atime, mtime);
},
clearCache() {
realFileSystem.clearCache();
},
};
}

export { createPassiveFileSystem };
Loading