• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

igoramadas / setmeup / 4897215279

pending completion
4897215279

push

github

Igor Ramadas
Version 1.9.0.

210 of 233 branches covered (90.13%)

Branch coverage included in aggregate %.

367 of 375 relevant lines covered (97.87%)

189.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.57
/src/utils.ts
1
// SetMeUp: utils.ts
2

3
import {cryptoMethod, CryptoOptions} from "./cryptohelper"
1✔
4
import fs from "fs"
1✔
5
import path from "path"
1✔
6

7
/** @hidden */
8
let logger = null
1✔
9

10
/**
11
 * Finds the correct path to the file looking first on the (optional) base path
12
 * then the current or running directory, finally the root directory.
13
 * Returns null if file is not found.
14
 * @param filename The filename to be searched
15
 * @param basepath Optional, basepath where to look for the file.
16
 * @returns The full path to the file if one was found, or null if not found.
17
 * @protected
18
 */
19
export function getFilePath(filename: string, basepath?: string): string {
1✔
20
    try {
52✔
21
        const originalFilename = filename.toString()
52✔
22
        let hasFile = false
51✔
23

24
        // A basepath was passed? Try there first.
25
        if (basepath) {
51✔
26
            filename = path.resolve(basepath, originalFilename)
1✔
27
            hasFile = fs.existsSync(filename)
1✔
28
            /* istanbul ignore else */
29
            if (hasFile) {
1✔
30
                return filename
1✔
31
            }
32
        }
33

34
        // Try running directory.
35
        filename = path.resolve(process.cwd(), originalFilename)
50✔
36
        hasFile = fs.existsSync(filename)
50✔
37
        /* istanbul ignore if */
38
        if (hasFile) {
50✔
39
            return filename
40
        }
41

42
        // Try application root path (CommonJS).
43
        // @ts-ignore
44
        if (require.main) {
12!
45
            // @ts-ignore
46
            filename = path.resolve(path.dirname(require.main.filename), originalFilename)
12✔
47
            hasFile = fs.existsSync(filename)
12✔
48
            /* istanbul ignore if */
49
            if (hasFile) {
12✔
50
                return filename
51
            }
52
        }
53

54
        // Last try.
55
        hasFile = fs.existsSync(filename)
12✔
56
        /* istanbul ignore if */
57
        if (hasFile) {
12✔
58
            return filename
59
        }
60
    } catch (ex) {
61
        if (logger) logger.error("SetMeUp.Utils.getFilePath", filename, ex)
1!
62
    }
63

64
    // Nothing found, so return null.
65
    return null
13✔
66
}
67

68
/**
69
 * Strip comments out of the JSON and returns it as a JSON object.
70
 * @param value The JSON string or object to be parsed.
71
 * @returns The parsed JSON object.
72
 * @protected
73
 */
74
export function parseJson(value: string | any) {
1✔
75
    const singleComment = 1
27✔
76
    const multiComment = 2
27✔
77
    let insideString = null
27✔
78
    let insideComment = null
27✔
79
    let offset = 0
27✔
80
    let ret = ""
27✔
81
    let strip = () => ""
27✔
82

83
    // Make sure value is a string!
84
    if (!isString(value)) {
27✔
85
        value = value.toString()
1✔
86
    }
87

88
    for (let i = 0; i < value.length; i++) {
27✔
89
        const currentChar = value[i]
9,070✔
90
        const nextChar = value[i + 1]
9,070✔
91

92
        if (!insideComment && currentChar === '"') {
9,070✔
93
            if (!(value[i - 1] === "\\" && value[i - 2] !== "\\")) {
649✔
94
                insideString = !insideString
648✔
95
            }
96
        }
97

98
        if (insideString) {
9,070✔
99
            continue
4,192✔
100
        }
101

102
        if (!insideComment && currentChar + nextChar === "//") {
4,878✔
103
            ret += value.slice(offset, i)
13✔
104
            offset = i
13✔
105
            insideComment = singleComment
13✔
106
            i++
13✔
107
        } /* istanbul ignore next */ else if (insideComment === singleComment && currentChar + nextChar === "\r\n") {
4,865!
108
            i++
×
109
            insideComment = false
×
110
            ret += strip()
×
111
            offset = i
×
112
            continue
×
113
        } else if (insideComment === singleComment && currentChar === "\n") {
4,865✔
114
            insideComment = false
13✔
115
            ret += strip()
13✔
116
            offset = i
13✔
117
        } else if (!insideComment && currentChar + nextChar === "/*") {
4,852✔
118
            ret += value.slice(offset, i)
4✔
119
            offset = i
4✔
120
            insideComment = multiComment
4✔
121
            i++
4✔
122
            continue
4✔
123
        } else if (insideComment === multiComment && currentChar + nextChar === "*/") {
4,848✔
124
            i++
3✔
125
            insideComment = false
3✔
126
            ret += strip()
3✔
127
            offset = i + 1
3✔
128
            continue
3✔
129
        }
130
    }
131

132
    let parsed = ret + (insideComment ? strip() : value.substr(offset))
27✔
133
    return JSON.parse(parsed)
27✔
134
}
135

