@naturalcycles/js-lib 15.19.0 → 15.21.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,30 +1,30 @@
1
1
  import type { AppError } from '../error/error.util.js';
2
- import type { ErrorDataTuple } from '../types.js';
3
2
  /**
4
- * Item to be validated.
5
- * Can be null or undefined, which allows validation function to produce an error,
6
- * if undefined/null are not accepted. But they might be accepted too, it depends
7
- * on the schema (implementation detail of the ValidationFunction).
3
+ * Function returns a tuple of [err, output].
8
4
  *
9
- * Function returns a tuple of [err, item].
10
- * In case of error it will be [err, null].
11
- * In case of success it is [null, item].
5
+ * If ERR is returned, it indicates that validation has failed.
6
+ * If ERR is null - validation has succeeded.
7
+ *
8
+ * Regardless of the Error, ValidationFunction always returns the output item.
9
+ *
10
+ * Output item may be transformed or not, depending on the implementation.
12
11
  *
13
12
  * ValidationFunction may mutate the input item or not,
14
13
  * depending on the implementation.
15
14
  *
16
15
  * @experimental
17
16
  */
18
- export type ValidationFunction<T, ERR extends AppError> = (item: T | null | undefined, opt?: ValidationFunctionOptions) => ErrorDataTuple<T, ERR>;
17
+ export type ValidationFunction<T, ERR extends AppError> = (input: T, opt?: ValidationFunctionOptions) => ValidationFunctionResult<T, ERR>;
18
+ export type ValidationFunctionResult<T, ERR extends AppError> = [err: ERR | null, output: T];
19
19
  export interface ValidationFunctionOptions {
20
20
  /**
21
21
  * E.g User
22
22
  * Used for error message printing.
23
23
  */
24
- itemName?: string;
24
+ inputName?: string;
25
25
  /**
26
26
  * E.g `12345678` (user id).
27
27
  * Used for error message printing.
28
28
  */
29
- itemId?: string;
29
+ inputId?: string;
30
30
  }
@@ -1,3 +1,4 @@
1
+ import type { ZodString } from 'zod';
1
2
  import { z } from 'zod';
2
3
  import type { IsoDate, UnixTimestamp, UnixTimestampMillis } from '../types.js';
3
4
  type ZodBranded<T, B> = T & Record<'_zod', Record<'output', number & B>>;
@@ -26,10 +27,23 @@ export declare const zJwt: () => z.ZodString;
26
27
  */
27
28
  export declare const zSlug: () => z.ZodString;
28
29
  export declare const zIanaTimezone: () => z.ZodEnum;
