@naturalcycles/nodejs-lib 15.7.0 → 15.8.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.
@@ -1,3 +1,4 @@
1
+ import { type ValidationFunctionResult } from '@naturalcycles/js-lib';
1
2
  import type { JsonSchema, JsonSchemaBuilder } from '@naturalcycles/js-lib/json-schema';
2
3
  import type { Ajv } from 'ajv';
3
4
  import { AjvValidationError } from './ajvValidationError.js';
@@ -62,7 +63,7 @@ export declare class AjvSchema<T = unknown> {
62
63
  *
63
64
  * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
64
65
  */
65
- validate(obj: T, opt?: AjvValidationOptions): T;
66
- isValid(obj: T): boolean;
67
- getValidationError(obj: T, opt?: AjvValidationOptions): AjvValidationError | undefined;
66
+ validate(input: T, opt?: AjvValidationOptions): T;
67
+ isValid(input: T): boolean;
68
+ getValidationResult(input: T, opt?: AjvValidationOptions): ValidationFunctionResult<T, AjvValidationError>;
68
69
  }
@@ -73,32 +73,33 @@ export class AjvSchema {
73
73
  *
74
74
  * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
75
75
  */
76
- validate(obj, opt = {}) {
77
- const err = this.getValidationError(obj, opt);
78
- if (err)
79
- throw err;
80
- return obj;
76
+ validate(input, opt = {}) {
77
+ const [error, output] = this.getValidationResult(input, opt);
78
+ if (error)
79
+ throw error;
80
+ return output;
81
81
  }
82
- isValid(obj) {
83
- return this.getValidateFunction()(obj);
82
+ isValid(input) {
83
+ return this.getValidateFunction()(input);
84
84
  }
85
- getValidationError(obj, opt = {}) {
86
- if (this.isValid(obj))
87
- return;
85
+ getValidationResult(input, opt = {}) {
86
+ if (this.isValid(input))
87
+ return [null, input];
88
88
  const errors = this.getValidateFunction().errors;
89
- const { objectId = _isObject(obj) ? obj['id'] : undefined, objectName = this.cfg.objectName, } = opt;
89
+ const { objectId = _isObject(input) ? input['id'] : undefined, objectName = this.cfg.objectName, } = opt;
90
90
  const name = [objectName || 'Object', objectId].filter(Boolean).join('.');
91
91
  let message = this.cfg.ajv.errorsText(errors, {
92
92
  dataVar: name,
93
93
  separator,
94
94
  });
95
- const inputStringified = _inspect(obj, { maxLen: 4000 });
95
+ const inputStringified = _inspect(input, { maxLen: 4000 });
96
96
  message = [message, 'Input: ' + inputStringified].join(separator);
97
- return new AjvValidationError(message, _filterNullishValues({
97
+ const err = new AjvValidationError(message, _filterNullishValues({
98
98
  errors,
99
99
  objectName,
100
100
  objectId,
101
101
  }));
102
+ return [err, input];
102
103
  }
103
104
  }
104
105
  const separator = '\n';
@@ -1,9 +1,6 @@
1
+ import { type ValidationFunctionResult } from '@naturalcycles/js-lib';
1
2
  import type { AnySchema, ValidationOptions } from 'joi';
2
3
  import { JoiValidationError } from './joi.validation.error.js';
3
- export interface JoiValidationResult<T = any> {
4
- value: T;
5
- error?: JoiValidationError;
6
- }
7
4
  /**
8
5
  * Validates with Joi.
9
6
  * Throws JoiValidationError if invalid.
@@ -21,7 +18,7 @@ export declare function validate<T>(input: any, schema?: AnySchema<T>, objectNam
21
18
  *
22
19
  * If `schema` is undefined - returns value as is.
23
20
  */
24
- export declare function getValidationResult<T>(input: any, schema?: AnySchema<T>, objectName?: string, options?: ValidationOptions): JoiValidationResult<T>;
21
+ export declare function getValidationResult<T>(input: T, schema?: AnySchema<T>, objectName?: string, options?: ValidationOptions): ValidationFunctionResult<T, JoiValidationError>;
25
22
  /**
26
23
  * Convenience function that returns true if !error.
27
24
  */
@@ -39,10 +39,9 @@ const defaultOptions = {
39
39
  * If `schema` is undefined - returns value as is.
40
40
  */
41
41
  export function validate(input, schema, objectName, opt = {}) {
42
- const { value: returnValue, error } = getValidationResult(input, schema, objectName, opt);
43
- if (error) {
42
+ const [error, returnValue] = getValidationResult(input, schema, objectName, opt);
43
+ if (error)
44
44
  throw error;
45
- }
46
45
  return returnValue;
47
46
  }
48
47
  /**
@@ -56,18 +55,13 @@ export function validate(input, schema, objectName, opt = {}) {
56
55
  */
57
56
  export function getValidationResult(input, schema, objectName, options = {}) {
58
57
  if (!schema)
59
- return { value: input };
58
+ return [null, input];
60
59
  const { value, error } = schema.validate(input, {
61
60
  ...defaultOptions,
62
61
  ...options,
63
62
  });
64
- const vr = {
65
- value,
66
- };
67
- if (error) {
68
- vr.error = createError(input, error, objectName);
69
- }
70
- return vr;
63
+ const err = error ? createError(input, error, objectName) : null;
64
+ return [err, value];
71
65
  }
72
66
  /**
73
67
  * Convenience function that returns true if !error.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.7.0",
4
+ "version": "15.8.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/through2-concurrent": "^2",
26
- "@naturalcycles/dev-lib": "18.4.2"
26
+ "@naturalcycles/dev-lib": "19.14.0"
27
27
  },
28
28
  "exports": {
29
29
  ".": "./dist/index.js",
@@ -1,4 +1,4 @@
1
- import { _isObject, _lazyValue } from '@naturalcycles/js-lib'
1
+ import { _isObject, _lazyValue, type ValidationFunctionResult } from '@naturalcycles/js-lib'
2
2
  import type { JsonSchema, JsonSchemaBuilder } from '@naturalcycles/js-lib/json-schema'
3
3
  import { JsonSchemaAnyBuilder } from '@naturalcycles/js-lib/json-schema'
4
4
  import { _filterNullishValues } from '@naturalcycles/js-lib/object'
@@ -124,23 +124,26 @@ export class AjvSchema<T = unknown> {
124
124
  *
125
125
  * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
126
126
  */
127
- validate(obj: T, opt: AjvValidationOptions = {}): T {
128
- const err = this.getValidationError(obj, opt)
129
- if (err) throw err
130
- return obj
127
+ validate(input: T, opt: AjvValidationOptions = {}): T {
128
+ const [error, output] = this.getValidationResult(input, opt)
129
+ if (error) throw error
130
+ return output
131
131
  }
132
132
 
133
- isValid(obj: T): boolean {
134
- return this.getValidateFunction()(obj)
133
+ isValid(input: T): boolean {
134
+ return this.getValidateFunction()(input)
135
135
  }
136
136
 
137
- getValidationError(obj: T, opt: AjvValidationOptions = {}): AjvValidationError | undefined {
138
- if (this.isValid(obj)) return
137
+ getValidationResult(
138
+ input: T,
139
+ opt: AjvValidationOptions = {},
140
+ ): ValidationFunctionResult<T, AjvValidationError> {
141
+ if (this.isValid(input)) return [null, input]
139
142
 
140
143
  const errors = this.getValidateFunction().errors!
141
144
 
142
145
  const {
143
- objectId = _isObject(obj) ? (obj['id' as keyof T] as any) : undefined,
146
+ objectId = _isObject(input) ? (input['id' as keyof T] as any) : undefined,
144
147
  objectName = this.cfg.objectName,
145
148
  } = opt
146
149
  const name = [objectName || 'Object', objectId].filter(Boolean).join('.')
@@ -150,10 +153,10 @@ export class AjvSchema<T = unknown> {
150
153
  separator,
151
154
  })
152
155
 
153
- const inputStringified = _inspect(obj, { maxLen: 4000 })
156
+ const inputStringified = _inspect(input, { maxLen: 4000 })
154
157
  message = [message, 'Input: ' + inputStringified].join(separator)
155
158
 
156
- return new AjvValidationError(
159
+ const err = new AjvValidationError(
157
160
  message,
158
161
  _filterNullishValues({
159
162
  errors,
@@ -161,6 +164,7 @@ export class AjvSchema<T = unknown> {
161
164
  objectId,
162
165
  }),
163
166
  )
167
+ return [err, input]
164
168
  }
165
169
  }
166
170
 
@@ -6,18 +6,12 @@
6
6
  * "Converts" mean e.g trims all strings from leading/trailing spaces.
7
7
  */
8
8
 
9
- import { _hb, _isObject } from '@naturalcycles/js-lib'
9
+ import { _hb, _isObject, type ValidationFunctionResult } from '@naturalcycles/js-lib'
10
10
  import { _truncateMiddle } from '@naturalcycles/js-lib/string/string.util.js'
11
11
  import type { AnySchema, ValidationError, ValidationOptions } from 'joi'
12
12
  import type { JoiValidationErrorData } from './joi.validation.error.js'
13
13
  import { JoiValidationError } from './joi.validation.error.js'
14
14
 
15
- // todo: consider replacing with Tuple of [error, value]
16
- export interface JoiValidationResult<T = any> {
17
- value: T
18
- error?: JoiValidationError
19
- }
20
-
21
15
  // Strip colors in production (for e.g Sentry reporting)
22
16
  // const stripColors = process.env.NODE_ENV === 'production' || !!process.env.GAE_INSTANCE
23
17
  // Currently colors do more bad than good, so let's strip them always for now
@@ -56,12 +50,8 @@ export function validate<T>(
56
50
  objectName?: string,
57
51
  opt: ValidationOptions = {},
58
52
  ): T {
59
- const { value: returnValue, error } = getValidationResult(input, schema, objectName, opt)
60
-
61
- if (error) {
62
- throw error
63
- }
64
-
53
+ const [error, returnValue] = getValidationResult(input, schema, objectName, opt)
54
+ if (error) throw error
65
55
  return returnValue
66
56
  }
67
57
 
@@ -75,27 +65,20 @@ export function validate<T>(
75
65
  * If `schema` is undefined - returns value as is.
76
66
  */
77
67
  export function getValidationResult<T>(
78
- input: any,
68
+ input: T,
79
69
  schema?: AnySchema<T>,
80
70
  objectName?: string,
81
71
  options: ValidationOptions = {},
82
- ): JoiValidationResult<T> {
83
- if (!schema) return { value: input }
72
+ ): ValidationFunctionResult<T, JoiValidationError> {
73
+ if (!schema) return [null, input]
84
74
 
85
75
  const { value, error } = schema.validate(input, {
86
76
  ...defaultOptions,
87
77
  ...options,
88
78
  })
89
79
 
90
- const vr: JoiValidationResult<T> = {
91
- value,
92
- }
93
-
94
- if (error) {
95
- vr.error = createError(input, error, objectName)
96
- }
97
-
98
- return vr
80
+ const err = error ? createError(input, error, objectName) : null
81
+ return [err, value]
99
82
  }
100
83
 
101
84
  /**
@@ -1,89 +0,0 @@
1
- const started = Date.now()
2
- import { workerData, parentPort } from 'node:worker_threads'
3
- import { inspect } from 'node:util'
4
- const { workerFile, workerIndex, logEvery = 1000, metric = 'worker' } = workerData || {}
5
-
6
- if (!workerFile) {
7
- throw new Error('workerData.workerFile is required!')
8
- }
9
-
10
- // console.log(`worker#${workerIndex} created`)
11
-
12
- try {
13
- // require('esbuild-register') // alternative
14
- // require('ts-node/register/transpile-only')
15
- // require('tsx/cjs/api').register() // https://tsx.is/dev-api/register-cjs
16
- const { register } = await import('tsx/esm/api')
17
- register() // https://tsx.is/dev-api/register-esm
18
- // require('tsconfig-paths/register')
19
- } catch {} // require if exists
20
-
21
- const { WorkerClass } = await import(workerFile)
22
- const worker = new WorkerClass(workerData)
23
-
24
- console.log(`${metric}#${workerIndex} loaded in ${Date.now() - started} ms`)
25
-
26
- let errors = 0
27
- let processed = 0
28
-
29
- parentPort.on('message', async msg => {
30
- if (msg === null) {
31
- // console.log(`EXIT (null) received by ${index}, exiting`)
32
- parentPort.close()
33
-
34
- logStats(true)
35
-
36
- return
37
- }
38
-
39
- // console.log(`message received by worker ${index}: `, msg)
40
-
41
- try {
42
- const out = await worker.process(msg.payload, msg.index)
43
-
44
- parentPort.postMessage({
45
- index: msg.index,
46
- payload: out,
47
- })
48
-
49
- processed++
50
-
51
- if (processed % logEvery === 0) logStats()
52
- } catch (err) {
53
- parentPort.postMessage({
54
- index: msg.index,
55
- error: err,
56
- })
57
-
58
- errors++
59
- console.log(`${metric}#${workerIndex} errors: ${errors}`)
60
- }
61
- })
62
-
63
- const inspectOpt = {
64
- colors: true,
65
- breakLength: 120,
66
- }
67
-
68
- function logStats(final) {
69
- const { rss, heapUsed, heapTotal, external } = process.memoryUsage()
70
-
71
- console.log(
72
- inspect(
73
- {
74
- [`${metric}${workerIndex}`]: processed,
75
- errors,
76
- heapUsed: mb(heapUsed),
77
- heapTotal: mb(heapTotal),
78
- rss: mb(rss),
79
- external: mb(external),
80
- ...(final ? { final: true } : {}),
81
- },
82
- inspectOpt,
83
- ),
84
- )
85
- }
86
-
87
- function mb(b) {
88
- return Math.round(b / (1024 * 1024))
89
- }