@naturalcycles/js-lib 14.128.1 → 14.129.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/dist/index.d.ts CHANGED
@@ -59,7 +59,6 @@ export * from './is.util';
59
59
  export * from './typeFest';
60
60
  export * from './types';
61
61
  export * from './unit/size.util';
62
- import { is } from './vendor/is';
63
62
  export * from './log/commonLogger';
64
63
  export * from './string/safeJsonStringify';
65
64
  export * from './promise/pQueue';
@@ -77,4 +76,9 @@ export * from './datetime/timeInterval';
77
76
  export * from './http/http.model';
78
77
  export * from './http/fetcher';
79
78
  export * from './http/fetcher.model';
80
- export { is };
79
+ export * from './zod/zod.util';
80
+ export * from './zod/zod.shared.schemas';
81
+ import { z, ZodSchema, ZodError, ZodIssue } from 'zod';
82
+ import { is } from './vendor/is';
83
+ export { is, z, ZodSchema, ZodError };
84
+ export type { ZodIssue };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.is = void 0;
3
+ exports.ZodError = exports.ZodSchema = exports.z = exports.is = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  tslib_1.__exportStar(require("./array/array.util"), exports);
6
6
  tslib_1.__exportStar(require("./lazy"), exports);
@@ -63,8 +63,6 @@ tslib_1.__exportStar(require("./is.util"), exports);
63
63
  tslib_1.__exportStar(require("./typeFest"), exports);
64
64
  tslib_1.__exportStar(require("./types"), exports);
65
65
  tslib_1.__exportStar(require("./unit/size.util"), exports);
66
- const is_1 = require("./vendor/is");
67
- Object.defineProperty(exports, "is", { enumerable: true, get: function () { return is_1.is; } });
68
66
  tslib_1.__exportStar(require("./log/commonLogger"), exports);
69
67
  tslib_1.__exportStar(require("./string/safeJsonStringify"), exports);
70
68
  tslib_1.__exportStar(require("./promise/pQueue"), exports);
@@ -82,3 +80,11 @@ tslib_1.__exportStar(require("./datetime/timeInterval"), exports);
82
80
  tslib_1.__exportStar(require("./http/http.model"), exports);
83
81
  tslib_1.__exportStar(require("./http/fetcher"), exports);
84
82
  tslib_1.__exportStar(require("./http/fetcher.model"), exports);
