@egi/smart-log 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/smart-log.js ADDED
@@ -0,0 +1,516 @@
1
+ "use strict";
2
+ // noinspection JSUnusedGlobalSymbols
3
+ var __values = (this && this.__values) || function(o) {
4
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
5
+ if (m) return m.call(o);
6
+ if (o && typeof o.length === "number") return {
7
+ next: function () {
8
+ if (o && i >= o.length) o = void 0;
9
+ return { value: o && o[i++], done: !o };
10
+ }
11
+ };
12
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.smartLog = exports.SmartLog = exports.SmartLogFormatElement = exports.SmartLocation = exports.SmartSeverityLevel = void 0;
16
+ var smart_log_date_utils_1 = require("./smart-log-date-utils");
17
+ var path = require("node:path");
18
+ var process = require("node:process");
19
+ var fs = require("node:fs");
20
+ var os = require("node:os");
21
+ var smart_tools_1 = require("./smart-tools");
22
+ var SmartSeverityLevel;
23
+ (function (SmartSeverityLevel) {
24
+ SmartSeverityLevel[SmartSeverityLevel["None"] = 0] = "None";
25
+ SmartSeverityLevel[SmartSeverityLevel["Fatal"] = 1] = "Fatal";
26
+ SmartSeverityLevel[SmartSeverityLevel["Error"] = 2] = "Error";
27
+ SmartSeverityLevel[SmartSeverityLevel["Warning"] = 3] = "Warning";
28
+ SmartSeverityLevel[SmartSeverityLevel["Info"] = 4] = "Info";
29
+ SmartSeverityLevel[SmartSeverityLevel["Verbose"] = 5] = "Verbose";
30
+ SmartSeverityLevel[SmartSeverityLevel["Debug"] = 6] = "Debug";
31
+ SmartSeverityLevel[SmartSeverityLevel["All"] = 9] = "All";
32
+ })(SmartSeverityLevel || (exports.SmartSeverityLevel = SmartSeverityLevel = {}));
33
+ var SmartLocation;
34
+ (function (SmartLocation) {
35
+ SmartLocation["App"] = "APP";
36
+ SmartLocation["Frontend"] = "FRONTEND";
37
+ SmartLocation["Backend"] = "BACKEND";
38
+ SmartLocation["Database"] = "DATABASE";
39
+ SmartLocation["UpgradeManager"] = "UPGRADE-MANAGER";
40
+ })(SmartLocation || (exports.SmartLocation = SmartLocation = {}));
41
+ var SmartLogFormatElement;
42
+ (function (SmartLogFormatElement) {
43
+ SmartLogFormatElement[SmartLogFormatElement["Severity"] = 0] = "Severity";
44
+ SmartLogFormatElement[SmartLogFormatElement["Type"] = 1] = "Type";
45
+ SmartLogFormatElement[SmartLogFormatElement["Timestamp"] = 2] = "Timestamp";
46
+ SmartLogFormatElement[SmartLogFormatElement["Message"] = 3] = "Message";
47
+ SmartLogFormatElement[SmartLogFormatElement["Location"] = 4] = "Location";
48
+ })(SmartLogFormatElement || (exports.SmartLogFormatElement = SmartLogFormatElement = {}));
49
+ /**
50
+ * A logging utility with severity-level control, flexible formatting, stack trace
51
+ * integration, and optional persistence via `ISmartLogDbWriter`.
52
+ *
53
+ * A default singleton `smartLog` is exported for convenience. Create additional
54
+ * instances for separate concerns (e.g. per-module loggers with different levels).
55
+ *
56
+ * ```typescript
57
+ * import { smartLog, SmartLog, SmartSeverityLevel } from "@egi/smart-log";
58
+ *
59
+ * smartLog.info("Application started");
60
+ *
61
+ * const verbose = new SmartLog({ logLevel: SmartSeverityLevel.Debug });
62
+ * verbose.debug("detailed trace");
63
+ * ```
64
+ */
65
+ var SmartLog = /** @class */ (function () {
66
+ function SmartLog(options) {
67
+ var _a, _b, _c, _d, _e, _f;
68
+ //
69
+ this.dbWriter = null;
70
+ this.includeLocation = false;
71
+ this.isLogging = false;
72
+ this.logFifo = [];
73
+ this.logLevel = SmartSeverityLevel.Info;
74
+ this.projectRoot = null;
75
+ this.useLogChannels = false;
76
+ this.userId = null;
77
+ if (!options) {
78
+ options = {};
79
+ }
80
+ this.logLevel = (_a = options.logLevel) !== null && _a !== void 0 ? _a : SmartSeverityLevel.Info;
81
+ this.dbWriter = (_b = options.dbWriter) !== null && _b !== void 0 ? _b : null;
82
+ this.includeLocation = !!options.location;
83
+ this.userId = (_c = options.user) !== null && _c !== void 0 ? _c : os.userInfo().username;
84
+ this.useLogChannels = !!options.logChannels;
85
+ this.outputHook = (_d = options.outputHook) !== null && _d !== void 0 ? _d : null;
86
+ this.formatHook = (_e = options.formatHook) !== null && _e !== void 0 ? _e : null;
87
+ this.stackProvider = (_f = options.stackProvider) !== null && _f !== void 0 ? _f : null;
88
+ var dir = __dirname;
89
+ while (!this.projectRoot) {
90
+ if (!dir.includes("/node_modules/") && fs.existsSync(path.join(dir, "package.json"))) {
91
+ this.projectRoot = fs.realpathSync(dir);
92
+ }
93
+ else if (dir == "/") {
94
+ dir = process.env.PROJECT_ROOT || process.env.PROJECT_HOME || process.cwd();
95
+ }
96
+ else {
97
+ dir = path.dirname(dir);
98
+ }
99
+ }
100
+ this.setLogFormat(options);
101
+ }
102
+ /**
103
+ * Overrides the stack provider used for automatic caller location detection.
104
+ * Useful when `SmartLog` is wrapped in another class and the default stack
105
+ * resolution points to the wrapper instead of the actual call site.
106
+ *
107
+ * @param stackProvider - A function that returns a fresh `Error` at the call site.
108
+ */
109
+ SmartLog.prototype.setStackProvider = function (stackProvider) {
110
+ this.stackProvider = stackProvider;
111
+ };
112
+ /**
113
+ * Sets a text transformation hook. Called with the fully formatted log line before
114
+ * console output; must return the (modified) string.
115
+ *
116
+ * Use `setOutputHook()` instead if you need side effects or want to suppress output.
117
+ *
118
+ * @param hook - Function receiving `(text, message)` and returning the transformed text.
119
+ */
120
+ SmartLog.prototype.setFormatHook = function (hook) {
121
+ this.formatHook = hook;
122
+ };
123
+ /**
124
+ * Sets a general-purpose output hook. Called after formatting and before console output.
125
+ * Use this for side effects such as writing to a file, calling a webhook, or emitting events.
126
+ *
127
+ * Return `false` (or resolve a Promise to `false`) to suppress console output for the entry.
128
+ * Any other return value (including `void`) leaves console output enabled.
129
+ *
130
+ * @param hook - Function receiving `(text, message)`. May return `false | void`
131
+ * or a `Promise` of the same.
132
+ */
133
+ SmartLog.prototype.setOutputHook = function (hook) {
134
+ this.outputHook = hook;
135
+ };
136
+ /**
137
+ * Configures the log format. Any property omitted in `format` retains its current value.
138
+ * The default sequence is: `Severity - Type - Timestamp: Message [Location]`.
139
+ *
140
+ * @param format - Partial `SmartLogFormat` to merge into the current format.
141
+ */
142
+ SmartLog.prototype.setLogFormat = function (format) {
143
+ if (!this.logFormat) {
144
+ this.logFormat = {
145
+ leading: "",
146
+ location: false,
147
+ lowerCase: false,
148
+ separator: "-",
149
+ sequence: [SmartLogFormatElement.Severity, SmartLogFormatElement.Type, SmartLogFormatElement.Timestamp, SmartLogFormatElement.Message, SmartLogFormatElement.Location]
150
+ };
151
+ }
152
+ if (format) {
153
+ for (var key in this.logFormat) {
154
+ if (format.hasOwnProperty(key)) {
155
+ this.logFormat[key] = format[key];
156
+ }
157
+ }
158
+ }
159
+ };
160
+ /**
161
+ * Returns the current minimum log severity level.
162
+ */
163
+ SmartLog.prototype.getLogLevel = function () {
164
+ return this.logLevel;
165
+ };
166
+ /**
167
+ * Sets the minimum log severity level. Messages with a higher level number are dropped.
168
+ *
169
+ * @param level - The new minimum level.
170
+ */
171
+ SmartLog.prototype.setLogLevel = function (level) {
172
+ this.logLevel = level;
173
+ };
174
+ /**
175
+ * Returns `true` if a db writer is currently set.
176
+ */
177
+ SmartLog.prototype.hasDbWriter = function () {
178
+ return this.dbWriter !== null;
179
+ };
180
+ /**
181
+ * Sets or replaces the db writer. Pass `null` to disable db logging.
182
+ *
183
+ * @param dbWriter - An `ISmartLogDbWriter` implementation, or `null` to clear.
184
+ */
185
+ SmartLog.prototype.setDbWriter = function (dbWriter) {
186
+ this.dbWriter = dbWriter;
187
+ };
188
+ /**
189
+ * Sets the timezone used when formatting timestamps in log output.
190
+ * Accepts any IANA timezone identifier (e.g. `"UTC"`, `"Europe/Berlin"`).
191
+ *
192
+ * @param timezone - IANA timezone string.
193
+ */
194
+ SmartLog.prototype.setTimezone = function (timezone) {
195
+ this.timezone = timezone;
196
+ };
197
+ /**
198
+ * Controls whether the caller's source location is appended to each log line.
199
+ *
200
+ * @param includeLocation - `true` to include location, `false` to omit.
201
+ */
202
+ SmartLog.prototype.setIncludeLocation = function (includeLocation) {
203
+ this.includeLocation = includeLocation;
204
+ };
205
+ /**
206
+ * Returns `true` if caller location is currently included in log output.
207
+ */
208
+ SmartLog.prototype.getIncludeLocation = function () {
209
+ return this.includeLocation;
210
+ };
211
+ /**
212
+ * Sets the user identifier stamped on every subsequent log entry.
213
+ *
214
+ * @param userId - A string or numeric user identifier.
215
+ */
216
+ SmartLog.prototype.setUserId = function (userId) {
217
+ this.userId = userId;
218
+ };
219
+ SmartLog.prototype.debug = function (message, options) {
220
+ this.writeLog(SmartSeverityLevel.Debug, message, options);
221
+ };
222
+ SmartLog.prototype.error = function (message, options) {
223
+ this.writeLog(SmartSeverityLevel.Error, message, options);
224
+ };
225
+ SmartLog.prototype.fatal = function (message, options) {
226
+ this.writeLog(SmartSeverityLevel.Fatal, message, options);
227
+ };
228
+ SmartLog.prototype.info = function (message, options) {
229
+ this.writeLog(SmartSeverityLevel.Info, message, options);
230
+ };
231
+ SmartLog.prototype.verbose = function (message, options) {
232
+ this.writeLog(SmartSeverityLevel.Verbose, message, options);
233
+ };
234
+ SmartLog.prototype.warning = function (message, options) {
235
+ this.writeLog(SmartSeverityLevel.Warning, message, options);
236
+ };
237
+ SmartLog.prototype.write = function (message, options) {
238
+ this.writeLog(null, message, options);
239
+ };
240
+ /**
241
+ * Core logging method. Normalises the arguments, resolves the caller location,
242
+ * and dispatches to `log()`.
243
+ *
244
+ * @param severityLevel - Severity of the message, or `null` for unseveritied `write()` calls.
245
+ * @param messageOrError - The message string or an `Error` whose `.message` is used.
246
+ * @param optionsOrError - Per-message options, or an `Error` stored as `data`.
247
+ */
248
+ SmartLog.prototype.writeLog = function (severityLevel, messageOrError, optionsOrError) {
249
+ var _a, _b, _c, _d, _e;
250
+ var options;
251
+ if (optionsOrError) {
252
+ if (optionsOrError instanceof Error || typeof optionsOrError != "object") {
253
+ options = { data: optionsOrError };
254
+ }
255
+ else {
256
+ options = optionsOrError;
257
+ }
258
+ }
259
+ else {
260
+ options = {};
261
+ }
262
+ var message;
263
+ if (messageOrError instanceof Error) {
264
+ message = messageOrError.message;
265
+ if (!options.data) {
266
+ options.data = messageOrError;
267
+ }
268
+ }
269
+ else if (typeof messageOrError.toString == "function") {
270
+ message = messageOrError.toString();
271
+ }
272
+ else {
273
+ message = String(messageOrError);
274
+ }
275
+ this.log({
276
+ type: (_a = options.type) !== null && _a !== void 0 ? _a : SmartLocation.App,
277
+ location: (_b = options.location) !== null && _b !== void 0 ? _b : smart_tools_1.tools.getCallerFromStack(this.stackProvider, {
278
+ projectRoot: this.projectRoot,
279
+ ignoreFiles: [__filename]
280
+ }),
281
+ severityLevel: severityLevel,
282
+ message: message,
283
+ data: options.data,
284
+ timestamp: (_c = options.timestamp) !== null && _c !== void 0 ? _c : Date.now(),
285
+ user: this.userId,
286
+ skipConsole: (_d = options.skipConsole) !== null && _d !== void 0 ? _d : false,
287
+ skipDatabase: (_e = options.skipDatabase) !== null && _e !== void 0 ? _e : false
288
+ });
289
+ };
290
+ /**
291
+ * Dispatches a fully-formed `LogMessage`. Filters by `logLevel`, formats the text,
292
+ * runs `outputHook` and `formatHook`, writes to the console (unless suppressed),
293
+ * and forwards to the db writer.
294
+ *
295
+ * Calls during an in-progress async db write are queued and replayed in order.
296
+ *
297
+ * @param messageObj - The complete log entry to process.
298
+ */
299
+ SmartLog.prototype.log = function (messageObj) {
300
+ var _this = this;
301
+ try {
302
+ if (this.isLogging) {
303
+ this.logFifo.push(messageObj);
304
+ }
305
+ else {
306
+ this.isLogging = true;
307
+ var withinLevel = !messageObj.severityLevel || messageObj.severityLevel <= this.logLevel;
308
+ if (withinLevel) {
309
+ var text = this.formatMessage(messageObj);
310
+ this.writeToConsole(text, messageObj);
311
+ }
312
+ if (withinLevel && !messageObj.skipDatabase && this.dbWriter) {
313
+ try {
314
+ var result = this.dbWriter.write(messageObj);
315
+ if (result instanceof Promise) {
316
+ result.then(function () {
317
+ _this.isLogging = false;
318
+ _this.nextStackEntry();
319
+ }).catch(function (error) {
320
+ _this.error("unable to write log entry to database", { skipDatabase: true, data: error });
321
+ _this.isLogging = false;
322
+ _this.nextStackEntry();
323
+ });
324
+ }
325
+ else {
326
+ this.isLogging = false;
327
+ this.nextStackEntry();
328
+ }
329
+ }
330
+ catch (error) {
331
+ this.error("unable to write log entry to database", { skipDatabase: true, data: error });
332
+ this.isLogging = false;
333
+ this.nextStackEntry();
334
+ }
335
+ }
336
+ else {
337
+ this.isLogging = false;
338
+ this.nextStackEntry();
339
+ }
340
+ }
341
+ }
342
+ catch (error) {
343
+ this.isLogging = false;
344
+ console.error("fatal logging error", error);
345
+ }
346
+ };
347
+ /**
348
+ * Formats a `LogMessage` into a string using the current log format sequence.
349
+ * Optionally accepts a custom `sequence` to override the instance format for this call.
350
+ *
351
+ * @param message - The log entry to format.
352
+ * @param sequence - Optional sequence override; uses the instance format when omitted.
353
+ * @returns The formatted log line string.
354
+ */
355
+ SmartLog.prototype.formatMessage = function (message, sequence) {
356
+ var e_1, _a;
357
+ var _b;
358
+ var text = "";
359
+ var beyondText = false;
360
+ try {
361
+ for (var _c = __values((sequence !== null && sequence !== void 0 ? sequence : this.logFormat.sequence)), _d = _c.next(); !_d.done; _d = _c.next()) {
362
+ var element = _d.value;
363
+ if (element != SmartLogFormatElement.Location || this.logFormat.location) {
364
+ if (text === "") {
365
+ text += this.logFormat.leading;
366
+ }
367
+ else if (element == SmartLogFormatElement.Message) {
368
+ text += ": ";
369
+ beyondText = true;
370
+ }
371
+ else if (beyondText) {
372
+ text += " ";
373
+ }
374
+ else {
375
+ text += this.logFormat.separator;
376
+ }
377
+ if (typeof element == "string") {
378
+ text += element;
379
+ }
380
+ else if (typeof element == "function") {
381
+ text += element();
382
+ }
383
+ else {
384
+ switch (element) {
385
+ case SmartLogFormatElement.Severity:
386
+ var severityCode = this.severityCodeFromLevel(message.severityLevel);
387
+ text += this.logFormat.lowerCase ? severityCode.toLowerCase() : severityCode;
388
+ break;
389
+ case SmartLogFormatElement.Type:
390
+ text += message.type ? (this.logFormat.lowerCase ? message.type.substring(0, 1).toLowerCase() : message.type.substring(0, 1)) : "";
391
+ break;
392
+ case SmartLogFormatElement.Timestamp:
393
+ text += (0, smart_log_date_utils_1.toSmartDbTimestamp)(message.timestamp, this.timezone);
394
+ break;
395
+ case SmartLogFormatElement.Message:
396
+ text += (_b = message.message) !== null && _b !== void 0 ? _b : "";
397
+ break;
398
+ case SmartLogFormatElement.Location:
399
+ if (this.logFormat.location) {
400
+ text += "[" + message.location + "]";
401
+ }
402
+ break;
403
+ }
404
+ }
405
+ }
406
+ text = text.trim();
407
+ }
408
+ }
409
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
410
+ finally {
411
+ try {
412
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
413
+ }
414
+ finally { if (e_1) throw e_1.error; }
415
+ }
416
+ var data = this.stringifyData(message.data);
417
+ if (data) {
418
+ text += " (".concat(data, ")");
419
+ }
420
+ return this.formatHook && !sequence ? this.formatHook(text, message) : text;
421
+ };
422
+ /**
423
+ * Returns the single-letter severity code for a given `SmartSeverityLevel`.
424
+ * Unknown levels fall back to the `Info` code.
425
+ *
426
+ * @param level - The severity level to look up.
427
+ * @returns A single uppercase letter: `F`, `E`, `W`, `I`, `D`, etc.
428
+ */
429
+ SmartLog.prototype.severityCodeFromLevel = function (level) {
430
+ var _a;
431
+ return (_a = SmartLog.severityLevelToCode[level]) !== null && _a !== void 0 ? _a : SmartLog.severityLevelToCode[SmartSeverityLevel.Info];
432
+ };
433
+ SmartLog.prototype.writeToConsole = function (text, messageObj) {
434
+ var _this = this;
435
+ if (messageObj.skipConsole) {
436
+ return;
437
+ }
438
+ if (this.outputHook) {
439
+ var result = this.outputHook(text, messageObj);
440
+ if (result instanceof Promise) {
441
+ result.then(function (res) {
442
+ if (res !== false) {
443
+ _this.printToConsole(text, messageObj);
444
+ }
445
+ }).catch(function (error) {
446
+ console.error("outputHook error", error);
447
+ _this.printToConsole(text, messageObj);
448
+ });
449
+ }
450
+ else {
451
+ if (result !== false) {
452
+ this.printToConsole(text, messageObj);
453
+ }
454
+ }
455
+ }
456
+ else {
457
+ this.printToConsole(text, messageObj);
458
+ }
459
+ };
460
+ SmartLog.prototype.printToConsole = function (text, messageObj) {
461
+ var logFn;
462
+ if (this.useLogChannels) {
463
+ switch (messageObj.severityLevel) {
464
+ case SmartSeverityLevel.Fatal:
465
+ case SmartSeverityLevel.Error:
466
+ logFn = console.error;
467
+ break;
468
+ case SmartSeverityLevel.Warning:
469
+ logFn = console.warn;
470
+ break;
471
+ case SmartSeverityLevel.Info:
472
+ case SmartSeverityLevel.Verbose:
473
+ logFn = console.info;
474
+ break;
475
+ case SmartSeverityLevel.Debug:
476
+ logFn = console.debug;
477
+ break;
478
+ default:
479
+ logFn = console.log;
480
+ break;
481
+ }
482
+ }
483
+ else {
484
+ logFn = console.log;
485
+ }
486
+ logFn(text);
487
+ };
488
+ SmartLog.prototype.stringifyData = function (data) {
489
+ if (data) {
490
+ if (data instanceof Error) {
491
+ return data.stack;
492
+ }
493
+ else if (typeof data == "object") {
494
+ return JSON.stringify(data);
495
+ }
496
+ else if (typeof data.toString == "function") {
497
+ return data.toString();
498
+ }
499
+ else {
500
+ return String(data);
501
+ }
502
+ }
503
+ return null;
504
+ };
505
+ SmartLog.prototype.nextStackEntry = function () {
506
+ if (this.logFifo.length > 0) {
507
+ var entry = this.logFifo.shift();
508
+ this.log(entry);
509
+ }
510
+ };
511
+ // corresponds with SmartSeverityLevel enum
512
+ SmartLog.severityLevelToCode = ["-", "F", "E", "W", "I", "I", "D", "A", "-", "-", "*"];
513
+ return SmartLog;
514
+ }());
515
+ exports.SmartLog = SmartLog;
516
+ exports.smartLog = new SmartLog();
@@ -0,0 +1,64 @@
1
+ export interface GetCallerOptions {
2
+ ignoreFiles?: string[];
3
+ projectRoot?: string;
4
+ }
5
+ export interface FrameData {
6
+ columnNumber: number;
7
+ fileName: string;
8
+ functionName: string;
9
+ lineNumber: number;
10
+ methodName: string;
11
+ native: boolean;
12
+ typeName: string;
13
+ }
14
+ export declare class SmartTools {
15
+ /**
16
+ * Captures the stack trace starting from the point just below the provided function.
17
+ *
18
+ * @param belowFn - A reference function to exclude from the stack trace.
19
+ * @returns An array of FrameData objects representing the captured stack trace.
20
+ */
21
+ getStackTrace(belowFn?: () => any): FrameData[];
22
+ /**
23
+ * Parses an error's stack trace into an array of FrameData objects.
24
+ *
25
+ * @param err - An error object containing the stack trace.
26
+ * @returns An array of FrameData objects parsed from the error's stack trace.
27
+ */
28
+ parseStackTrace(err: Error): FrameData[];
29
+ /**
30
+ * Retrieves caller information from the stack trace, excluding specified files or patterns.
31
+ *
32
+ * @param {Error | (() => Error)} [errorOrStackProvider] - An error object or function returning an error,
33
+ * used to extract the stack trace. Defaults to capturing the current stack trace if omitted.
34
+ * @param options - Optional settings for filtering and formatting the caller information.
35
+ * @returns {string} A string with the format "fileName:lineNumber (functionName)",
36
+ * or "unknown location" if caller information cannot be determined.
37
+ */
38
+ getCallerFromStack(errorOrStackProvider?: Error | (() => Error), options?: GetCallerOptions): string;
39
+ kebabCase(s: string): string;
40
+ snakeCase(s: string): string;
41
+ camelCase(s: string): string;
42
+ pascalCase(s: string): string;
43
+ titleCase(s: string): string;
44
+ constantCase(s: string): string;
45
+ clone<T extends object>(obj: T): T;
46
+ cloneDeep<T>(obj: T): T;
47
+ isSimpleObject(obj: any): boolean;
48
+ isObject(obj: any): boolean;
49
+ isArray(obj: any): boolean;
50
+ isString(obj: any): boolean;
51
+ isNumber(obj: any): boolean;
52
+ isBoolean(obj: any): boolean;
53
+ isNull(obj: any): boolean;
54
+ isUndefined(obj: any): boolean;
55
+ isFunction(obj: any): boolean;
56
+ isDate(obj: any): boolean;
57
+ isRegExp(obj: any): boolean;
58
+ isError(obj: any): boolean;
59
+ isSymbol(obj: any): boolean;
60
+ isEmpty(obj: any): boolean;
61
+ isPrimitive(obj: any): boolean;
62
+ private splitWords;
63
+ }
64
+ export declare const tools: SmartTools;