node-automator 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.
Files changed (143) hide show
  1. package/LICENSE +15 -0
  2. package/assets/alert.png +0 -0
  3. package/assets/error.png +0 -0
  4. package/assets/success.png +0 -0
  5. package/commands/abort.js +11 -0
  6. package/commands/alert.js +19 -0
  7. package/commands/assemble.js +56 -0
  8. package/commands/assert.js +18 -0
  9. package/commands/base.js +363 -0
  10. package/commands/break.js +11 -0
  11. package/commands/change_filter.js +34 -0
  12. package/commands/cheerio.js +15 -0
  13. package/commands/clear_screen.js +14 -0
  14. package/commands/commit.js +31 -0
  15. package/commands/compare.js +23 -0
  16. package/commands/confirm.js +16 -0
  17. package/commands/continue.js +11 -0
  18. package/commands/copy.js +14 -0
  19. package/commands/cursor_up.js +12 -0
  20. package/commands/date.js +25 -0
  21. package/commands/debugger.js +11 -0
  22. package/commands/dingtalk.js +110 -0
  23. package/commands/disassemble.js +36 -0
  24. package/commands/divination.js +15 -0
  25. package/commands/download.js +12 -0
  26. package/commands/edit.js +83 -0
  27. package/commands/edit_excel.js +57 -0
  28. package/commands/env_optional.js +57 -0
  29. package/commands/eval.js +27 -0
  30. package/commands/exec_from_file.js +31 -0
  31. package/commands/export_diff_head.js +31 -0
  32. package/commands/file_info.js +41 -0
  33. package/commands/file_size.js +12 -0
  34. package/commands/files.js +14 -0
  35. package/commands/first_exist.js +18 -0
  36. package/commands/flatten.js +18 -0
  37. package/commands/ftp.js +161 -0
  38. package/commands/git_commit.js +31 -0
  39. package/commands/git_export_diff_head.js +13 -0
  40. package/commands/git_is_dirty.js +13 -0
  41. package/commands/hash.js +21 -0
  42. package/commands/http_request.js +12 -0
  43. package/commands/image_crop.js +19 -0
  44. package/commands/input.js +37 -0
  45. package/commands/interval.js +60 -0
  46. package/commands/is_dirty.js +31 -0
  47. package/commands/jwt_decode.js +22 -0
  48. package/commands/list2dict.js +32 -0
  49. package/commands/log.js +72 -0
  50. package/commands/loop.js +115 -0
  51. package/commands/loop_forever.js +66 -0
  52. package/commands/merge_files.js +39 -0
  53. package/commands/mgr.js +476 -0
  54. package/commands/modify.js +44 -0
  55. package/commands/move.js +14 -0
  56. package/commands/move_local.js +14 -0
  57. package/commands/multi_select.js +16 -0
  58. package/commands/mysql_connect.js +29 -0
  59. package/commands/mysql_end.js +13 -0
  60. package/commands/mysql_query.js +19 -0
  61. package/commands/notify.js +13 -0
  62. package/commands/open.js +30 -0
  63. package/commands/parse.js +18 -0
  64. package/commands/pause.js +15 -0
  65. package/commands/print.js +47 -0
  66. package/commands/read_cache.js +12 -0
  67. package/commands/read_cfg.js +13 -0
  68. package/commands/read_clipboard.js +19 -0
  69. package/commands/read_excel.js +17 -0
  70. package/commands/read_only_excel.js +40 -0
  71. package/commands/read_plain.js +14 -0
  72. package/commands/remove.js +14 -0
  73. package/commands/retrieve.js +17 -0
  74. package/commands/reveal.js +33 -0
  75. package/commands/revision_info.js +31 -0
  76. package/commands/schedule.js +80 -0
  77. package/commands/select.js +17 -0
  78. package/commands/send_email.js +25 -0
  79. package/commands/share_data.js +745 -0
  80. package/commands/shell.js +13 -0
  81. package/commands/sleep.js +17 -0
  82. package/commands/store.js +13 -0
  83. package/commands/store_optional.js +33 -0
  84. package/commands/stream.js +16 -0
  85. package/commands/stringify.js +24 -0
  86. package/commands/svn_add.js +26 -0
  87. package/commands/svn_commit.js +49 -0
  88. package/commands/svn_export_diff_head.js +13 -0
  89. package/commands/svn_is_dirty.js +13 -0
  90. package/commands/svn_update.js +27 -0
  91. package/commands/switch.js +18 -0
  92. package/commands/temp.js +12 -0
  93. package/commands/tencent_cos.js +323 -0
  94. package/commands/test.js +14 -0
  95. package/commands/title.js +18 -0
  96. package/commands/tmpdir.js +21 -0
  97. package/commands/translate.js +58 -0
  98. package/commands/traversal.js +38 -0
  99. package/commands/truncate.js +31 -0
  100. package/commands/truncate_all.js +62 -0
  101. package/commands/ts_sort.js +18 -0
  102. package/commands/unzip.js +50 -0
  103. package/commands/updating_revision.js +28 -0
  104. package/commands/valid_required.js +31 -0
  105. package/commands/void.js +10 -0
  106. package/commands/watch_mail.js +94 -0
  107. package/commands/web_socket.js +233 -0
  108. package/commands/which.js +60 -0
  109. package/commands/write_cache.js +16 -0
  110. package/commands/write_cfg.js +18 -0
  111. package/commands/write_clipboard.js +23 -0
  112. package/commands/write_excel.js +17 -0
  113. package/commands/write_plain.js +18 -0
  114. package/commands/zip.js +78 -0
  115. package/commands/zip_data.js +64 -0
  116. package/examples/print_env.yml +3 -0
  117. package/index.js +109 -0
  118. package/package.json +63 -0
  119. package/scratch/.gitkeep +0 -0
  120. package/utils/alert_tool.js +133 -0
  121. package/utils/base64_tool.js +13 -0
  122. package/utils/cache/local_cache.js +79 -0
  123. package/utils/cache/raw_cache.js +47 -0
  124. package/utils/cache/simple_local_cache.js +33 -0
  125. package/utils/cache/simple_sqlite_cache.js +43 -0
  126. package/utils/cache/simple_svn_cache.js +49 -0
  127. package/utils/cache/svn_cache.js +40 -0
  128. package/utils/cache_tool.js +53 -0
  129. package/utils/display_tool.js +85 -0
  130. package/utils/divination_util.js +555 -0
  131. package/utils/file_tool.js +529 -0
  132. package/utils/hash_tool.js +8 -0
  133. package/utils/interaction_tool.js +228 -0
  134. package/utils/log_tool.js +190 -0
  135. package/utils/parse_directive.js +194 -0
  136. package/utils/parse_tool.js +236 -0
  137. package/utils/request_tool.js +156 -0
  138. package/utils/scm_tool.js +108 -0
  139. package/utils/selection_tool.js +593 -0
  140. package/utils/shell_tool.js +162 -0
  141. package/utils/svn_diff/diff_file.js +44 -0
  142. package/utils/svn_diff/diff_parser.js +55 -0
  143. package/utils/transform_tool.js +520 -0