30
+ export declare const zBaseDBEntity: () => z.ZodObject<{
31
+ id: ZodString;
32
+ created: ZodBrandedInt<UnixTimestamp>;
33
+ updated: ZodBrandedInt<UnixTimestamp>;
34
+ }>;
35
+ type BaseDBEntityZodShape = {
36
+ id: ZodString;
37
+ created: ZodBrandedInt<UnixTimestamp>;
38
+ updated: ZodBrandedInt<UnixTimestamp>;
39
+ };
40
+ declare function zDBEntity(): z.ZodObject<BaseDBEntityZodShape>;
41
+ declare function zDBEntity<T extends z.ZodRawShape>(shape: T): z.ZodObject<BaseDBEntityZodShape & T>;
29
42
  export declare const customZodSchemas: {
30
43
  base62: () => z.ZodString;
31
44
  base64: () => z.ZodString;
32
45
  base64Url: () => z.ZodString;
46
+ dbEntity: typeof zDBEntity;
33
47
  email: () => z.ZodEmail;
34
48
  ianaTimezone: () => z.ZodEnum;
35
49
  isoDate: () => ZodBrandedString<IsoDate>;
@@ -54,10 +54,21 @@ export const zSlug = () => z
54
54
  export const zIanaTimezone = () => z
55
55
  // UTC is added to assist unit-testing, which uses UTC by default (not technically a valid Iana timezone identifier)
56
56
  .enum([...Intl.supportedValuesOf('timeZone'), 'UTC']);
57
+ export const zBaseDBEntity = () => {
58
+ return z.object({
59
+ id: z.string(),
60
+ created: zUnixTimestamp2000(),
61
+ updated: zUnixTimestamp2000(),
62
+ });
63
+ };
64
+ function zDBEntity(shape) {
65
+ return zBaseDBEntity().extend(shape ?? {});
66
+ }
57
67
  export const customZodSchemas = {
58
68
  base62: zBase62,
59
69
  base64: zBase64,
60
70
  base64Url: zBase64Url,
71
+ dbEntity: zDBEntity,
61
72
  email: zEmail,
62
73
  ianaTimezone: zIanaTimezone,
63
74
  isoDate: zIsoDate,
@@ -1,19 +1,10 @@
1
1
  import type { ZodError, ZodType } from 'zod';
2
2
  import type { ErrorData } from '../error/error.model.js';
3
3
  import { AppError } from '../error/error.util.js';
4
- export interface ZodErrorResult<T> {
5
- success: false;
6
- data?: T;
7
- error: ZodValidationError;
8
- }
9
- export interface ZodSuccessResult<T> {
10
- success: true;
11
- data: T;
12
- error?: ZodValidationError;
13
- }
4
+ import type { ValidationFunctionResult } from '../validation/validation.js';
14
5
  export declare function zIsValid<T>(value: T, schema: ZodType<T>): boolean;
15
6
  export declare function zValidate<T>(value: T, schema: ZodType<T>): T;
16
- export declare function zSafeValidate<T>(value: T, schema: ZodType<T>): ZodSuccessResult<T> | ZodErrorResult<T>;
7
+ export declare function zSafeValidate<T>(input: T, schema: ZodType<T>): ValidationFunctionResult<T, ZodValidationError>;
17
8
  export interface ZodValidationErrorData extends ErrorData {
18
9
  }
19
10
  export declare class ZodValidationError extends AppError<ZodValidationErrorData> {
@@ -5,21 +5,17 @@ export function zIsValid(value, schema) {
5
5
  return success;
6
6
  }
7
7
  export function zValidate(value, schema) {
8
- const r = zSafeValidate(value, schema);
9
- if (r.success) {
10
- return r.data;
11
- }
12
- throw r.error;
8
+ const [err, data] = zSafeValidate(value, schema);
9
+ if (err)
10
+ throw err;
11
+ return data;
13
12
  }
14
- export function zSafeValidate(value, schema) {
15
- const r = schema.safeParse(value);
13
+ export function zSafeValidate(input, schema) {
14
+ const r = schema.safeParse(input);
16
15
  if (r.success) {
17
- return r;
16
+ return [null, r.data];
18
17
  }
19
- return {
20
- success: false,
21
- error: new ZodValidationError(r.error, value, schema),
22
- };
18
+ return [new ZodValidationError(r.error, input, schema), r.data ?? input];
23
19
  }
24
20
  export class ZodValidationError extends AppError {
25
21
  constructor(zodError, value, schema) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.19.0",
4
+ "version": "15.21.0",
5
5
  "dependencies": {
6
6
  "tslib": "^2",
7
7
  "zod": "^4"
@@ -180,7 +180,11 @@ export function _stringify(obj: any, opt: StringifyOptions = {}): string {
180
180
  // Handle maxLen
181
181
  const { maxLen = 10_000 } = opt
182
182
  if (maxLen && s.length > maxLen) {
183
- return _truncateMiddle(s, maxLen, `\n... ${Math.ceil(s.length / 1024)} Kb message truncated ...\n`)
183
+ return _truncateMiddle(
184
+ s,
185
+ maxLen,
186
+ `\n... ${Math.ceil(s.length / 1024)} Kb message truncated ...\n`,
187
+ )
184
188
  }
185
189
 
186
190
  return s
@@ -1,15 +1,14 @@
1
1
  import type { AppError } from '../error/error.util.js'
2
- import type { ErrorDataTuple } from '../types.js'
3
2
 
4
3
  /**
5
- * Item to be validated.
6
- * Can be null or undefined, which allows validation function to produce an error,
7
- * if undefined/null are not accepted. But they might be accepted too, it depends
8
- * on the schema (implementation detail of the ValidationFunction).
4
+ * Function returns a tuple of [err, output].
9
5
  *
10
- * Function returns a tuple of [err, item].
11
- * In case of error it will be [err, null].
12
- * In case of success it is [null, item].
6
+ * If ERR is returned, it indicates that validation has failed.
7
+ * If ERR is null - validation has succeeded.
8
+ *
9
+ * Regardless of the Error, ValidationFunction always returns the output item.
10
+ *
11
+ * Output item may be transformed or not, depending on the implementation.
13
12
  *
14
13
  * ValidationFunction may mutate the input item or not,
15
14
  * depending on the implementation.
@@ -17,19 +16,21 @@ import type { ErrorDataTuple } from '../types.js'
17
16
  * @experimental
18
17
  */
19
18
  export type ValidationFunction<T, ERR extends AppError> = (
20
- item: T | null | undefined,
19
+ input: T,
21
20
  opt?: ValidationFunctionOptions,
22
- ) => ErrorDataTuple<T, ERR>
21
+ ) => ValidationFunctionResult<T, ERR>
22
+
23
+ export type ValidationFunctionResult<T, ERR extends AppError> = [err: ERR | null, output: T]
23
24
 
24
25
  export interface ValidationFunctionOptions {
25
26
  /**
26
27
  * E.g User
27
28
  * Used for error message printing.
28
29
  */
29
- itemName?: string
30
+ inputName?: string
30
31
  /**
31
32
  * E.g `12345678` (user id).
32
33
  * Used for error message printing.
33
34
  */
34
- itemId?: string
35
+ inputId?: string
35
36
  }
@@ -1,3 +1,4 @@
1
+ import type { ZodString } from 'zod'
1
2
  import { z } from 'zod'
2
3
  import type { IsoDate, UnixTimestamp, UnixTimestampMillis } from '../types.js'
3
4
 
@@ -88,10 +89,37 @@ export const zIanaTimezone = (): z.ZodEnum =>
88
89
  // UTC is added to assist unit-testing, which uses UTC by default (not technically a valid Iana timezone identifier)
89
90
  .enum([...Intl.supportedValuesOf('timeZone'), 'UTC'])
90
91
 
92
+ export const zBaseDBEntity = (): z.ZodObject<{
93
+ id: ZodString
94
+ created: ZodBrandedInt<UnixTimestamp>
95
+ updated: ZodBrandedInt<UnixTimestamp>
96
+ }> => {
97
+ return z.object({
98
+ id: z.string(),
99
+ created: zUnixTimestamp2000(),
100
+ updated: zUnixTimestamp2000(),
101
+ })
102
+ }
103
+
104
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
105
+ type BaseDBEntityZodShape = {
106
+ id: ZodString
107
+ created: ZodBrandedInt<UnixTimestamp>
108
+ updated: ZodBrandedInt<UnixTimestamp>
109
+ }
110
+
111
+ function zDBEntity(): z.ZodObject<BaseDBEntityZodShape>
112
+ function zDBEntity<T extends z.ZodRawShape>(shape: T): z.ZodObject<BaseDBEntityZodShape & T>
113
+
114
+ function zDBEntity<T extends z.ZodRawShape>(shape?: T): z.ZodObject<BaseDBEntityZodShape & T> {
115
+ return zBaseDBEntity().extend(shape ?? {}) as z.ZodObject<BaseDBEntityZodShape & T>
116
+ }
117
+
91
118
  export const customZodSchemas = {
92
119
  base62: zBase62,
93
120
  base64: zBase64,
94
121
  base64Url: zBase64Url,
122
+ dbEntity: zDBEntity,
95
123
  email: zEmail,
96
124
  ianaTimezone: zIanaTimezone,
97
125
  isoDate: zIsoDate,
@@ -2,18 +2,7 @@ import type { ZodError, ZodType } from 'zod'
2
2
  import type { ErrorData } from '../error/error.model.js'
3
3
  import { AppError } from '../error/error.util.js'
4
4
  import { _stringify } from '../string/stringify.js'
5
-
6
- export interface ZodErrorResult<T> {
7
- success: false
8
- data?: T
9
- error: ZodValidationError
10
- }
11
-
12
- export interface ZodSuccessResult<T> {
13
- success: true
14
- data: T
15
- error?: ZodValidationError
16
- }
5
+ import type { ValidationFunctionResult } from '../validation/validation.js'
17
6
 
18
7
  export function zIsValid<T>(value: T, schema: ZodType<T>): boolean {
19
8
  const { success } = schema.safeParse(value)
@@ -21,28 +10,22 @@ export function zIsValid<T>(value: T, schema: ZodType<T>): boolean {
21
10
  }
22
11
 
23
12
  export function zValidate<T>(value: T, schema: ZodType<T>): T {
24
- const r = zSafeValidate(value, schema)
25
- if (r.success) {
26
- return r.data
27
- }
28
-
29
- throw r.error
13
+ const [err, data] = zSafeValidate(value, schema)
14
+ if (err) throw err
15
+ return data
30
16
  }
31
17
 
32
18
  export function zSafeValidate<T>(
33
- value: T,
19
+ input: T,
34
20
  schema: ZodType<T>,
35
21
  // objectName?: string,
36
- ): ZodSuccessResult<T> | ZodErrorResult<T> {
37
- const r = schema.safeParse(value)
22
+ ): ValidationFunctionResult<T, ZodValidationError> {
23
+ const r = schema.safeParse(input)
38
24
  if (r.success) {
39
- return r
25
+ return [null, r.data]
40
26
  }
41
27
 
42
- return {
43
- success: false,
44
- error: new ZodValidationError(r.error, value, schema),
45
- }
28
+ return [new ZodValidationError(r.error, input, schema), r.data ?? input]
46
29
  }
47
30
 
48
31
  export interface ZodValidationErrorData extends ErrorData {