-
Notifications
You must be signed in to change notification settings - Fork 0
/
_private.js
156 lines (145 loc) · 5.92 KB
/
_private.js
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// * # private for the developer, public to the author *
// static variables (IDs) Never change by concumer
const generateErr = {
id: Symbol(),
process(error) {
return error
},
}
const throwErr = {
id: Symbol(),
process(error) {
throw error
},
}
// static variables (pre-defined messages) may change by concumer, these are the pre-defined templates
const errorMessages = {
function: '{$} is not a function, typeof given: {!}',
asyncfunction: '{$} is not an async function, typeof given: {!}',
string: '{$} is not a string, typeof given: {!}',
number: '{$} is not a number, typeof given: {!}',
object: '{$} is not an object, typeof given: {!}',
null: '{$} is not a null type, typeof given: {!}',
undefined: '{$} is not an undefined, typeof given: {!}',
symbol: '{$} is not a symbol, typeof given: {!}',
map: '{$} is not a map type, typeof given: {!}',
date: '{$} is not a date, typeof given: {!}',
array: '{$} is not an array, typeof given: {!}',
AsyncOrSyncFunction:
'{$} is not an Async nor Sync Function , typeof given: {!}',
defaultTemplate: '{$} is not a valid type , typeof given: {!}',
}
const errorMessagesResiption = (arg, requiredType, optionalMessage) => {
// this function returns the error message based on particular calculations
const typeStr = checkType(arg)
const argStr = JSON.stringify(arg)
let template
if (optionalMessage)
template = optionalMessage.replace(/{\#\}/g, errorMessages[requiredType])
else template = errorMessages[requiredType]
const mapObj = {
'{$}': argStr,
'{!}': typeStr,
}
if (!template) template = errorMessages['defaultTemplate']
template = template.replace(/\{\$\}|\{\!\}/g, (match) => mapObj[match])
return template
}
const checkType = (o) => {
return Object.prototype.toString
.call(o)
.replace(/\[|object\s|\]/g, '')
.toLowerCase()
}
const handleErrorById = (id, error) => {
switch (id) {
case generateErr.id:
return generateErr.process(error)
case throwErr.id:
throwErr.process(error)
break
default:
throw new Error(
'Internal Error in checkTypes/_private.js, ID is not recognizable'
)
}
}
const checkOneByOne = (arr, typeStr, mixinAlias) => {
// arr is the input by the user to check for, it could also hold generateErr || throwErr by the develoepr.
// typeStr could be a string or an array of strings, if a string, this is going to be used as the key for the $errorMessages object, this argument is given by the author.
// mixinAlias is a string, if provided, it will be used as the key for the $errorMessages object. this field is required only if typeStr is an array, since all $errorMessages keys are strings, this argument is given by the author.
let mistake
let handleErr = {
status: false,
id: 0,
idObject: {},
}
// true: there was a mistake
let status
if (arr.length === 0 && typeStr !== 'undefined') {
// when the array length is zero and the developer is not checking for undefined
status = true
} else
status = arr.some((value) => {
// arr.some by default is going to return false if the array is empty, this is only the case that will happen if the developer checking for undefined because of the if statement above me
// because of arr.some, once an item within the argument list (arr) found incorrect based on the developer's choise, all of the validation will fail on the first incorrect input
// TODO: maybe in future versions, add an option to the developer to choose if he wants the entire validation to fail on the first incorrect input or not
if (
checkType(value) == 'object' &&
value._identifier &&
arr.length === 1 &&
typeStr !== 'undefined'
) {
// the current item is a hashable object (has _identifier propery inside of it), and the argument list only holds one item, and the developer is not checking for undefined
handleErr.status = true
handleErr.id = value._identifier
handleErr.idObject = value
mistake = undefined
return true
}
if (checkType(value) == 'object' && value._identifier) {
// the current item is an object, and it's a hash injected object (has _identifier propery inside of it)
handleErr.status = true
handleErr.id = value._identifier
handleErr.idObject = value
return false
}
if (!typeStr.includes(checkType(value))) {
// if the current item doesn't match the developer's choise (typeStr)
mistake = value
return true
}
// if non of the above checkings was the case for the current item, then it seems like there is no mistake, with it, continue looping if there are any items left to check
return false
})
// status === true: there was a mistake
if (status) {
let error = new Error()
error = Object.assign(error, handleErr.idObject)
error.message = errorMessagesResiption(
mistake,
mixinAlias || typeStr, // if there is a mixinAlias, use mixinAlias instead of typeStr
error.message
)
if (handleErr.status) return handleErrorById(handleErr.id, error)
return false
}
// nothing is wrong, the user input matches the developer's choise
return true
}
const injectHash = (idType, obj = {}) => {
// injects the unique symbol into the developer's given obj
// idType is given by the author, it could be the throwErr or the generateErr unique symbol, this symbol is taken by the author from the $generateErr or the $throwError objects since they're exported publicly from this file
obj._identifier = idType
return obj
}
module.exports = {
injectHash,
checkType,
config: {
errorMessages,
},
checkOneByOne,
throwErr,
generateErr,
}