-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathsource-checkers.ts
97 lines (87 loc) · 2.95 KB
/
source-checkers.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
87
88
89
90
91
92
93
94
95
96
97
import { URL } from 'url' // tslint:disable-line no-circular-imports
import { Readable } from 'stream'
import { FileURI, ObjectSource, PlainSource, Source, TupleSource } from '../_types'
/**
* Check if argument is String
*/
export const isString = (x: Source | undefined | null): x is string => typeof x === 'string'
/**
* Check if argument is Buffer
*/
export const isBuffer = (x: Source | undefined | null): x is Buffer =>
x != null && x instanceof Buffer
/**
* Check if argument is Stream
*/
export const isStream = (x: Source | undefined | null): x is NodeJS.ReadableStream =>
x != null && x instanceof Readable
/**
* Check if argument is URL
*/
export const isURL = (x: Source | undefined | null): x is URL => x != null && x instanceof URL
/**
* Check if argument is uri to local file
* https://en.wikipedia.org/wiki/File_URI_scheme
*/
export const isFileUri = (x: Source | undefined | null): x is FileURI =>
isString(x) && x.startsWith('file:')
/**
* Check if argument is PlainSource - either String, Stream or Buffer
*/
export const isPlain = (x: Source | undefined | null): x is PlainSource =>
isString(x) || isStream(x) || isBuffer(x) // || isFileUri(x) <- redundant check
/**
* Check if argument is TupleSource - two-values array, like [key, PlainSource]
*/
export const isTuple = (x: object | undefined | null): x is TupleSource =>
Array.isArray(x) && x.length === 2 && typeof x[0] === 'string' && isPlain(x[1])
/**
* Check if argument is ObjectSource, with PlainSources inside
*/
export const isObject = (x: Source | undefined | null): x is ObjectSource => {
if (
x == null ||
typeof x !== 'object' ||
Array.isArray(x) ||
typeof x[Symbol.iterator] === 'function' ||
x instanceof URL
) {
return false
}
for (const key in x) {
if (x.hasOwnProperty(key) && !isPlain(x[key])) return false
}
return true
}
/**
* Check if argument is Iterable over PlainSource or TupleSource
*/
export const isIterable = (
x: Source | undefined | null
): x is Iterable<PlainSource | TupleSource | ObjectSource> => {
if (x == null || typeof x === 'string') return false
if (typeof x[Symbol.iterator] === 'function') {
for (const src of x as Iterable<Source | undefined | null>) {
if (src == null) return false
if (!isPlain(src) && !isTuple(src) && !isObject(src)) return false
}
return true
}
return false
}
/**
* Check, if given argument is simple string, and presumably is is just file name
*/
const filenameRE = /.+\..+/
const filenameReservedRE = /[<>:"/\\|?*\u0000-\u001F]/g
const windowsReservedNameRE = /^(con|prn|aux|nul|com\d|lpt\d)$/i
const MAX_FILE_NAME_LENGTH = 255
export const isFileName = (x: Source | undefined | null) =>
isString(x) &&
x.length <= MAX_FILE_NAME_LENGTH &&
x !== '.' &&
x !== '..' &&
!x.startsWith('file:') && // in ideal world there should be `!isFileUri(x)`, but TypeScript sucks here
!filenameReservedRE.test(x) &&
!windowsReservedNameRE.test(x) &&
filenameRE.test(x)