83
+ tslib_1.__exportStar(require("./zod/zod.util"), exports);
84
+ tslib_1.__exportStar(require("./zod/zod.shared.schemas"), exports);
85
+ const zod_1 = require("zod");
86
+ Object.defineProperty(exports, "z", { enumerable: true, get: function () { return zod_1.z; } });
87
+ Object.defineProperty(exports, "ZodSchema", { enumerable: true, get: function () { return zod_1.ZodSchema; } });
88
+ Object.defineProperty(exports, "ZodError", { enumerable: true, get: function () { return zod_1.ZodError; } });
89
+ const is_1 = require("./vendor/is");
90
+ Object.defineProperty(exports, "is", { enumerable: true, get: function () { return is_1.is; } });
@@ -0,0 +1,52 @@
1
+ import { z } from 'zod';
2
+ export declare const TS_2500 = 16725225600;
3
+ export declare const TS_2000 = 946684800;
4
+ export declare const zUnixTimestamp: z.ZodNumber;
5
+ export declare const zUnixTimestamp2000: z.ZodNumber;
6
+ export declare const zUnixTimestampMillis: z.ZodNumber;
7
+ export declare const zUnixTimestampMillis2000: z.ZodNumber;
8
+ export declare const zSemVer: z.ZodString;
9
+ export declare const zIsoDateString: z.ZodEffects<z.ZodString, string, string>;
10
+ export declare const zEmail: z.ZodEffects<z.ZodString, string, string>;
11
+ export declare const BASE62_REGEX: RegExp;
12
+ export declare const BASE64_REGEX: RegExp;
13
+ export declare const BASE64URL_REGEX: RegExp;
14
+ export declare const zBase62: z.ZodString;
15
+ export declare const zBase64: z.ZodString;
16
+ export declare const zBase64Url: z.ZodString;
17
+ export declare const JWT_REGEX: RegExp;
18
+ export declare const zJwt: z.ZodString;
19
+ export declare const zId: z.ZodString;
20
+ export declare const zIdBase62: z.ZodString;
21
+ export declare const zIdBase64: z.ZodString;
22
+ export declare const zIdBase64Url: z.ZodString;
23
+ /**
24
+ * "Slug" - a valid URL, filename, etc.
25
+ */
26
+ export declare const zSlug: z.ZodString;
27
+ export declare const zBaseDBEntity: z.ZodObject<{
28
+ id: z.ZodOptional<z.ZodString>;
29
+ created: z.ZodOptional<z.ZodNumber>;
30
+ updated: z.ZodOptional<z.ZodNumber>;
31
+ }, "strip", z.ZodTypeAny, {
32
+ id?: string | undefined;
33
+ created?: number | undefined;
34
+ updated?: number | undefined;
35
+ }, {
36
+ id?: string | undefined;
37
+ created?: number | undefined;
38
+ updated?: number | undefined;
39
+ }>;
40
+ export declare const zSavedDBEntity: z.ZodObject<{
41
+ id: z.ZodString;
42
+ created: z.ZodNumber;
43
+ updated: z.ZodNumber;
44
+ }, "strip", z.ZodTypeAny, {
45
+ id: string;
46
+ created: number;
47
+ updated: number;
48
+ }, {
49
+ id: string;
50
+ created: number;
51
+ updated: number;
52
+ }>;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.zSavedDBEntity = exports.zBaseDBEntity = exports.zSlug = exports.zIdBase64Url = exports.zIdBase64 = exports.zIdBase62 = exports.zId = exports.zJwt = exports.JWT_REGEX = exports.zBase64Url = exports.zBase64 = exports.zBase62 = exports.BASE64URL_REGEX = exports.BASE64_REGEX = exports.BASE62_REGEX = exports.zEmail = exports.zIsoDateString = exports.zSemVer = exports.zUnixTimestampMillis2000 = exports.zUnixTimestampMillis = exports.zUnixTimestamp2000 = exports.zUnixTimestamp = exports.TS_2000 = exports.TS_2500 = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.TS_2500 = 16725225600; // 2500-01-01
6
+ exports.TS_2000 = 946684800; // 2000-01-01
7
+ exports.zUnixTimestamp = zod_1.z
8
+ .number()
9
+ .int()
10
+ .min(0)
11
+ .max(exports.TS_2500, 'Must be a UnixTimestamp number')
12
+ .describe('UnixTimestamp');
13
+ exports.zUnixTimestamp2000 = zod_1.z
14
+ .number()
15
+ .int()
16
+ .min(exports.TS_2000)
17
+ .max(exports.TS_2500, 'Must be a UnixTimestamp number after 2000-01-01')
18
+ .describe('UnixTimestamp2000');
19
+ exports.zUnixTimestampMillis = zod_1.z
20
+ .number()
21
+ .int()
22
+ .min(0)
23
+ .max(exports.TS_2500 * 1000, 'Must be a UnixTimestampMillis number')
24
+ .describe('UnixTimestampMillis');
25
+ exports.zUnixTimestampMillis2000 = zod_1.z
26
+ .number()
27
+ .int()
28
+ .min(exports.TS_2000 * 1000)
29
+ .max(exports.TS_2500 * 1000, 'Must be a UnixTimestampMillis number after 2000-01-01')
30
+ .describe('UnixTimestampMillis2000');
31
+ exports.zSemVer = zod_1.z
32
+ .string()
33
+ .regex(/^[0-9]+\.[0-9]+\.[0-9]+$/, 'Must be a SemVer string')
34
+ .describe('SemVer');
35
+ exports.zIsoDateString = zod_1.z
36
+ .string()
37
+ .refine(v => {
38
+ return /^\d{4}-\d{2}-\d{2}$/.test(v);
39
+ }, 'Must be an IsoDateString')
40
+ .describe('IsoDateString');
41
+ exports.zEmail = zod_1.z
42
+ .string()
43
+ .trim()
44
+ .email()
45
+ .transform(s => s.toLowerCase())
46
+ .describe('Email');
47
+ exports.BASE62_REGEX = /^[a-zA-Z0-9]+$/;
48
+ exports.BASE64_REGEX = /^[A-Za-z0-9+/]+={0,2}$/;
49
+ exports.BASE64URL_REGEX = /^[\w-/]+$/;
50
+ exports.zBase62 = zod_1.z
51
+ .string()
52
+ .regex(exports.BASE62_REGEX, 'Must be a base62 string')
53
+ .describe('Base62String');
54
+ exports.zBase64 = zod_1.z
55
+ .string()
56
+ .regex(exports.BASE64_REGEX, 'Must be a base64 string')
57
+ .describe('Base64String');
58
+ exports.zBase64Url = zod_1.z
59
+ .string()
60
+ .regex(exports.BASE64URL_REGEX, 'Must be a base64url string')
61
+ .describe('Base64UrlString');
62
+ exports.JWT_REGEX = /^[\w-]+\.[\w-]+\.[\w-]+$/;
63
+ exports.zJwt = zod_1.z.string().regex(exports.JWT_REGEX, 'Must be a JWT string').describe('JWTString');
64
+ exports.zId = zod_1.z
65
+ .string()
66
+ .regex(/^[a-zA-Z0-9_]{6,64}$/, 'Must be an id string')
67
+ .describe('IdString');
68
+ exports.zIdBase62 = zod_1.z
69
+ .string()
70
+ .regex(/^[a-zA-Z0-9]{8,64}$/, 'Must be a base62 id string')
71
+ .describe('Base62Id');
72
+ exports.zIdBase64 = zod_1.z
73
+ .string()
74
+ .regex(/^[A-Za-z0-9+/]{6,62}={0,2}$/, 'Must be a base64 id string')
75
+ .describe('Base64Id');
76
+ exports.zIdBase64Url = zod_1.z
77
+ .string()
78
+ .regex(/^[\w-/]{8,64}$/, 'Must be a base64url id string')
79
+ .describe('Base64UrlId');
80
+ /**
81
+ * "Slug" - a valid URL, filename, etc.
82
+ */
83
+ exports.zSlug = zod_1.z
84
+ .string()
85
+ .regex(/^[a-z0-9-]{1,255}$/, 'Must be a slug string')
86
+ .describe('Slug');
87
+ exports.zBaseDBEntity = zod_1.z
88
+ .object({
89
+ id: zod_1.z.string().optional(),
90
+ created: exports.zUnixTimestamp2000.optional(),
91
+ updated: exports.zUnixTimestamp2000.optional(),
92
+ })
93
+ .describe('BaseDBEntity');
94
+ exports.zSavedDBEntity = exports.zBaseDBEntity.required().describe('SavedDBEntity');
@@ -0,0 +1,21 @@
1
+ import { ZodError, ZodSchema, ZodIssue } from 'zod';
2
+ export interface ZodErrorResult<T> {
3
+ success: false;
4
+ data?: T;
5
+ error: ZodValidationError<T>;
6
+ }
7
+ export interface ZodSuccessResult<T> {
8
+ success: true;
9
+ data: T;
10
+ error?: ZodValidationError<T>;
11
+ }
12
+ export declare function zIsValid<T>(value: T, schema: ZodSchema<T>): boolean;
13
+ export declare function zValidate<T>(value: T, schema: ZodSchema<T>): T;
14
+ export declare function zSafeValidate<T>(value: T, schema: ZodSchema<T>): ZodSuccessResult<T> | ZodErrorResult<T>;
15
+ export declare class ZodValidationError<T> extends ZodError<T> {
16
+ value: T;
17
+ schema: ZodSchema<T>;
18
+ constructor(issues: ZodIssue[], value: T, schema: ZodSchema<T>);
19
+ get message(): string;
20
+ annotate(): string;
21
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZodValidationError = exports.zSafeValidate = exports.zValidate = exports.zIsValid = void 0;
4
+ const zod_1 = require("zod");
5
+ const stringifyAny_1 = require("../string/stringifyAny");
6
+ function zIsValid(value, schema) {
7
+ const { success } = schema.safeParse(value);
8
+ return success;
9
+ }
10
+ exports.zIsValid = zIsValid;
11
+ function zValidate(value, schema) {
12
+ const r = zSafeValidate(value, schema);
13
+ if (r.success) {
14
+ return r.data;
15
+ }
16
+ throw r.error;
17
+ }
18
+ exports.zValidate = zValidate;
19
+ function zSafeValidate(value, schema) {
20
+ const r = schema.safeParse(value);
21
+ if (r.success) {
22
+ return r;
23
+ }
24
+ return {
25
+ success: false,
26
+ error: new ZodValidationError(r.error.issues, value, schema),
27
+ };
28
+ }
29
+ exports.zSafeValidate = zSafeValidate;
30
+ class ZodValidationError extends zod_1.ZodError {
31
+ constructor(issues, value, schema) {
32
+ super(issues);
33
+ this.value = value;
34
+ this.schema = schema;
35
+ }
36
+ get message() {
37
+ return this.annotate();
38
+ }
39
+ annotate() {
40
+ let objectTitle = this.schema.description;
41
+ if (typeof this.value === 'object' && this.value) {
42
+ const objectName = this.schema.description || this.value.constructor?.name;
43
+ const objectId = this.value['id'];
44
+ objectTitle = [objectName, objectId].filter(Boolean).join('.');
45
+ }
46
+ objectTitle ||= 'data';
47
+ return [
48
+ `Invalid ${objectTitle}`,
49
+ '',
50
+ 'Input:',
51
+ (0, stringifyAny_1._stringifyAny)(this.value),
52
+ this.issues.length > 1 ? `\n${this.issues.length} issues:` : '',
53
+ ...this.issues.slice(0, 100).map(i => {
54
+ return [i.path.join('.'), i.message].filter(Boolean).join(': ');
55
+ }),
56
+ ].join('\n');
57
+ }
58
+ }
59
+ exports.ZodValidationError = ZodValidationError;
package/dist-esm/index.js CHANGED
@@ -59,7 +59,6 @@ export * from './is.util';
59
59
  export * from './typeFest';
60
60
  export * from './types';
61
61
  export * from './unit/size.util';
62
- import { is } from './vendor/is';
63
62
  export * from './log/commonLogger';
64
63
  export * from './string/safeJsonStringify';
65
64
  export * from './promise/pQueue';
@@ -77,4 +76,8 @@ export * from './datetime/timeInterval';
77
76
  export * from './http/http.model';
78
77
  export * from './http/fetcher';
79
78
  export * from './http/fetcher.model';
80
- export { is };
79
+ export * from './zod/zod.util';
80
+ export * from './zod/zod.shared.schemas';
81
+ import { z, ZodSchema, ZodError } from 'zod';
82
+ import { is } from './vendor/is';
83
+ export { is, z, ZodSchema, ZodError };
@@ -0,0 +1,91 @@
1
+ import { z } from 'zod';
2
+ export const TS_2500 = 16725225600; // 2500-01-01
3
+ export const TS_2000 = 946684800; // 2000-01-01
4
+ export const zUnixTimestamp = z
5
+ .number()
6
+ .int()
7
+ .min(0)
8
+ .max(TS_2500, 'Must be a UnixTimestamp number')
9
+ .describe('UnixTimestamp');
10
+ export const zUnixTimestamp2000 = z
11
+ .number()
12
+ .int()
13
+ .min(TS_2000)
14
+ .max(TS_2500, 'Must be a UnixTimestamp number after 2000-01-01')
15
+ .describe('UnixTimestamp2000');
16
+ export const zUnixTimestampMillis = z
17
+ .number()
18
+ .int()
19
+ .min(0)
20
+ .max(TS_2500 * 1000, 'Must be a UnixTimestampMillis number')
21
+ .describe('UnixTimestampMillis');
22
+ export const zUnixTimestampMillis2000 = z
23
+ .number()
24
+ .int()
25
+ .min(TS_2000 * 1000)
26
+ .max(TS_2500 * 1000, 'Must be a UnixTimestampMillis number after 2000-01-01')
27
+ .describe('UnixTimestampMillis2000');
28
+ export const zSemVer = z
29
+ .string()
30
+ .regex(/^[0-9]+\.[0-9]+\.[0-9]+$/, 'Must be a SemVer string')
31
+ .describe('SemVer');
32
+ export const zIsoDateString = z
33
+ .string()
34
+ .refine(v => {
35
+ return /^\d{4}-\d{2}-\d{2}$/.test(v);
36
+ }, 'Must be an IsoDateString')
37
+ .describe('IsoDateString');
38
+ export const zEmail = z
39
+ .string()
40
+ .trim()
41
+ .email()
42
+ .transform(s => s.toLowerCase())
43
+ .describe('Email');
44
+ export const BASE62_REGEX = /^[a-zA-Z0-9]+$/;
45
+ export const BASE64_REGEX = /^[A-Za-z0-9+/]+={0,2}$/;
46
+ export const BASE64URL_REGEX = /^[\w-/]+$/;
47
+ export const zBase62 = z
48
+ .string()
49
+ .regex(BASE62_REGEX, 'Must be a base62 string')
50
+ .describe('Base62String');
51
+ export const zBase64 = z
52
+ .string()
53
+ .regex(BASE64_REGEX, 'Must be a base64 string')
54
+ .describe('Base64String');
55
+ export const zBase64Url = z
56
+ .string()
57
+ .regex(BASE64URL_REGEX, 'Must be a base64url string')
58
+ .describe('Base64UrlString');
59
+ export const JWT_REGEX = /^[\w-]+\.[\w-]+\.[\w-]+$/;
60
+ export const zJwt = z.string().regex(JWT_REGEX, 'Must be a JWT string').describe('JWTString');
61
+ export const zId = z
62
+ .string()
63
+ .regex(/^[a-zA-Z0-9_]{6,64}$/, 'Must be an id string')
64
+ .describe('IdString');
65
+ export const zIdBase62 = z
66
+ .string()
67
+ .regex(/^[a-zA-Z0-9]{8,64}$/, 'Must be a base62 id string')
68
+ .describe('Base62Id');
69
+ export const zIdBase64 = z
70
+ .string()
71
+ .regex(/^[A-Za-z0-9+/]{6,62}={0,2}$/, 'Must be a base64 id string')
72
+ .describe('Base64Id');
73
+ export const zIdBase64Url = z
74
+ .string()
75
+ .regex(/^[\w-/]{8,64}$/, 'Must be a base64url id string')
76
+ .describe('Base64UrlId');
77
+ /**
78
+ * "Slug" - a valid URL, filename, etc.
79
+ */
80
+ export const zSlug = z
81
+ .string()
82
+ .regex(/^[a-z0-9-]{1,255}$/, 'Must be a slug string')
83
+ .describe('Slug');
84
+ export const zBaseDBEntity = z
85
+ .object({
86
+ id: z.string().optional(),
87
+ created: zUnixTimestamp2000.optional(),
88
+ updated: zUnixTimestamp2000.optional(),
89
+ })
90
+ .describe('BaseDBEntity');
91
+ export const zSavedDBEntity = zBaseDBEntity.required().describe('SavedDBEntity');
@@ -0,0 +1,53 @@
1
+ import { ZodError } from 'zod';
2
+ import { _stringifyAny } from '../string/stringifyAny';
3
+ export function zIsValid(value, schema) {
4
+ const { success } = schema.safeParse(value);
5
+ return success;
6
+ }
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;
13
+ }
14
+ export function zSafeValidate(value, schema) {
15
+ const r = schema.safeParse(value);
16
+ if (r.success) {
17
+ return r;
18
+ }
19
+ return {
20
+ success: false,
21
+ error: new ZodValidationError(r.error.issues, value, schema),
22
+ };
23
+ }
24
+ export class ZodValidationError extends ZodError {
25
+ constructor(issues, value, schema) {
26
+ super(issues);
27
+ this.value = value;
28
+ this.schema = schema;
29
+ }
30
+ get message() {
31
+ return this.annotate();
32
+ }
33
+ annotate() {
34
+ var _a;
35
+ let objectTitle = this.schema.description;
36
+ if (typeof this.value === 'object' && this.value) {
37
+ const objectName = this.schema.description || ((_a = this.value.constructor) === null || _a === void 0 ? void 0 : _a.name);
38
+ const objectId = this.value['id'];
39
+ objectTitle = [objectName, objectId].filter(Boolean).join('.');
40
+ }
41
+ objectTitle || (objectTitle = 'data');
42
+ return [
43
+ `Invalid ${objectTitle}`,
44
+ '',
45
+ 'Input:',
46
+ _stringifyAny(this.value),
47
+ this.issues.length > 1 ? `\n${this.issues.length} issues:` : '',
48
+ ...this.issues.slice(0, 100).map(i => {
49
+ return [i.path.join('.'), i.message].filter(Boolean).join(': ');
50
+ }),
51
+ ].join('\n');
52
+ }
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.128.1",
3
+ "version": "14.129.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -8,7 +8,8 @@
8
8
  "docs-build": "NODE_OPTIONS=--openssl-legacy-provider vuepress build docs"
9
9
  },
