-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
DirectoryInput.ts
86 lines (71 loc) · 2.43 KB
/
DirectoryInput.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { FileInput } from './FileInput'
import nodePath from 'node:path'
import { readDir } from '../utils/fs'
import { Input, TrackOptions, getTrackOptions } from './Input'
export class DirectoryInput implements Input {
constructor(
private readonly path: string,
private readonly exerciseSlug: string,
private trackOptions = getTrackOptions()
) {}
public async files(n = 1, preferredExtension = 'js'): Promise<FileInput[]> {
const files = await readDir(this.path)
const candidates = findCandidates(
files,
n,
`${this.exerciseSlug}.${preferredExtension}`,
this.trackOptions
)
return candidates.map(
(candidate) =>
new FileInput(nodePath.join(this.path, candidate), this.trackOptions)
)
}
public async read(n = 1, preferredExtension = 'js'): Promise<string[]> {
const files = await this.files(n, preferredExtension)
return await Promise.all(
files.map(async (file): Promise<string> => {
const [source] = await file.read()
return source
})
)
}
public set fileExtensions(next: RegExp) {
this.trackOptions = { ...this.trackOptions, fileExtensions: next }
}
public set testFilePattern(next: RegExp) {
this.trackOptions = { ...this.trackOptions, testFilePattern: next }
}
public set configurationFilePattern(next: RegExp) {
this.trackOptions = { ...this.trackOptions, configurationFilePattern: next }
}
}
/**
* Given a list of files, finds up to n files that are not test files and have
* an extension that will probably work with the estree analyzer.
*
* @param files the file candidates
* @param n the number of files it should return
* @param preferredNames the names of the files it prefers
*/
function findCandidates(
files: string[],
n: number,
preferredName: string,
{ fileExtensions, testFilePattern, configurationFilePattern }: TrackOptions
): string[] {
const candidates = files
.filter((file): boolean => fileExtensions.test(file))
.filter((file): boolean => !testFilePattern.test(file))
.filter((file): boolean => !configurationFilePattern.test(file))
const preferredMatches = candidates.filter((file): boolean =>
preferredName.includes(file)
)
const allMatches =
preferredMatches.length >= n
? preferredMatches
: preferredMatches.concat(
candidates.filter((file): boolean => !preferredMatches.includes(file))
)
return allMatches.slice(0, n)
}