Skip to content

Commit d2369f7

Browse files
feat: add file system reader
1 parent 2f899b4 commit d2369f7

File tree

5 files changed

+119
-15
lines changed

5 files changed

+119
-15
lines changed

src/lib/library/library.factory.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
url,
1414
} from '@angular-devkit/schematics';
1515
import { parse } from 'jsonc-parser';
16-
import { readFileSync } from 'fs';
1716
import { normalizeToKebabOrSnakeCase } from '../../utils/formatting';
1817
import {
1918
DEFAULT_LANGUAGE,
@@ -22,6 +21,7 @@ import {
2221
PROJECT_TYPE,
2322
} from '../defaults';
2423
import { LibraryOptions } from './library.schema';
24+
import { FileSystemReader } from '../readers';
2525

2626
type UpdateJsonFn<T> = (obj: T) => T | void;
2727
interface TsConfigPartialType {
@@ -45,23 +45,20 @@ export function main(options: LibraryOptions): Rule {
4545
}
4646

4747
function getDefaultLibraryPrefix(defaultLibraryPrefix = '@app') {
48+
const fileSystemReader = new FileSystemReader(process.cwd())
49+
const content: string | undefined = fileSystemReader.readSyncAnyOf([
50+
'nest-cli.json',
51+
'.nestcli.json',
52+
'.nest-cli.json',
53+
'nest.json',
54+
]);
55+
4856
try {
49-
const nestCliJson = JSON.parse(
50-
readFileSync('./nest-cli.json', 'utf-8'),
51-
);
52-
if (nestCliJson.hasOwnProperty('defaultLibraryPrefix')) {
53-
return nestCliJson['defaultLibraryPrefix'];
57+
const nestJson = JSON.parse(content || '{}');
58+
if (nestJson.hasOwnProperty('defaultLibraryPrefix')) {
59+
return nestJson['defaultLibraryPrefix'];
5460
}
5561
} catch (e) {
56-
try {
57-
const nestJson = JSON.parse(
58-
readFileSync('./nest.json', 'utf-8'),
59-
);
60-
if (nestJson.hasOwnProperty('defaultLibraryPrefix')) {
61-
return nestJson['defaultLibraryPrefix'];
62-
}
63-
} catch (e) {
64-
}
6562
}
6663

6764
return defaultLibraryPrefix;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as fs from 'fs';
2+
import * as path from 'path';
3+
import { Reader } from './reader';
4+
5+
export class FileSystemReader implements Reader {
6+
constructor(private readonly directory: string) {}
7+
8+
public list(): Promise<string[]> {
9+
return fs.promises.readdir(this.directory);
10+
}
11+
12+
public read(name: string): Promise<string> {
13+
return fs.promises.readFile(path.join(this.directory, name), 'utf8');
14+
}
15+
16+
public readSync(name: string): string {
17+
return fs.readFileSync(path.join(this.directory, name), 'utf8');
18+
}
19+
20+
public async readAnyOf(filenames: string[]): Promise<string | undefined> {
21+
try {
22+
for (const file of filenames) {
23+
return await this.read(file);
24+
}
25+
} catch (err) {
26+
return filenames.length > 0
27+
? await this.readAnyOf(filenames.slice(1, filenames.length))
28+
: undefined;
29+
}
30+
}
31+
32+
public readSyncAnyOf(filenames: string[]): string | undefined {
33+
try {
34+
for (const file of filenames) {
35+
return this.readSync(file);
36+
}
37+
} catch (err) {
38+
return filenames.length > 0
39+
? this.readSyncAnyOf(filenames.slice(1, filenames.length))
40+
: undefined;
41+
}
42+
}
43+
}

src/lib/readers/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './reader';
2+
export * from './file-system.reader';

src/lib/readers/reader.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface Reader {
2+
list(): string[] | Promise<string[]>;
3+
read(name: string): string | Promise<string>;
4+
readSync(name: string): string;
5+
readAnyOf(filenames: string[]): string | Promise<string | undefined>;
6+
readSyncAnyOf(filenames: string[]): string | undefined;
7+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as fs from 'fs';
2+
import { FileSystemReader, Reader } from '../../../src/lib/readers';
3+
4+
jest.mock('fs', () => ({
5+
readFileSync: jest.fn().mockReturnValue('content'),
6+
promises: {
7+
readdir: jest.fn().mockResolvedValue([]),
8+
readFile: jest.fn().mockResolvedValue('content'),
9+
},
10+
}));
11+
12+
const dir: string = process.cwd();
13+
const reader: Reader = new FileSystemReader(dir);
14+
15+
describe('File System Reader', () => {
16+
afterAll(() => {
17+
jest.clearAllMocks();
18+
});
19+
it('should use fs.promises.readdir when list', async () => {
20+
await reader.list();
21+
expect(fs.promises.readdir).toHaveBeenCalled();
22+
});
23+
it('should use fs.promises.readFile when read', async () => {
24+
await reader.read('filename');
25+
expect(fs.promises.readFile).toHaveBeenCalled();
26+
});
27+
28+
describe('readAnyOf tests', () => {
29+
it('should call readFile when running readAnyOf fn', async () => {
30+
const filenames: string[] = ['file1', 'file2', 'file3'];
31+
await reader.readAnyOf(filenames);
32+
33+
expect(fs.promises.readFile).toHaveBeenCalled();
34+
});
35+
36+
it('should return undefined when no file is passed', async () => {
37+
const content = await reader.readAnyOf([]);
38+
expect(content).toEqual(undefined);
39+
});
40+
});
41+
42+
describe('readSyncAnyOf tests', () => {
43+
it('should call readFileSync when running readSyncAnyOf fn', async () => {
44+
const filenames: string[] = ['file1', 'file2', 'file3'];
45+
reader.readSyncAnyOf(filenames);
46+
47+
expect(fs.readFileSync).toHaveBeenCalled();
48+
});
49+
50+
it('should return undefined when no file is passed', async () => {
51+
const content = reader.readSyncAnyOf([]);
52+
expect(content).toEqual(undefined);
53+
});
54+
});
55+
});

0 commit comments

Comments
 (0)