10
10
  "dependencies": {
11
- "tslib": "^2.0.0"
11
+ "tslib": "^2.0.0",
12
+ "zod": "^3.20.2"
12
13
  },
13
14
  "devDependencies": {
14
15
  "@naturalcycles/bench-lib": "^1.5.0",
package/src/index.ts CHANGED
@@ -59,7 +59,6 @@ export * from './is.util'
59
59
  export * from './typeFest'
60
60
  export * from './types'
61
61
  export * from './unit/size.util'
62
- import { is } from './vendor/is'
63
62
  export * from './log/commonLogger'
64
63
  export * from './string/safeJsonStringify'
65
64
  export * from './promise/pQueue'
@@ -77,5 +76,10 @@ export * from './datetime/timeInterval'
77
76
  export * from './http/http.model'
78
77
  export * from './http/fetcher'
79
78
  export * from './http/fetcher.model'
79
+ export * from './zod/zod.util'
80
+ export * from './zod/zod.shared.schemas'
81
+ import { z, ZodSchema, ZodError, ZodIssue } from 'zod'
82
+ import { is } from './vendor/is'
80
83
 
81
- export { is }
84
+ export { is, z, ZodSchema, ZodError }
85
+ export type { ZodIssue }
@@ -0,0 +1,102 @@
1
+ import { z } from 'zod'
2
+
3
+ export const TS_2500 = 16725225600 // 2500-01-01
4
+ export const TS_2000 = 946684800 // 2000-01-01
5
+
6
+ export const zUnixTimestamp = z
7
+ .number()
8
+ .int()
9
+ .min(0)
10
+ .max(TS_2500, 'Must be a UnixTimestamp number')
11
+ .describe('UnixTimestamp')
12
+ export const zUnixTimestamp2000 = z
13
+ .number()
14
+ .int()
15
+ .min(TS_2000)
16
+ .max(TS_2500, 'Must be a UnixTimestamp number after 2000-01-01')
17
+ .describe('UnixTimestamp2000')
18
+ export const zUnixTimestampMillis = z
19
+ .number()
20
+ .int()
21
+ .min(0)
22
+ .max(TS_2500 * 1000, 'Must be a UnixTimestampMillis number')
23
+ .describe('UnixTimestampMillis')
24
+ export const zUnixTimestampMillis2000 = z
25
+ .number()
26
+ .int()
27
+ .min(TS_2000 * 1000)
28
+ .max(TS_2500 * 1000, 'Must be a UnixTimestampMillis number after 2000-01-01')
29
+ .describe('UnixTimestampMillis2000')
30
+
31
+ export const zSemVer = z
32
+ .string()
33
+ .regex(/^[0-9]+\.[0-9]+\.[0-9]+$/, 'Must be a SemVer string')
34
+ .describe('SemVer')
35
+
36
+ export const zIsoDateString = z
37
+ .string()
38
+ .refine(v => {
39
+ return /^\d{4}-\d{2}-\d{2}$/.test(v)
40
+ }, 'Must be an IsoDateString')
41
+ .describe('IsoDateString')
42
+
43
+ export const zEmail = z
44
+ .string()
45
+ .trim()
46
+ .email()
47
+ .transform(s => s.toLowerCase())
48
+ .describe('Email')
49
+
50
+ export const BASE62_REGEX = /^[a-zA-Z0-9]+$/
51
+ export const BASE64_REGEX = /^[A-Za-z0-9+/]+={0,2}$/
52
+ export const BASE64URL_REGEX = /^[\w-/]+$/
53
+ export const zBase62 = z
54
+ .string()
55
+ .regex(BASE62_REGEX, 'Must be a base62 string')
56
+ .describe('Base62String')
57
+ export const zBase64 = z
58
+ .string()
59
+ .regex(BASE64_REGEX, 'Must be a base64 string')
60
+ .describe('Base64String')
61
+ export const zBase64Url = z
62
+ .string()
63
+ .regex(BASE64URL_REGEX, 'Must be a base64url string')
64
+ .describe('Base64UrlString')
65
+
66
+ export const JWT_REGEX = /^[\w-]+\.[\w-]+\.[\w-]+$/
67
+ export const zJwt = z.string().regex(JWT_REGEX, 'Must be a JWT string').describe('JWTString')
68
+
69
+ export const zId = z
70
+ .string()
71
+ .regex(/^[a-zA-Z0-9_]{6,64}$/, 'Must be an id string')
72
+ .describe('IdString')
73
+ export const zIdBase62 = z
74
+ .string()
75
+ .regex(/^[a-zA-Z0-9]{8,64}$/, 'Must be a base62 id string')
76
+ .describe('Base62Id')
77
+ export const zIdBase64 = z
78
+ .string()
79
+ .regex(/^[A-Za-z0-9+/]{6,62}={0,2}$/, 'Must be a base64 id string')
80
+ .describe('Base64Id')
81
+ export const zIdBase64Url = z
82
+ .string()
83
+ .regex(/^[\w-/]{8,64}$/, 'Must be a base64url id string')
84
+ .describe('Base64UrlId')
85
+
86
+ /**
87
+ * "Slug" - a valid URL, filename, etc.
88
+ */
89
+ export const zSlug = z
90
+ .string()
91
+ .regex(/^[a-z0-9-]{1,255}$/, 'Must be a slug string')
92
+ .describe('Slug')
93
+
94
+ export const zBaseDBEntity = z
95
+ .object({
96
+ id: z.string().optional(),
97
+ created: zUnixTimestamp2000.optional(),
98
+ updated: zUnixTimestamp2000.optional(),
99
+ })
100
+ .describe('BaseDBEntity')
101
+
102
+ export const zSavedDBEntity = zBaseDBEntity.required().describe('SavedDBEntity')
@@ -0,0 +1,77 @@
1
+ import { ZodError, ZodSchema, ZodIssue } from 'zod'
2
+ import { _stringifyAny } from '../string/stringifyAny'
3
+
4
+ export interface ZodErrorResult<T> {
5
+ success: false
6
+ data?: T
7
+ error: ZodValidationError<T>
8
+ }
9
+
10
+ export interface ZodSuccessResult<T> {
11
+ success: true
12
+ data: T
13
+ error?: ZodValidationError<T>
14
+ }
15
+
16
+ export function zIsValid<T>(value: T, schema: ZodSchema<T>): boolean {
17
+ const { success } = schema.safeParse(value)
18
+ return success
19
+ }
20
+
21
+ export function zValidate<T>(value: T, schema: ZodSchema<T>): T {
22
+ const r = zSafeValidate(value, schema)
23
+ if (r.success) {
24
+ return r.data
25
+ }
26
+
27
+ throw r.error
28
+ }
29
+
30
+ export function zSafeValidate<T>(
31
+ value: T,
32
+ schema: ZodSchema<T>,
33
+ // objectName?: string,
34
+ ): ZodSuccessResult<T> | ZodErrorResult<T> {
35
+ const r = schema.safeParse(value)
36
+ if (r.success) {
37
+ return r
38
+ }
39
+
40
+ return {
41
+ success: false,
42
+ error: new ZodValidationError<T>(r.error.issues, value, schema),
43
+ }
44
+ }
45
+
46
+ export class ZodValidationError<T> extends ZodError<T> {
47
+ constructor(issues: ZodIssue[], public value: T, public schema: ZodSchema<T>) {
48
+ super(issues)
49
+ }
50
+
51
+ override get message(): string {
52
+ return this.annotate()
53
+ }
54
+
55
+ annotate(): string {
56
+ let objectTitle = this.schema.description
57
+
58
+ if (typeof this.value === 'object' && this.value) {
59
+ const objectName = this.schema.description || this.value.constructor?.name
60
+ const objectId = (this.value as any)['id'] as string
61
+ objectTitle = [objectName, objectId].filter(Boolean).join('.')
62
+ }
63
+
64
+ objectTitle ||= 'data'
65
+
66
+ return [
67
+ `Invalid ${objectTitle}`,
68
+ '',
69
+ 'Input:',
70
+ _stringifyAny(this.value),
71
+ this.issues.length > 1 ? `\n${this.issues.length} issues:` : '',
72
+ ...this.issues.slice(0, 100).map(i => {
73
+ return [i.path.join('.'), i.message].filter(Boolean).join(': ')
74
+ }),
75
+ ].join('\n')
76
+ }
77
+ }