@@ -0,0 +1,520 @@
1
+ function toArray(value) {
2
+ if (value instanceof Array) {
3
+ return value;
4
+ }
5
+ return [value];
6
+ }
7
+ /**
8
+ *
9
+ * @param {*} value
10
+ * @param { {remove_duplicate_pattern: string, remove_duplicate_prefix: string, remove_duplicate_suffix: string} } options
11
+ * @returns
12
+ */
13
+ function removeDuplicate(value, options) {
14
+ let seen = {};
15
+ let duplicate_map = {};
16
+ options = options || {};
17
+ value = value.filter(v => {
18
+ let raw = v = typeof v === "string" ? v : JSON.stringify(v);
19
+ if (options.remove_duplicate_pattern) {
20
+ v = v.match(new RegExp(options.remove_duplicate_pattern));
21
+ }
22
+ duplicate_map[raw] = v;
23
+ if (!seen[v]) {
24
+ seen[v] = 1;
25
+ return true;
26
+ } else {
27
+ ++seen[v];
28
+ }
29
+ });
30
+ // // 添加过滤前缀
31
+ if (options.remove_duplicate_prefix || options.remove_duplicate_suffix) {
32
+ value = value.map(v => {
33
+ let raw = typeof v === "string" ? v : JSON.stringify(v);
34
+ let repeat = seen[duplicate_map[raw]] || 0;
35
+ let prefix = options.remove_duplicate_prefix && format(options.remove_duplicate_prefix, {repeat}) || "";
36
+ let suffix = options.remove_duplicate_suffix && format(options.remove_duplicate_suffix, {repeat}) || "";
37
+ return prefix + v + suffix;
38
+ });
39
+ }
40
+ return value;
41
+ }
42
+
43
+ function removeDuplicateObject(value, key) {
44
+ let seen = {};
45
+ value = value.filter(v => {
46
+ v = getDataByKeySimple(key, v);
47
+ if (!seen[v]) {
48
+ seen[v] = 1;
49
+ return true;
50
+ } else {
51
+ ++seen[v];
52
+ }
53
+ });
54
+ return value;
55
+ }
56
+
57
+ /**
58
+ * 格式化字符串
59
+ * @param {*} value
60
+ * @param {*} args
61
+ */
62
+ function format(value, ...args) {
63
+ if (args.length == 1 && typeof (args[0]) == "object") {
64
+ args = args[0];
65
+ }
66
+ return value.replace(/\{(\S+?)\}/g, function (s, i) {
67
+ return (args && args[i] == null) ? s : args[i];
68
+ });
69
+ }
70
+
71
+ const converters = {
72
+ "int": parseInt,
73
+ "integer": parseInt,
74
+ "float": parseFloat,
75
+ "number": parseFloat,
76
+ "string": (v) => v.toString(),
77
+ "str": (v) => v.toString(),
78
+ "list": (v) => v instanceof Array ? v : JSON.parse(v),
79
+ "array": (v) => v instanceof Array ? v : JSON.parse(v),
80
+ "bool": v => !!v,
81
+ "boolean": v => !!v,
82
+ "millisecond": v => {
83
+ if (typeof v === "number") {
84
+ return v;
85
+ }
86
+ if (typeof v === "string") {
87
+ let fragments = v.split(":");
88
+ let result = 0;
89
+ fragments.forEach((fragment, i) => {
90
+ result += parseFloat(fragment) * Math.pow(60, 2 - i) * 1000;
91
+ });
92
+ return result;
93
+ }
94
+ throw `无法将 ${v} 转换成 millisecond 类型`;
95
+ },
96
+ };
97
+ /**
98
+ *
99
+ * @param {*} value
100
+ * @param {"int" | "integer" | "float" | "number" | "string" | "str" | "list" | "array" | "bool" | "boolean" | "millisecond" } type
101
+ * @returns
102
+ */
103
+ function convert(value, type) {
104
+ let value_type_matches = /(\w+)((\[\])*)/.exec(type || "");
105
+ let main_type = value_type_matches && value_type_matches[1];
106
+ // n维数组
107
+ let num_dim = value_type_matches && value_type_matches[2] && value_type_matches[2].length / 2 || 0;
108
+ let converter = converters[main_type];
109
+ if (converter) {
110
+ value = recursive_convert_list(value, converter, num_dim);
111
+ }
112
+ return value;
113
+ }
114
+
115
+ function recursive_convert_list(value, converter, num_dim) {
116
+ if (!num_dim) {
117
+ return converter(value);
118
+ } else {
119
+ for (let i in value) {
120
+ let v = value[i];
121
+ value[i] = recursive_convert_list(v, converter, num_dim - 1);
122
+ }
123
+ return value;
124
+ }
125
+ }
126
+
127
+ /**
128
+ * JSON字符串化
129
+ * @param {Array|Object} value 对象
130
+ * @param {number} space 空格数,可选。默认值:4
131
+ * @param {string[]?} sortKeys 键排序数据,可选。默认值:null
132
+ */
133
+ function json_compacted(value, space, sortKeys) {
134
+ if (value == null) {
135
+ return "null";
136
+ }
137
+ let result = "";
138
+ space = space === undefined ? 2 : space;
139
+ let depth = arguments[3] === undefined ? 0 : arguments[3];
140
+
141
+ /** key: value 是否换行 */
142
+ let wrapKV = false;
143
+ /** 对象属性 是否换行 */
144
+ let wrapAtt = false;
145
+ /** 数组元素 是否换行 */
146
+ let wrapArr = false;
147
+ wrapKV = wrapAtt = wrapArr = space > 0;
148
+
149
+ /** 是否可以显示在同一行 */
150
+ let canSameLine = false;
151
+ if (value instanceof Array) {
152
+ canSameLine = value.every(v => typeof v !== "object");
153
+ if (canSameLine) {
154
+ wrapKV = false;
155
+ wrapArr = false;
156
+ }
157
+ } else if (typeof value === "object") {
158
+ canSameLine = true;
159
+ for (let k in value) {
160
+ if (value.hasOwnProperty(k)) {
161
+ if (value[k] != null && typeof value[k] === "object") {
162
+ canSameLine = false;
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ if (canSameLine) {
168
+ wrapAtt = false;
169
+ wrapKV = false;
170
+ }
171
+ }
172
+ let space1 = "";
173
+ let n = (depth + 1) * space;;
174
+ while (--n >= 0) {
175
+ space1 += " ";
176
+ }
177
+ let space2 = space1.substr(space);
178
+
179
+ if (value instanceof Array) {
180
+ result += "[";
181
+ if (wrapKV) {
182
+ result += "\n";
183
+ }
184
+ ++depth;
185
+ if (!wrapArr && wrapKV) {
186
+ result += space1;
187
+ }
188
+ // 不能用 map 需要用 for。 使用 for 时,如果value有<empty item>, map 无法正确的值
189
+ for (let i = 0, len = value.length; i < len; ++i) {
190
+ let v = value[i];
191
+ result += `${wrapArr ? space1 : ""}${json_compacted(v, space, sortKeys, depth)}`;
192
+ if (i != len - 1) {
193
+ result += !wrapArr ? "," : ",\n";
194
+ }
195
+ }
196
+ // result += value.map(v => {
197
+ // return `${wrapArr ? space1 : ""}${json_compacted(v, space, sortKeys, depth)}`;
198
+ // }).join(!wrapArr ? "," : ",\n");
199
+ } else if (typeof value === "object") {
200
+ result += "{";
201
+ if (wrapKV) {
202
+ result += "\n";
203
+ }
204
+ ++depth;
205
+ let keys = Object.keys(value);
206
+ keys = keys.filter(v => value.hasOwnProperty(v));
207
+ if (sortKeys instanceof Array) {
208
+ let num = sortKeys.length * 2;
209
+ keys.sort((keyA, keyB) => {
210
+ let idxA = sortKeys.indexOf(keyA);
211
+ let idxB = sortKeys.indexOf(keyB);
212
+ idxA = (idxA + num) % num;
213
+ idxB = (idxB + num) % num;
214
+ return idxA - idxB;
215
+ });
216
+ }
217
+ if (!wrapAtt && wrapKV) {
218
+ result += space1;
219
+ }
220
+ result += keys.map(v => {
221
+ return `${wrapAtt ? space1 : ""}"${v}": ${json_compacted(value[v], space, sortKeys, depth)}`;
222
+ }).join(!wrapAtt ? "," : ",\n");
223
+ } else if (typeof value === "string") {
224
+ result += `"${escapeString(value)}"`;
225
+ } else {
226
+ result += value;
227
+ }
228
+ if (value instanceof Array) {
229
+ if (wrapKV) {
230
+ result += "\n";
231
+ result += space2;
232
+ }
233
+ result += "]";
234
+ } else if (typeof value === "object") {
235
+ if (wrapKV) {
236
+ result += "\n";
237
+ result += space2;
238
+ }
239
+ result += "}";
240
+ }
241
+ return result;
242
+ }
243
+
244
+ function escapeString(str) {
245
+ return str
246
+ .replace(/\\/g, '\\\\')
247
+ .replace(/\"/g, '\\\"')
248
+ // .replace(/\//g, '\\/')
249
+ // *注: [\b] 是匹配backspace, \b 是匹配边界
250
+ .replace(/[\b]/g, '\\b')
251
+ .replace(/\f/g, '\\f')
252
+ .replace(/\n/g, '\\n')
253
+ .replace(/\r/g, '\\r')
254
+ .replace(/\t/g, '\\t');
255
+ };
256
+
257
+
258
+ /** 格式化数值相关 */
259
+ function formatByValues(values, fmt, prefix) {
260
+ prefix = prefix || "0000";
261
+ return fmt.replace(/(.)\1{0,}/g, function (matchString) {
262
+ var key = matchString[0];
263
+ if (key && values.hasOwnProperty(key)) {
264
+ var value = values[key];
265
+ var valueStr = value.toString();
266
+ if (matchString.length == 1) {
267
+ return valueStr;
268
+ } else {
269
+ return (prefix + valueStr).substr(valueStr.length + prefix.length - matchString.length);
270
+ }
271
+ } else {
272
+ return matchString;
273
+ }
274
+ });
275
+ }
276
+
277
+ const dayInWeeks = [ "日","一","二","三","四","五","六" ];
278
+ const fullDayInWeeks = [ "星期日","星期一","星期二","星期三","星期四","星期五","星期六" ];
279
+ /**
280
+ * 格式化日期
281
+ * @param {Date} date
282
+ * @param {string} fmt
283
+ */
284
+ function formatDate(date, fmt) {
285
+ if (fmt == null) {
286
+ // fmt = 'YYYY-MM-DD hh:mm:ss SSS';
287
+ fmt = 'YYYY-MM-DD hh:mm:ss';
288
+ }
289
+
290
+ var values = {
291
+ "Y": date.getFullYear(),
292
+ "M": date.getMonth() + 1,
293
+ "D": date.getDate(),
294
+ "e": dayInWeeks[date.getDay()],
295
+ "E": fullDayInWeeks[date.getDay()],
296
+ "h": date.getHours(),
297
+ "m": date.getMinutes(),
298
+ "s": date.getSeconds(),
299
+ "S": date.getMilliseconds(),
300
+ };
301
+ return formatByValues(values, fmt);
302
+ }
303
+
304
+ /**
305
+ * 格式化时间戳(毫秒)
306
+ * @param {number} millisec 毫秒
307
+ * @param {string} fmt
308
+ */
309
+ function formatTimestampMillisec(millisec, fmt) {
310
+ /**
311
+ * @type {Date}
312
+ */
313
+ let date = this['__formatDateInMillisec__date'] = this['__formatDateInMillisec__date'] || new Date();
314
+ date.setTime(millisec);
315
+ return formatDate(date, fmt);
316
+ }
317
+
318
+ /**
319
+ * 格式化时间戳(秒)
320
+ * @param {number} sec 秒
321
+ * @param {string} fmt
322
+ */
323
+ function formatTimestampSec(sec, fmt) {
324
+ return formatTimestampMillisec(sec * 1000, fmt);
325
+ }
326
+
327
+ /**
328
+ * 格式化时间(秒)
329
+ * @param {number} time
330
+ * @param {string} fmt
331
+ */
332
+ function formatTimeInSec(time, fmt) {
333
+ if (fmt == null) {
334
+ fmt = 'hh:mm:ss';
335
+ }
336
+
337
+ var hours = Math.floor(time / 3600),
338
+ minutes = Math.floor(time / 60) % 60,
339
+ seconds = Math.floor(time % 60);
340
+ var values = {
341
+ "h": hours,
342
+ "m": minutes,
343
+ "s": seconds,
344
+ };
345
+ return formatByValues(values, fmt);
346
+ }
347
+
348
+
349
+ /**
350
+ * 格式化时间(毫秒)
351
+ * @param {number} time
352
+ * @param {string | boolean } fmt
353
+ * @param {{ hour: string, minute: string, second: string, millisec: string }} fmtData
354
+ */
355
+ function formatTimeInMillisec(time, fmt, fmtData) {
356
+ if (fmt == null) {
357
+ fmt = 'hh:mm:ss SSS';
358
+ }
359
+ if (fmt === true) {
360
+ fmt = fmtData || {
361
+ day: "天",
362
+ hour: "小时",
363
+ minute: "分钟",
364
+ second: "秒",
365
+ millisec: "毫秒",
366
+ };
367
+ }
368
+
369
+ var days = Math.floor(time / 86400000);
370
+ var hours = Math.floor(time / 3600000) % 24;
371
+ var seconds = Math.floor(time / 1000) % 60;
372
+ var minutes = Math.floor(time / 60000) % 60;
373
+ var millisec = time % 1000;
374
+ var values = {
375
+ "d": days,
376
+ "h": hours,
377
+ "m": minutes,
378
+ "s": seconds,
379
+ "S": millisec,
380
+ };
381
+ if (typeof fmt === "object") {
382
+ if (time < 1000) {
383
+ return formatByValues(values, `S${fmt.millisec}`);
384
+ }
385
+ if (time < 60 * 1000) {
386
+ return formatByValues(values, `s${fmt.second}`);
387
+ }
388
+ if (time < 60 * 1000 * 60) {
389
+ return formatByValues(values, `m${fmt.minute}`);
390
+ }
391
+ return formatByValues(values, `h${fmt.hour}`);
392
+ }
393
+ return formatByValues(values, fmt);
394
+ }
395
+
396
+ /** 对齐方式 */
397
+ const Alignment = {
398
+ RIGHT: 1, // 右对齐
399
+ LEFT: 2, // 左对齐
400
+ CENTER: 3, // 居中对齐
401
+ };
402
+
403
+ /**
404
+ * 使用from的格式化长度与to的格式化长度相等
405
+ * @param {*} from
406
+ * @param {*} to
407
+ * @param { {alignment: Alignment, paddingChar: string} } options
408
+ */
409
+ function alignNumber(from, to, options) {
410
+ return alignStr(from, to.toString().length, options);
411
+ }
412
+
413
+ /**
414
+ * 使用from的格式化长度与toNum相等
415
+ * @param {*} from
416
+ * @param {number} toNum
417
+ * @param { {alignment: Alignment, paddingChar: string} } options
418
+ */
419
+ function alignStr(from, toNum, options) {
420
+ options = Object.assign({alignment: Alignment.RIGHT, paddingChar: " "}, options);
421
+ let prefixNum = 0;
422
+ let suffixNum = 0;
423
+ from = from.toString().substr(0, toNum);
424
+ let fromNum = from.length;
425
+ let totalOffset = toNum - fromNum;
426
+ if (totalOffset < 0) {
427
+ totalOffset = 0;
428
+ }
429
+ switch (options.alignment) {
430
+ case Alignment.LEFT: {
431
+ suffixNum = totalOffset;
432
+ break;
433
+ }
434
+ case Alignment.CENTER: {
435
+ prefixNum = Math.ceil(totalOffset / 2);
436
+ suffixNum = Math.floor(totalOffset / 2);
437
+ break;
438
+ }
439
+ case Alignment.RIGHT:
440
+ default: {
441
+ prefixNum = totalOffset;
442
+ break;
443
+ }
444
+ }
445
+ return options.paddingChar.repeat(prefixNum) + from + options.paddingChar.repeat(suffixNum);
446
+ }
447
+
448
+ /**
449
+ * 扁平化数组
450
+ * @param {*} src
451
+ * @param {any[]} dst
452
+ */
453
+ function flatten(src, dst = null) {
454
+ if (dst == null) {
455
+ dst = [];
456
+ }
457
+ if (src instanceof Array) {
458
+ for (let sub_src of src) {
459
+ flatten(sub_src, dst);
460
+ }
461
+ } else {
462
+ dst.push(src);
463
+ }
464
+ return dst;
465
+ }
466
+
467
+ const KB = 1024;
468
+ const MB = 1024 * 1024;
469
+ const GB = 1024 * 1024 * 1024;
470
+
471
+ /**
472
+ *
473
+ * @param {number} bytes
474
+ */
475
+ function formatByteSize(bytes) {
476
+ if (bytes >= GB) {
477
+ return `${(bytes / GB).toFixed(2)} GB`;
478
+ }
479
+ if (bytes >= MB) {
480
+ return `${(bytes / MB).toFixed(2)} MB`;
481
+ }
482
+ return (bytes / KB).toFixed(2) + " KB";
483
+ }
484
+
485
+ /**
486
+ *
487
+ * @param {string} key
488
+ */
489
+ function getDataByKeySimple(key, from) {
490
+ const subkeys = key.split(".");
491
+ let val = from;
492
+ for (const subkey of subkeys) {
493
+ if (subkey == null) {
494
+ continue;
495
+ }
496
+ val = val && val[subkey];
497
+ }
498
+ return val;
499
+ }
500
+
501
+ module.exports = {
502
+ toArray,
503
+ format,
504
+ convert,
505
+ json_compacted,
506
+ formatByValues,
507
+ formatDate,
508
+ formatTimestampMillisec,
509
+ formatTimestampSec,
510
+ formatTimeInSec,
511
+ formatTimeInMillisec,
512
+ alignNumber,
513
+ Alignment,
514
+ flatten,
515
+ alignStr,
516
+ formatByteSize,
517
+ escapeString,
518
+ removeDuplicate,
519
+ removeDuplicateObject,
520
+ };