@naturalcycles/nodejs-lib 13.23.1 → 13.24.1
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/dist/csv/csvReader.js +1 -1
- package/dist/slack/slack.service.js +1 -1
- package/dist/stream/progressLogger.js +1 -1
- package/dist/util/buildInfo.util.js +1 -1
- package/dist/validation/joi/string.extensions.js +41 -6
- package/package.json +2 -2
- package/src/csv/csvReader.ts +4 -1
- package/src/slack/slack.service.ts +2 -2
- package/src/stream/progressLogger.ts +2 -2
- package/src/util/buildInfo.util.ts +2 -2
- package/src/validation/joi/string.extensions.ts +51 -7
package/dist/csv/csvReader.js
CHANGED
|
@@ -34,7 +34,7 @@ function csvStringParse(str, cfg = {}) {
|
|
|
34
34
|
}
|
|
35
35
|
exports.csvStringParse = csvStringParse;
|
|
36
36
|
function csvStringToArray(str) {
|
|
37
|
-
const objPattern = new RegExp(
|
|
37
|
+
const objPattern = new RegExp(String.raw `(,|\r?\n|\r|^)(?:"([^"]*(?:""[^"]*)*)"|([^,\r\n]*))`, 'gi');
|
|
38
38
|
let matches;
|
|
39
39
|
const arr = [[]];
|
|
40
40
|
while ((matches = objPattern.exec(str))) {
|
|
@@ -130,7 +130,7 @@ class SlackService {
|
|
|
130
130
|
}
|
|
131
131
|
exports.SlackService = SlackService;
|
|
132
132
|
function slackDefaultMessagePrefixHook(msg) {
|
|
133
|
-
const tokens = [
|
|
133
|
+
const tokens = [js_lib_1.localTime.now().toPretty()];
|
|
134
134
|
const { ctx } = msg;
|
|
135
135
|
// AppEngine-specific decoration
|
|
136
136
|
if (GAE && ctx && typeof ctx === 'object' && typeof ctx.header === 'function') {
|
|
@@ -103,7 +103,7 @@ class ProgressLogger {
|
|
|
103
103
|
if (perHour > 900) {
|
|
104
104
|
perHour = Math.round(perHour / 1000) + 'K';
|
|
105
105
|
}
|
|
106
|
-
logger.log(`${(0, colors_1.dimGrey)(
|
|
106
|
+
logger.log(`${(0, colors_1.dimGrey)(js_lib_1.localTime.now().toPretty())} ${(0, colors_1.white)(metric)} took ${(0, colors_1.yellow)((0, js_lib_1._since)(this.started))} so far to process ${(0, colors_1.yellow)(batchedProgress)} rows, ~${(0, colors_1.yellow)(perHour)}/hour`);
|
|
107
107
|
}
|
|
108
108
|
else if (final) {
|
|
109
109
|
logger.log(`${(0, colors_1.boldWhite)(metric)} took ${(0, colors_1.yellow)((0, js_lib_1._since)(this.started))} to process ${(0, colors_1.yellow)(batchedProgress)} rows with total RPS of ${(0, colors_1.yellow)(rpsTotal)}`);
|
|
@@ -5,7 +5,7 @@ const js_lib_1 = require("@naturalcycles/js-lib");
|
|
|
5
5
|
const fs2_1 = require("../fs/fs2");
|
|
6
6
|
const git_util_1 = require("./git.util");
|
|
7
7
|
function generateBuildInfo(opt = {}) {
|
|
8
|
-
const now =
|
|
8
|
+
const now = js_lib_1.localTime.orNow(opt.overrideTimestamp);
|
|
9
9
|
const ts = now.unix();
|
|
10
10
|
const rev = (0, git_util_1.gitCurrentCommitSha)();
|
|
11
11
|
const branchName = (0, git_util_1.gitCurrentBranchName)();
|
|
@@ -41,14 +41,14 @@ function stringExtensions(joi) {
|
|
|
41
41
|
let { min, max } = args;
|
|
42
42
|
// Today allows +-14 hours gap to account for different timezones
|
|
43
43
|
if (max === 'today') {
|
|
44
|
-
max = (
|
|
44
|
+
max = getTodayStrPlus15();
|
|
45
45
|
}
|
|
46
46
|
if (min === 'today') {
|
|
47
|
-
min = (
|
|
47
|
+
min = getTodayStrMinus15();
|
|
48
48
|
}
|
|
49
49
|
// console.log('min/max', min, max)
|
|
50
|
-
const
|
|
51
|
-
if (!
|
|
50
|
+
const parts = /^(\d{4})-(\d{2})-(\d{2})$/.exec(v);
|
|
51
|
+
if (!parts || parts.length < 4) {
|
|
52
52
|
err = 'string.dateString';
|
|
53
53
|
}
|
|
54
54
|
else if (min && v < min) {
|
|
@@ -57,8 +57,7 @@ function stringExtensions(joi) {
|
|
|
57
57
|
else if (max && v > max) {
|
|
58
58
|
err = 'string.dateStringMax';
|
|
59
59
|
}
|
|
60
|
-
else if (!
|
|
61
|
-
// todo: replace with another regex (from ajv-validators) for speed
|
|
60
|
+
else if (!isValidDate(parts)) {
|
|
62
61
|
err = 'string.dateStringCalendarAccuracy';
|
|
63
62
|
}
|
|
64
63
|
if (err) {
|
|
@@ -71,3 +70,39 @@ function stringExtensions(joi) {
|
|
|
71
70
|
};
|
|
72
71
|
}
|
|
73
72
|
exports.stringExtensions = stringExtensions;
|
|
73
|
+
const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
74
|
+
// Based on: https://github.com/ajv-validator
|
|
75
|
+
function isValidDate(parts) {
|
|
76
|
+
const year = Number(parts[1]);
|
|
77
|
+
const month = Number(parts[2]);
|
|
78
|
+
const day = Number(parts[3]);
|
|
79
|
+
return (month >= 1 &&
|
|
80
|
+
month <= 12 &&
|
|
81
|
+
day >= 1 &&
|
|
82
|
+
day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month]));
|
|
83
|
+
}
|
|
84
|
+
function isLeapYear(year) {
|
|
85
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
86
|
+
}
|
|
87
|
+
let lastCheckedPlus = 0;
|
|
88
|
+
let todayStrPlusCached;
|
|
89
|
+
let lastCheckedMinus = 0;
|
|
90
|
+
let todayStrMinusCached;
|
|
91
|
+
function getTodayStrPlus15() {
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
if (now - lastCheckedPlus < 3_600_000) {
|
|
94
|
+
// cached for 1 hour
|
|
95
|
+
return todayStrPlusCached;
|
|
96
|
+
}
|
|
97
|
+
lastCheckedPlus = now;
|
|
98
|
+
return (todayStrPlusCached = js_lib_1.localTime.now().plus(15, 'hour').toISODate());
|
|
99
|
+
}
|
|
100
|
+
function getTodayStrMinus15() {
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
if (now - lastCheckedMinus < 3_600_000) {
|
|
103
|
+
// cached for 1 hour
|
|
104
|
+
return todayStrMinusCached;
|
|
105
|
+
}
|
|
106
|
+
lastCheckedMinus = now;
|
|
107
|
+
return (todayStrMinusCached = js_lib_1.localTime.now().plus(-15, 'hour').toISODate());
|
|
108
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/nodejs-lib",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.24.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky",
|
|
6
6
|
"docs-serve": "vuepress dev docs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"yargs": "^17.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@naturalcycles/bench-lib": "^
|
|
37
|
+
"@naturalcycles/bench-lib": "^3.0.0",
|
|
38
38
|
"@naturalcycles/dev-lib": "^13.0.0",
|
|
39
39
|
"@types/node": "^20.1.0",
|
|
40
40
|
"@types/yargs": "^16.0.0",
|
package/src/csv/csvReader.ts
CHANGED
|
@@ -56,7 +56,10 @@ export function csvStringParse<T extends AnyObject = any>(
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export function csvStringToArray(str: string): string[][] {
|
|
59
|
-
const objPattern = new RegExp(
|
|
59
|
+
const objPattern = new RegExp(
|
|
60
|
+
String.raw`(,|\r?\n|\r|^)(?:"([^"]*(?:""[^"]*)*)"|([^,\r\n]*))`,
|
|
61
|
+
'gi',
|
|
62
|
+
)
|
|
60
63
|
let matches: RegExpExecArray | null
|
|
61
64
|
const arr: any[][] = [[]]
|
|
62
65
|
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
CommonLogLevel,
|
|
7
7
|
Fetcher,
|
|
8
8
|
getFetcher,
|
|
9
|
-
|
|
9
|
+
localTime,
|
|
10
10
|
PQueue,
|
|
11
11
|
} from '@naturalcycles/js-lib'
|
|
12
12
|
import { _inspect, InspectAnyOptions } from '..'
|
|
@@ -180,7 +180,7 @@ export class SlackService<CTX = any> {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
export function slackDefaultMessagePrefixHook(msg: SlackMessage): string[] {
|
|
183
|
-
const tokens = [
|
|
183
|
+
const tokens = [localTime.now().toPretty()]
|
|
184
184
|
const { ctx } = msg
|
|
185
185
|
|
|
186
186
|
// AppEngine-specific decoration
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
_since,
|
|
5
5
|
AnyObject,
|
|
6
6
|
CommonLogger,
|
|
7
|
-
|
|
7
|
+
localTime,
|
|
8
8
|
SimpleMovingAverage,
|
|
9
9
|
UnixTimestampMillisNumber,
|
|
10
10
|
} from '@naturalcycles/js-lib'
|
|
@@ -294,7 +294,7 @@ export class ProgressLogger<T> implements Disposable {
|
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
logger.log(
|
|
297
|
-
`${dimGrey(
|
|
297
|
+
`${dimGrey(localTime.now().toPretty())} ${white(metric)} took ${yellow(
|
|
298
298
|
_since(this.started),
|
|
299
299
|
)} so far to process ${yellow(batchedProgress)} rows, ~${yellow(perHour)}/hour`,
|
|
300
300
|
)
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
_filterUndefinedValues,
|
|
3
3
|
AnyObject,
|
|
4
4
|
BuildInfo,
|
|
5
|
-
|
|
5
|
+
localTime,
|
|
6
6
|
UnixTimestampNumber,
|
|
7
7
|
} from '@naturalcycles/js-lib'
|
|
8
8
|
import { fs2 } from '../fs/fs2'
|
|
@@ -21,7 +21,7 @@ export interface GenerateBuildInfoOptions {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function generateBuildInfo(opt: GenerateBuildInfoOptions = {}): BuildInfo {
|
|
24
|
-
const now =
|
|
24
|
+
const now = localTime.orNow(opt.overrideTimestamp)
|
|
25
25
|
const ts = now.unix()
|
|
26
26
|
|
|
27
27
|
const rev = gitCurrentCommitSha()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { localTime } from '@naturalcycles/js-lib'
|
|
2
2
|
import Joi, { Extension, StringSchema as JoiStringSchema } from 'joi'
|
|
3
3
|
|
|
4
4
|
export interface StringSchema<TSchema = string> extends JoiStringSchema<TSchema> {
|
|
@@ -51,22 +51,21 @@ export function stringExtensions(joi: typeof Joi): Extension {
|
|
|
51
51
|
|
|
52
52
|
// Today allows +-14 hours gap to account for different timezones
|
|
53
53
|
if (max === 'today') {
|
|
54
|
-
max =
|
|
54
|
+
max = getTodayStrPlus15()
|
|
55
55
|
}
|
|
56
56
|
if (min === 'today') {
|
|
57
|
-
min =
|
|
57
|
+
min = getTodayStrMinus15()
|
|
58
58
|
}
|
|
59
59
|
// console.log('min/max', min, max)
|
|
60
60
|
|
|
61
|
-
const
|
|
62
|
-
if (!
|
|
61
|
+
const parts = /^(\d{4})-(\d{2})-(\d{2})$/.exec(v)
|
|
62
|
+
if (!parts || parts.length < 4) {
|
|
63
63
|
err = 'string.dateString'
|
|
64
64
|
} else if (min && v < min) {
|
|
65
65
|
err = 'string.dateStringMin'
|
|
66
66
|
} else if (max && v > max) {
|
|
67
67
|
err = 'string.dateStringMax'
|
|
68
|
-
} else if (!
|
|
69
|
-
// todo: replace with another regex (from ajv-validators) for speed
|
|
68
|
+
} else if (!isValidDate(parts)) {
|
|
70
69
|
err = 'string.dateStringCalendarAccuracy'
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -80,3 +79,48 @@ export function stringExtensions(joi: typeof Joi): Extension {
|
|
|
80
79
|
},
|
|
81
80
|
}
|
|
82
81
|
}
|
|
82
|
+
|
|
83
|
+
const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
84
|
+
// Based on: https://github.com/ajv-validator
|
|
85
|
+
function isValidDate(parts: string[]): boolean {
|
|
86
|
+
const year = Number(parts[1])
|
|
87
|
+
const month = Number(parts[2])
|
|
88
|
+
const day = Number(parts[3])
|
|
89
|
+
return (
|
|
90
|
+
month >= 1 &&
|
|
91
|
+
month <= 12 &&
|
|
92
|
+
day >= 1 &&
|
|
93
|
+
day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month]!)
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isLeapYear(year: number): boolean {
|
|
98
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let lastCheckedPlus = 0
|
|
102
|
+
let todayStrPlusCached: string
|
|
103
|
+
let lastCheckedMinus = 0
|
|
104
|
+
let todayStrMinusCached: string
|
|
105
|
+
|
|
106
|
+
function getTodayStrPlus15(): string {
|
|
107
|
+
const now = Date.now()
|
|
108
|
+
if (now - lastCheckedPlus < 3_600_000) {
|
|
109
|
+
// cached for 1 hour
|
|
110
|
+
return todayStrPlusCached
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
lastCheckedPlus = now
|
|
114
|
+
return (todayStrPlusCached = localTime.now().plus(15, 'hour').toISODate())
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function getTodayStrMinus15(): string {
|
|
118
|
+
const now = Date.now()
|
|
119
|
+
if (now - lastCheckedMinus < 3_600_000) {
|
|
120
|
+
// cached for 1 hour
|
|
121
|
+
return todayStrMinusCached
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
lastCheckedMinus = now
|
|
125
|
+
return (todayStrMinusCached = localTime.now().plus(-15, 'hour').toISODate())
|
|
126
|
+
}
|