136
/**
137
 * Load the specified file and returns JSON object.
138
 * @param filename Path to the file that should be loaded.
139
 * @param cryptoOptions In case file is encrypted, pass the crypto key and IV options.
140
 * @returns The parsed JSON object.
141
 * @protected
142
 */
143
export function loadJson(filename: string, cryptoOptions?: CryptoOptions | boolean): any {
1✔
144
    let result = null
35✔
145

146
    // Try loading the anyhow module.
147
    if (!logger) {
35✔
148
        try {
1✔
149
            logger = require("anyhow")
1✔
150
        } catch (ex) {
151
            // Anyhow module not found
152
        }
153
    }
154

155
    // Found file? Load it. Try using UTF8 first, if failed, use ASCII.
156
    if (filename != null) {
35✔
157
        const encUtf8 = {encoding: "utf8"} as any
27✔
158
        const encAscii = {encoding: "ascii"} as any
27✔
159

160
        // Try parsing the file with UTF8 first, if fails, try ASCII.
161
        try {
27✔
162
            result = fs.readFileSync(filename, encUtf8)
27✔
163
            result = parseJson(result)
24✔
164
        } catch (ex) {
165
            /* istanbul ignore next */
166
            result = fs.readFileSync(filename, encAscii)
167
            /* istanbul ignore next */
168
            result = parseJson(result)
169
        }
170
    }
171

172
    // Encrypted file and passed encryption options?
173
    if (result && result.encrypted) {
32✔
174
        // Ignore if crypto options passed as false.
175
        if (cryptoOptions === false) {
8✔
176
            return result
6✔
177
        }
178

179
        /* istanbul ignore else */
180
        if (cryptoOptions != null) {
2✔
181
            // If crypto options are passed as true, clear its value to use the defaults.
182
            if (cryptoOptions === true) {
2✔
183
                cryptoOptions = null
1✔
184
            }
185

186
            if (logger) logger.debug("SetMeUp.Utils.loadJson", filename, "Will be decrypted")
2!
187

188
            result = cryptoMethod("decrypt", filename, cryptoOptions as CryptoOptions)
2✔
189
        }
190
    }
191

192
    return result
26✔
193
}
194

195
/**
196
 * Extends the target object with properties from the source.
197
 * @param source The source object.
198
 * @param target The target object.
199
 * @param overwrite If false it won't set properties that are already defined, default is true.
200
 * @protected
201
 */
202
export function extend(source: any, target: any, overwrite: boolean): void {
1✔
203
    if (overwrite == null || typeof overwrite == "undefined") {
78!
204
        overwrite = true
×
205
    }
206

207
    // Iterade object properties (deep).
208
    for (let prop in source) {
78✔
209
        const value = source[prop]
224✔
210
        if (value && value.constructor === Object) {
224✔
211
            if (target[prop] == null) {
48✔
212
                target[prop] = {}
28✔
213
            }
214
            extend(source[prop], target[prop], overwrite)
48✔
215
        } else if (overwrite || target[prop] == null) {
176✔
216
            target[prop] = source[prop]
175✔
217
        }
218
    }
219
}
220

221
/**
222
 * Get the passed object's tag.
223
 * @param value Object or value.
224
 */
225
export const getTag = (value) => {
1✔
226
    const toString = Object.prototype.toString
1✔
227

228
    if (value == null) {
1!
229
        return value === undefined ? "[object Undefined]" : "[object Null]"
×
230
    }
231

232
    return toString.call(value)
1✔
233
}
234

235
/**
236
 * Check if the passed value is an array.
237
 * @param value Object or value.
238
 */
239
export const isArray = (value): boolean => {
1✔
240
    return value && Array.isArray(value)
39✔
241
}
242

243
/**
244
 * Check if the passed value is a string.
245
 * @param value Object or value.
246
 */
247
export const isString = (value): boolean => {
1✔
248
    const type = typeof value
62✔
249
    return type === "string" || (type === "object" && value != null && !Array.isArray(value) && getTag(value) == "[object String]")
62✔
250
}
251

252
/**
253
 * Check if the passed value is a boolean.
254
 * @param value Object or value.
255
 */
256
export const isBoolean = (value): boolean => {
1✔
257
    return typeof value === "boolean"
69✔
258
}
259

260
/**
261
 * Check if the passed value is a number.
262
 * @param value Object or value.
263
 */
264
export const isNumber = (value): boolean => {
1✔
265
    return typeof value === "number" || typeof value === "bigint"
13✔
266
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2023 Coveralls, Inc