UNPKG

15.4 kBJavaScriptView Raw
1"use strict";
2/**
3 * This file is part of the @egodigital/egoose distribution.
4 * Copyright (c) e.GO Digital GmbH, Aachen, Germany (https://www.e-go-digital.com/)
5 *
6 * @egodigital/egoose is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation, version 3.
9 *
10 * @egodigital/egoose is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18function __export(m) {
19 for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
20}
21Object.defineProperty(exports, "__esModule", { value: true });
22const child_process_1 = require("child_process");
23const _ = require("lodash");
24const crypto = require("crypto");
25const fsExtra = require("fs-extra");
26const path = require("path");
27const moment = require("moment-timezone");
28const util = require("util");
29const UUID = require("uuid");
30const UUID_v5 = require("uuid/v5");
31const yargs = require("yargs-parser");
32/**
33 * Applies an object or value to a function.
34 *
35 * @param {TFunc} func The function to apply 'thisArg' to.
36 * @param {any} thisArg The object or value to apply to 'func'.
37 *
38 * @return {TFunc} The new function.
39 */
40function applyFuncFor(func, thisArg) {
41 return function () {
42 return func.apply(thisArg, arguments);
43 };
44}
45exports.applyFuncFor = applyFuncFor;
46/**
47 * Returns an input value as array.
48 *
49 * @param {T|T[]} val The input value.
50 * @param {boolean} [noEmpty] Remove values, which are (null) or (undefined).
51 *
52 * @return {T[]} The input value as array.
53 */
54function asArray(val, noEmpty = true) {
55 if (!Array.isArray(val)) {
56 val = [val];
57 }
58 return val.filter(x => {
59 if (noEmpty) {
60 return !_.isNil(x);
61 }
62 return true;
63 });
64}
65exports.asArray = asArray;
66/**
67 * Keeps sure that a value is a Moment instance (local timezone).
68 *
69 * @param {any} time The input value.
70 *
71 * @return {moment.Moment} The Moment instance.
72 */
73function asLocal(time) {
74 let result = asMoment(time);
75 if (!_.isNil(result)) {
76 if (result.isValid()) {
77 if (!result.isLocal()) {
78 result = result.local();
79 }
80 }
81 }
82 return result;
83}
84exports.asLocal = asLocal;
85/**
86 * Keeps sure that a value is a Moment instance.
87 *
88 * @param {any} val The input value.
89 *
90 * @return {moment.Moment} The Moment instance.
91 */
92function asMoment(val) {
93 if (_.isNil(val)) {
94 return val;
95 }
96 let result;
97 if (moment.isMoment(val)) {
98 result = val;
99 }
100 else if (moment.isDate(val)) {
101 result = moment(val);
102 }
103 else {
104 const TIME_STR = toStringSafe(val).trim();
105 if (/^([0-9]{1,})$/i.test(TIME_STR)) {
106 // UNIX timestamp
107 result = moment(parseInt(TIME_STR));
108 }
109 else {
110 result = moment(TIME_STR);
111 }
112 }
113 return result;
114}
115exports.asMoment = asMoment;
116/**
117 * Keeps sure that a value is a Moment instance (UTC timezone).
118 *
119 * @param {any} time The input value.
120 *
121 * @return {moment.Moment} The Moment instance.
122 */
123function asUTC(time) {
124 let result = asMoment(time);
125 if (!_.isNil(result)) {
126 if (result.isValid()) {
127 if (!result.isUTC()) {
128 result = result.utc();
129 }
130 }
131 }
132 return result;
133}
134exports.asUTC = asUTC;
135/**
136 * Clones an object / value.
137 *
138 * @param {T} obj The value to clone.
139 *
140 * @return {T} The cloned value.
141 */
142function cloneObj(obj) {
143 if (!obj) {
144 return obj;
145 }
146 return JSON.parse(JSON.stringify(obj));
147}
148exports.cloneObj = cloneObj;
149/**
150 * Compare to values for sorting.
151 *
152 * @param {any} x The "left" value.
153 * @param {any} y The "right" value.
154 *
155 * @return {number} The sort value.
156 */
157function compareValues(x, y) {
158 return compareValuesBy(x, y, i => i);
159}
160exports.compareValues = compareValues;
161/**
162 * Compare to values for sorting by using a selector.
163 *
164 * @param {any} x The "left" value.
165 * @param {any} y The "right" value.
166 * @param {Function} selector The selector.
167 *
168 * @return {number} The sort value.
169 */
170function compareValuesBy(x, y, selector) {
171 const VAL_X = selector(x);
172 const VAL_Y = selector(y);
173 if (VAL_X !== VAL_Y) {
174 if (VAL_X < VAL_Y) {
175 return -1;
176 }
177 if (VAL_X > VAL_Y) {
178 return 1;
179 }
180 }
181 return 0;
182}
183exports.compareValuesBy = compareValuesBy;
184/**
185 * Creates a simple 'completed' callback for a promise.
186 *
187 * @param {Function} resolve The 'succeeded' callback.
188 * @param {Function} reject The 'error' callback.
189 *
190 * @return {CompletedAction<TResult>} The created action.
191 */
192function createCompletedAction(resolve, reject) {
193 let completedInvoked = false;
194 return (err, result) => {
195 if (completedInvoked) {
196 return;
197 }
198 completedInvoked = true;
199 if (err) {
200 if (reject) {
201 reject(err);
202 }
203 }
204 else {
205 if (resolve) {
206 resolve(result);
207 }
208 }
209 };
210}
211exports.createCompletedAction = createCompletedAction;
212/**
213 * Promise version of `child_process.exec()` function.
214 *
215 * @param {string} command The command to execute.
216 *
217 * @return {Promise<ExecResult>} The promise with the result.
218 */
219async function exec(command) {
220 command = toStringSafe(command);
221 return new Promise((resolve, reject) => {
222 try {
223 child_process_1.exec(command, (err, stdout, stderr) => {
224 if (err) {
225 reject(err);
226 }
227 else {
228 resolve({
229 stderr: stderr,
230 stdout: stdout,
231 });
232 }
233 });
234 }
235 catch (e) {
236 reject(e);
237 }
238 });
239}
240exports.exec = exec;
241/**
242 * An async 'forEach'.
243 *
244 * @param {Enumerable.Sequence<T>} seq The sequence or array to iterate.
245 * @param {ForEachAsyncAction<T>} action The action to invoke.
246 */
247async function forEachAsync(seq, action) {
248 let i = -1;
249 for (const ITEM of seq) {
250 ++i;
251 await Promise.resolve(action(ITEM, i));
252 }
253}
254exports.forEachAsync = forEachAsync;
255/**
256 * Detects version information about the current app via Git (synchronous).
257 *
258 * @param {GetAppVersionOptions} [opts] Custom options.
259 *
260 * @return {AppVersion} Version information.
261 */
262function getAppVersionSync(opts) {
263 if (!opts) {
264 opts = {};
265 }
266 // working directory
267 let cwd = toStringSafe(opts.cwd);
268 if (isEmptyString(cwd)) {
269 cwd = process.cwd();
270 }
271 if (!path.isAbsolute(cwd)) {
272 cwd = path.join(process.cwd(), cwd);
273 }
274 cwd = path.resolve(cwd);
275 const VERSION = {};
276 // VERSION.date
277 try {
278 VERSION.date = asUTC(moment(child_process_1.execSync('git log -n1 --pretty=%cI HEAD', {
279 cwd: cwd,
280 }).toString('utf8')
281 .trim()));
282 }
283 catch {
284 VERSION.date = false;
285 }
286 // VERSION.hash
287 try {
288 VERSION.hash = normalizeString(child_process_1.execSync('git log --pretty="%H" -n1 HEAD', {
289 cwd: cwd,
290 }).toString('utf8'));
291 }
292 catch {
293 VERSION.hash = false;
294 }
295 // VERSION.code
296 try {
297 let buildNr = false;
298 // first check for 'BUILD_NR' file
299 const BUILD_NR_FILE = path.resolve(path.join(cwd, 'BUILD_NR'));
300 if (fsExtra.existsSync(BUILD_NR_FILE)) { // does exist?
301 if (fsExtra.statSync(BUILD_NR_FILE).isFile()) { // check if file
302 buildNr = parseInt(fsExtra.readFileSync(BUILD_NR_FILE, 'utf8')
303 .trim());
304 }
305 }
306 if (false === buildNr) {
307 // now try from 'BUILD_NR' env var
308 const BUILD_NR = toStringSafe(process.env.BUILD_NR)
309 .trim();
310 if ('' !== BUILD_NR) {
311 buildNr = parseInt(BUILD_NR);
312 }
313 }
314 if (false !== buildNr) {
315 VERSION.code = isNaN(buildNr) ?
316 false : buildNr;
317 }
318 }
319 catch (e) {
320 VERSION.code = false;
321 }
322 // VERSION.name
323 try {
324 const PACKAGE_JSON_FILE = path.resolve(path.join(cwd, 'package.json'));
325 if (fsExtra.existsSync(PACKAGE_JSON_FILE)) { // does exist?
326 if (fsExtra.statSync(PACKAGE_JSON_FILE).isFile()) { // check if file
327 const PACKAGE_JSON = JSON.parse(fsExtra.readFileSync(PACKAGE_JSON_FILE, 'utf8')
328 .trim());
329 if (PACKAGE_JSON && !isEmptyString(PACKAGE_JSON.version)) {
330 VERSION.name = toStringSafe(PACKAGE_JSON.version)
331 .trim();
332 }
333 }
334 }
335 }
336 catch (e) {
337 VERSION.name = false;
338 }
339 return VERSION;
340}
341exports.getAppVersionSync = getAppVersionSync;
342/**
343 * Alias of 'uuid()' function.
344 */
345function guid(version) {
346 return uuid.apply(null, arguments);
347}
348exports.guid = guid;
349/**
350 * Checks if the string representation of a value is an empty string or not.
351 *
352 * @param {any} val The value to check.
353 *
354 * @return {boolean} If empty string or not.
355 */
356function isEmptyString(val) {
357 return '' === toStringSafe(val)
358 .trim();
359}
360exports.isEmptyString = isEmptyString;
361/**
362 * Normalizes a value to a string, which is comparable.
363 *
364 * @param {any} val The value to normalize.
365 *
366 * @return {string} The normalized string.
367 */
368function normalizeString(val) {
369 return toStringSafe(val).toLowerCase()
370 .trim();
371}
372exports.normalizeString = normalizeString;
373/**
374 * Returns the current time.
375 *
376 * @param {string} [timezone] The custom timezone to use.
377 *
378 * @return {Moment.Moment} The current time.
379 */
380function now(timezone) {
381 timezone = toStringSafe(timezone).trim();
382 const NOW = moment();
383 return '' === timezone ? NOW
384 : NOW.tz(timezone);
385}
386exports.now = now;
387/**
388 * Parses a value as string of a command line input.
389 *
390 * @param {any} cmd The command line input.
391 *
392 * @return {ParsedCommandLine} The parsed data.
393 */
394function parseCommandLine(cmd) {
395 cmd = toStringSafe(cmd).trim();
396 const ARGS = yargs(cmd);
397 cmd = normalizeString(ARGS._[0]);
398 ARGS._ = ARGS._.filter((a, i) => i > 0).map((a) => {
399 if (_.isString(a)) {
400 if (a.startsWith('"') && a.endsWith('"')) {
401 a = a.substr(1, a.length - 2);
402 a = a.split('\\"')
403 .join('"');
404 }
405 }
406 return a;
407 });
408 if ('' === cmd) {
409 cmd = undefined;
410 }
411 return {
412 arguments: ARGS,
413 command: cmd,
414 };
415}
416exports.parseCommandLine = parseCommandLine;
417/**
418 * Generates a random string.
419 *
420 * @param {number} size The size of the result string.
421 * @param {string} [chars] The custom list of characters.
422 *
423 * @return {Promise<string>} The promise with the random string.
424 */
425async function randChars(size, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
426 return randCharsInner(await util.promisify(crypto.randomBytes)(size), chars);
427}
428exports.randChars = randChars;
429function randCharsInner(randBlob, chars) {
430 chars = toStringSafe(chars);
431 let str = '';
432 for (let i = 0; i < randBlob.length; i++) {
433 str += chars.substr(randBlob.readInt8(i) % chars.length, 1);
434 }
435 return str;
436}
437/**
438 * Generates a random string.
439 *
440 * @param {number} size The size of the result string.
441 * @param {string} [chars] The custom list of characters.
442 *
443 * @return {string} The random string.
444 */
445function randCharsSync(size, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
446 return randCharsInner(crypto.randomBytes(size), chars);
447}
448exports.randCharsSync = randCharsSync;
449/**
450 * Returns a value as "real" boolean.
451 *
452 * @param {any} val The input value.
453 * @param {boolean} [defaultValue] The value to return if 'val' is (null) or (undefined).
454 *
455 * @return {boolean} The output value.
456 */
457function toBooleanSafe(val, defaultValue = false) {
458 if (_.isBoolean(val)) {
459 return val;
460 }
461 if (_.isNil(val)) {
462 return !!defaultValue;
463 }
464 return !!val;
465}
466exports.toBooleanSafe = toBooleanSafe;
467/**
468 * Converts a value to a string (if needed), which is not (null) and not (undefined).
469 *
470 * @param {any} val The value to convert.
471 * @param {string} [defaultValue] The custom default value if 'val' is (null) or (undefined).
472 *
473 * @return {string} 'val' as string.
474 */
475function toStringSafe(val, defaultValue = '') {
476 if (_.isString(val)) {
477 return val;
478 }
479 if (_.isNil(val)) {
480 return '' + defaultValue;
481 }
482 if (val instanceof Error) {
483 return `[${val.name}] ${val.message}${_.isNil(val.stack) ? '' : ("\n\n" + val.stack)}`;
484 }
485 if (_.isFunction(val['toString'])) {
486 return '' + val.toString();
487 }
488 if (Array.isArray(val) || _.isObjectLike(val)) {
489 return JSON.stringify(val);
490 }
491 return '' + val;
492}
493exports.toStringSafe = toStringSafe;
494/**
495 * Returns the current time in UTC.
496 *
497 * @return {moment.Moment} The current UTC time.
498 */
499function utc() {
500 return moment.utc();
501}
502exports.utc = utc;
503/**
504 * Generates an unique ID.
505 *
506 * @param {string} [version] The custom version to use. Default: 4
507 * @param {any[]} []
508 *
509 * @return {string} The new GUID / unique ID.
510 */
511function uuid(version, ...args) {
512 version = normalizeString(version);
513 switch (version) {
514 case '':
515 case '4':
516 case 'v4':
517 return UUID.v4
518 .apply(null, args);
519 case '1':
520 case 'v1':
521 return UUID.v1
522 .apply(null, args);
523 case '5':
524 case 'v5':
525 return UUID_v5.apply(null, args);
526 }
527 throw new Error(`Version '${version}' is not supported`);
528}
529exports.uuid = uuid;
530__export(require("./apis/host"));
531__export(require("./apis/index"));
532__export(require("./apis/statistics"));
533__export(require("./apis/validation"));
534__export(require("./azure/storage"));
535__export(require("./cache"));
536__export(require("./cache/redis"));
537__export(require("./dev"));
538__export(require("./diagnostics/logger"));
539__export(require("./diagnostics/stopwatch"));
540__export(require("./env"));
541__export(require("./events"));
542__export(require("./fs"));
543__export(require("./geo"));
544__export(require("./http"));
545__export(require("./http/websockets"));
546__export(require("./mail"));
547__export(require("./mongo/index"));
548__export(require("./mongo/statistics"));
549__export(require("./oauth/microsoft"));
550__export(require("./queues/index"));
551__export(require("./schemas"));
552__export(require("./services/feedback"));
553__export(require("./statistics"));
554__export(require("./streams"));
555__export(require("./strings"));
556__export(require("./system"));
557__export(require("./zip/builder"));
558var swagger_jsdoc_express_1 = require("swagger-jsdoc-express");
559exports.setupSwaggerUIFromSourceFiles = swagger_jsdoc_express_1.setupSwaggerUIFromSourceFiles;
560//# sourceMappingURL=index.js.map
\No newline at end of file