@nemigo/helpers 2.4.0 → 2.6.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.
@@ -56,7 +56,6 @@ export class AsyncContext {
56
56
  const result = await this.__async_storage.run(transaction, () => func(transaction));
57
57
  if (autoAfterCommit && transaction.length > 0) {
58
58
  await this.__submit(transaction);
59
- // eslint-disable-next-line require-atomic-updates
60
59
  transaction.length = 0;
61
60
  }
62
61
  return result;
@@ -1,4 +1,4 @@
1
- import type { AnyFunc, Args, CanBePromise, Return } from "../types.js";
1
+ import type { AnyFunc, Args, CanBePromise, IState, Return } from "../types.js";
2
2
  /**
3
3
  * Промис из {@link createManualPromise}
4
4
  */
@@ -30,6 +30,7 @@ export declare const delay: (ms: number, success?: boolean) => Promise<void>;
30
30
  * ```
31
31
  */
32
32
  export declare const debounce: <F extends AnyFunc>(func: F, ms: number) => ((...args: Args<F>) => void);
33
+ export declare const useStateGuard: <F extends AnyFunc>(func: F, state: IState<boolean>) => ((...args: Args<F>) => Promise<void>);
33
34
  /**
34
35
  * Режимы троттлинга для {@link throttle}:
35
36
  * - `"delay"`:
@@ -42,13 +43,20 @@ export declare const debounce: <F extends AnyFunc>(func: F, ms: number) => ((...
42
43
  * * Аргументы обновляются, но не влияют, если функция уже выполняется
43
44
  */
44
45
  export type ThrottleMode = "urgent" | "delay";
46
+ export interface ThrottleOptions {
47
+ state?: IState<boolean>;
48
+ /**
49
+ * @default "urgent"
50
+ */
51
+ mode?: ThrottleMode;
52
+ /**
53
+ * @default 250
54
+ */
55
+ ms?: number;
56
+ }
45
57
  /**
46
58
  * Создаёт throttle-функцию, которая вызывает переданную функцию не чаще одного раза в заданный интервал времени
47
59
  *
48
- * @param func - Функция для троттлинга
49
- * @param [mode="urgent"] - Режим троттлинга
50
- * @param [ms=250] - Интервал времени в миллисекундах
51
- *
52
60
  * @throws {unknown} Ошибки функции прокидываются в промис
53
61
  *
54
62
  * @example
@@ -61,7 +69,7 @@ export type ThrottleMode = "urgent" | "delay";
61
69
  * const result2 = await throttledFetch("456"); // Возвращает тот же промис с "123"
62
70
  * ```
63
71
  */
64
- export declare const throttle: <F extends AnyFunc>(func: F, mode?: "urgent" | "delay", ms?: number) => ((...args: Args<F>) => Promise<Awaited<Return<F>>>);
72
+ export declare const throttle: <F extends AnyFunc>(func: F, { mode, ms, state }: ThrottleOptions) => ((...args: Args<F>) => Promise<Awaited<Return<F>>>);
65
73
  export type BoundaryFallback<Fallback> = Fallback | ((err: unknown) => CanBePromise<Fallback>);
66
74
  /**
67
75
  * Приведение коллбэка к промису с отловом ошибок и fallback-значением
@@ -44,13 +44,18 @@ export const debounce = (func, ms) => {
44
44
  timeout = setTimeout(() => void func(...args), ms);
45
45
  };
46
46
  };
47
+ export const useStateGuard = (func, state) => async (...args) => {
48
+ state.set(true);
49
+ try {
50
+ await func(...args);
51
+ }
52
+ finally {
53
+ state.set(false);
54
+ }
55
+ };
47
56
  /**
48
57
  * Создаёт throttle-функцию, которая вызывает переданную функцию не чаще одного раза в заданный интервал времени
49
58
  *
50
- * @param func - Функция для троттлинга
51
- * @param [mode="urgent"] - Режим троттлинга
52
- * @param [ms=250] - Интервал времени в миллисекундах
53
- *
54
59
  * @throws {unknown} Ошибки функции прокидываются в промис
55
60
  *
56
61
  * @example
@@ -63,17 +68,19 @@ export const debounce = (func, ms) => {
63
68
  * const result2 = await throttledFetch("456"); // Возвращает тот же промис с "123"
64
69
  * ```
65
70
  */
66
- export const throttle = (func, mode = "urgent", ms = 250) => {
71
+ export const throttle = (func, { mode = "urgent", ms = 250, state }) => {
67
72
  let _promise;
68
73
  let _args = [];
69
74
  const call = async () => await func(..._args);
70
75
  const reset = () => {
71
76
  _promise = null;
77
+ state?.set(false);
72
78
  };
73
79
  return (...args) => {
74
80
  _args = args;
75
81
  if (_promise)
76
82
  return _promise;
83
+ state?.set(true);
77
84
  const { resolve, reject, promise } = createManualPromise();
78
85
  _promise = promise;
79
86
  if (mode === "delay") {
@@ -44,7 +44,6 @@ export const createEnterHandler = (handler, props = {}) => (event) => {
44
44
  secondary?.(event);
45
45
  }
46
46
  };
47
- // oxlint-disable-next-line typescript/explicit-module-boundary-types
48
47
  export const isKeyboardEvent = (e) => !!e.code;
49
48
  /**
50
49
  * Создаёт обработчик события контекстного меню
package/dist/mutate.js CHANGED
@@ -116,7 +116,6 @@ export const inject = (self, key, func, dynamic = false) => {
116
116
  const original = self[key];
117
117
  if (dynamic) {
118
118
  // динамический this
119
- // oxlint-disable-next-line eslint/func-names
120
119
  // eslint-disable-next-line func-names
121
120
  self[key] = function (...args) {
122
121
  // eslint-disable-next-line unicorn/consistent-function-scoping
package/dist/script.js CHANGED
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable no-console */
2
- // oxlint-disable no-console
3
2
  import { exec } from "node:child_process";
4
3
  import { MS_IN_MINUTE } from "./datetime/delta.js";
5
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nemigo/helpers",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "private": false,
5
5
  "license": "MPL-2.0",
6
6
  "author": {
@@ -183,27 +183,15 @@
183
183
  "types": "./dist/veil.d.ts",
184
184
  "default": "./dist/veil.js"
185
185
  },
186
- "./xod": {
187
- "types": "./dist/xod.d.ts",
188
- "default": "./dist/xod.js"
189
- },
190
186
  "./zipper": {
191
187
  "types": "./dist/zipper.d.ts",
192
188
  "default": "./dist/zipper.js"
193
189
  }
194
190
  },
195
- "peerDependencies": {
196
- "zod": ">=4.2.0"
197
- },
198
- "peerDependenciesMeta": {
199
- "zod": {
200
- "optional": true
201
- }
202
- },
203
191
  "dependencies": {
204
192
  "@std/msgpack": "npm:@jsr/std__msgpack"
205
193
  },
206
194
  "devDependencies": {
207
- "@nemigo/configs": "2.4.0"
195
+ "@nemigo/configs": "2.6.0"
208
196
  }
209
197
  }
package/dist/xod.d.ts DELETED
@@ -1,246 +0,0 @@
1
- import { z } from "zod";
2
- /**
3
- * Параметры для создания ошибки валидации {@link https://zod.dev Zod}
4
- */
5
- export interface InvalidValueIssue {
6
- /**
7
- * Исходное значение которое не прошло валидацию
8
- */
9
- value: unknown;
10
- /**
11
- * Контекст валидации {@link https://zod.dev Zod}
12
- */
13
- ctx: z.core.$RefinementCtx;
14
- /**
15
- * Сообщение об ошибке
16
- */
17
- message: string;
18
- /**
19
- * Ожидаемый тип значения
20
- */
21
- expected: string;
22
- }
23
- /**
24
- * Добавляет ошибку валидации в контекст {@link https://zod.dev Zod}-схемы через {@link RefinementCtx.addIssue} и прерывает выполнение
25
- */
26
- export declare const throwValueIssue: (props: InvalidValueIssue) => never;
27
- /**
28
- * Схема для отсутствующих значений
29
- *
30
- * Замаскировано под эквивалент: `z.union([z.null().optional().transform(() => undefined)])`
31
- *
32
- * Принимает:
33
- * - `null` → `undefined`
34
- * - `undefined` → `undefined`
35
- * - `"nUll"` (любой регистр) → `undefined`
36
- * - `"undeFinEd"` (любой регистр) → `undefined`
37
- * - `""` → `undefined`
38
- * - `ETC` → ZodError
39
- */
40
- export declare const nullSchema: z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>;
41
- /**
42
- * Создаёт схему: либо {@link nullSchema}, либо значения по переданной схеме
43
- *
44
- * @example
45
- * ```typescript
46
- * const nullableString = toNullable(z.string());
47
- * nullableString.parse("hello"); // "hello"
48
- * nullableString.parse(null); // undefined
49
- * nullableString.parse("null"); // undefined
50
- * ```
51
- */
52
- export declare const toNullable: <T extends z.core.SomeType>(schema: T) => z.ZodUnion<[typeof nullSchema, T]>;
53
- /**
54
- * Схема для boolean-значений через {@link caseBoolean}
55
- *
56
- * Замаскировано под эквивалент: `z.boolean().transform((v) => v)`
57
- */
58
- export declare const booleanSchema: z.ZodPipe<z.ZodBoolean, z.ZodTransform<boolean, boolean>>;
59
- /**
60
- * Сочетает {@link nullSchema} и {@link booleanSchema}
61
- */
62
- export declare const booleanSchemaOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodBoolean, z.ZodTransform<boolean, boolean>>]>;
63
- /**
64
- * Схема для числовых значений через {@link caseNumber}
65
- *
66
- * Замаскировано под эквивалент: `z.union([z.number(), z.string()]).transform((v) => Number(v))`
67
- */
68
- export declare const numberSchema: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
69
- /**
70
- * Сочетает {@link nullSchema} и {@link numberSchema}
71
- */
72
- export declare const numberSchemaOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>]>;
73
- /**
74
- * Отличается типизацией от {@link numberSchema} тем, что якобы не принимает строки
75
- *
76
- * Замаскировано под эквивалент: `z.number().transform((v) => v)`
77
- *
78
- * @example
79
- * ```typescript
80
- * numberStrictSchema.parse(42); // 42
81
- * numberStrictSchema.parse("42"); // Ошибка типизации!
82
- * ```
83
- */
84
- export declare const numberStrictSchema: z.ZodPipe<z.ZodNumber, z.ZodTransform<number, number>>;
85
- /**
86
- * Сочетает {@link nullSchema} и {@link numberStrictSchema}
87
- */
88
- export declare const numberStrictSchemaOptional: z.ZodUnion<[typeof nullSchema, typeof numberStrictSchema]>;
89
- /**
90
- * Схема для строковых значений через {@link caseString}
91
- *
92
- * Замаскировано под эквивалент: `z.union([z.number(), z.string()]).transform((v) => String(v))`
93
- */
94
- export declare const stringSchema: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<string, string | number>>;
95
- /**
96
- * Сочетает {@link nullSchema} и {@link stringSchema}
97
- */
98
- export declare const stringSchemaOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<string, string | number>>]>;
99
- /**
100
- * Отличается типизацией от {@link stringSchema} тем, что якобы не принимает числа
101
- *
102
- * Замаскировано под эквивалент: `z.string().transform((v) => v)`
103
- *
104
- * @example
105
- * ```typescript
106
- * stringStrictSchema.parse("hello"); // "hello"
107
- * stringStrictSchema.parse(42); // Ошибка типизации!
108
- * ```
109
- */
110
- export declare const stringStrictSchema: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
111
- /**
112
- * Сочетает {@link nullSchema} и {@link stringStrictSchema}
113
- */
114
- export declare const stringStrictSchemaOptional: z.ZodUnion<[typeof nullSchema, typeof stringStrictSchema]>;
115
- /**
116
- * Схема для {@link ZoneStamp}
117
- */
118
- export declare const zoneStampSchema: z.ZodObject<{
119
- stamp: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
120
- zone: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
121
- }, z.core.$strip>;
122
- /**
123
- * Сочетает {@link nullSchema} и {@link zoneStampSchema}
124
- */
125
- export declare const zoneStampSchemaOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodObject<{
126
- stamp: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
127
- zone: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
128
- }, z.core.$strip>]>;
129
- /**
130
- * Строгая версия {@link zoneStampSchema}, которая не якобы принимает строковые представления чисел
131
- *
132
- * @example
133
- * ```typescript
134
- * zoneStampStrictSchema.parse({ stamp: 1234567890, zone: 3 }); // { stamp: 1234567890, zone: 3 }
135
- * zoneStampStrictSchema.parse({ stamp: 1234567890, zone: "3" }); // Ошибка типизации!
136
- * ```
137
- */
138
- export declare const zoneStampStrictSchema: z.ZodObject<{
139
- stamp: typeof numberStrictSchema;
140
- zone: typeof numberStrictSchema;
141
- }>;
142
- /**
143
- * Сочетает {@link nullSchema} и {@link zoneStampStrictSchema}
144
- */
145
- export declare const zoneStampStrictSchemaOptional: z.ZodUnion<[typeof nullSchema, typeof zoneStampStrictSchema]>;
146
- /**
147
- * Схема для {@link LWH}
148
- */
149
- export declare const lwhSchema: z.ZodObject<{
150
- length: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
151
- width: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
152
- height: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
153
- }, z.core.$strip>;
154
- /**
155
- * Сочетает {@link nullSchema} и {@link lwhSchema}
156
- */
157
- export declare const lwhSchemaOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodObject<{
158
- length: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
159
- width: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
160
- height: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
161
- }, z.core.$strip>]>;
162
- /**
163
- * Отличается типизацией от {@link lwhSchema} тем, что якобы не принимает строковые представления чисел
164
- *
165
- * @example
166
- * ```typescript
167
- * lwhStrictSchema.parse({ length: 10, width: 20, height: 30 }); // { length: 10, width: 20, height: 30 }
168
- * lwhStrictSchema.parse({ length: "10", width: "20", height: "30" }); // Ошибка типизации!
169
- * ```
170
- */
171
- export declare const lwhStrictSchema: z.ZodObject<{
172
- length: typeof numberStrictSchema;
173
- width: typeof numberStrictSchema;
174
- height: typeof numberStrictSchema;
175
- }>;
176
- /**
177
- * Сочетает {@link nullSchema} и {@link lwhStrictSchema}
178
- */
179
- export declare const lwhStrictSchemaOptional: z.ZodUnion<[typeof nullSchema, typeof lwhStrictSchema]>;
180
- /**
181
- * Коллекция расширенных {@link https://zod.dev Zod}-схем со встроенными преобразованиями типов
182
- *
183
- * @example
184
- * ```typescript
185
- * import { xod } from "./xod.js"; // or import xod from "./xod.js";
186
- *
187
- * const userSchema = z.object({
188
- * name: xod.string, // Принимает string и number
189
- * age: xod.number, // Принимает number и string
190
- * isActive: xod.boolean, // Принимает boolean, number, string
191
- * notes: xod.stringOptional, // Принимает string, number, null, undefined
192
- * created: xod.zoneStamp, // Принимает объект с временной меткой и зоной
193
- * });
194
- * ```
195
- */
196
- export declare const xod: {
197
- throwValueIssue: (props: InvalidValueIssue) => never;
198
- toNullable: <T extends z.core.SomeType>(schema: T) => z.ZodUnion<[typeof nullSchema, T]>;
199
- null: z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>;
200
- boolean: z.ZodPipe<z.ZodBoolean, z.ZodTransform<boolean, boolean>>;
201
- booleanOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodBoolean, z.ZodTransform<boolean, boolean>>]>;
202
- number: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
203
- numberStrict: z.ZodPipe<z.ZodNumber, z.ZodTransform<number, number>>;
204
- numberOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>]>;
205
- numberStrictOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodNumber, z.ZodTransform<number, number>>]>;
206
- string: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<string, string | number>>;
207
- stringStrict: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
208
- stringOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<string, string | number>>]>;
209
- stringStrictOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>]>;
210
- zoneStamp: z.ZodObject<{
211
- stamp: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
212
- zone: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
213
- }, z.core.$strip>;
214
- zoneStampOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodObject<{
215
- stamp: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
216
- zone: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
217
- }, z.core.$strip>]>;
218
- zoneStampStrict: z.ZodObject<{
219
- stamp: typeof numberStrictSchema;
220
- zone: typeof numberStrictSchema;
221
- }, z.core.$strip>;
222
- zoneStampStrictOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodObject<{
223
- stamp: typeof numberStrictSchema;
224
- zone: typeof numberStrictSchema;
225
- }, z.core.$strip>]>;
226
- lwh: z.ZodObject<{
227
- length: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
228
- width: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
229
- height: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
230
- }, z.core.$strip>;
231
- lwhOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodObject<{
232
- length: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
233
- width: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
234
- height: z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
235
- }, z.core.$strip>]>;
236
- lwhStrict: z.ZodObject<{
237
- length: typeof numberStrictSchema;
238
- width: typeof numberStrictSchema;
239
- height: typeof numberStrictSchema;
240
- }, z.core.$strip>;
241
- lwhStrictOptional: z.ZodUnion<[z.ZodPipe<z.ZodOptional<z.ZodNull>, z.ZodTransform<undefined, null | undefined>>, z.ZodObject<{
242
- length: typeof numberStrictSchema;
243
- width: typeof numberStrictSchema;
244
- height: typeof numberStrictSchema;
245
- }, z.core.$strip>]>;
246
- };
package/dist/xod.js DELETED
@@ -1,241 +0,0 @@
1
- import { z } from "zod";
2
- import { caseBoolean, caseNumber, caseString } from "./cases.js";
3
- /**
4
- * Добавляет ошибку валидации в контекст {@link https://zod.dev Zod}-схемы через {@link RefinementCtx.addIssue} и прерывает выполнение
5
- */
6
- export const throwValueIssue = (props) => {
7
- props.ctx.addIssue({
8
- code: "invalid_type",
9
- message: props.message,
10
- input: props.value,
11
- expected: props.expected,
12
- });
13
- return z.NEVER;
14
- };
15
- //...
16
- /**
17
- * Схема для отсутствующих значений
18
- *
19
- * Замаскировано под эквивалент: `z.union([z.null().optional().transform(() => undefined)])`
20
- *
21
- * Принимает:
22
- * - `null` → `undefined`
23
- * - `undefined` → `undefined`
24
- * - `"nUll"` (любой регистр) → `undefined`
25
- * - `"undeFinEd"` (любой регистр) → `undefined`
26
- * - `""` → `undefined`
27
- * - `ETC` → ZodError
28
- */
29
- export const nullSchema = z.union([
30
- // biome-ignore format : потеря смысла
31
- // oxlint-disable-next-line unicorn/no-useless-undefined
32
- // eslint-disable-next-line unicorn/no-useless-undefined
33
- z.null().optional().transform(() => undefined),
34
- z.string().transform((value, ctx) => {
35
- if (!value)
36
- return;
37
- const flat = value.trim().toLowerCase();
38
- if (flat === "undefined" || flat === "null")
39
- return;
40
- return throwValueIssue({
41
- ctx,
42
- value,
43
- message: "It isn't a null / undefined",
44
- expected: "null / undefined (or string like null / undefined)",
45
- });
46
- }),
47
- ]);
48
- /**
49
- * Создаёт схему: либо {@link nullSchema}, либо значения по переданной схеме
50
- *
51
- * @example
52
- * ```typescript
53
- * const nullableString = toNullable(z.string());
54
- * nullableString.parse("hello"); // "hello"
55
- * nullableString.parse(null); // undefined
56
- * nullableString.parse("null"); // undefined
57
- * ```
58
- */
59
- export const toNullable = (schema) => z.union([nullSchema, schema]);
60
- //...
61
- /**
62
- * Схема для boolean-значений через {@link caseBoolean}
63
- *
64
- * Замаскировано под эквивалент: `z.boolean().transform((v) => v)`
65
- */
66
- export const booleanSchema = z.unknown().transform((value, ctx) => caseBoolean(value, (result) => result === undefined
67
- ? throwValueIssue({
68
- ctx,
69
- value,
70
- message: "It isn't a boolean",
71
- expected: "boolean (or string / number like boolean)",
72
- })
73
- : result));
74
- /**
75
- * Сочетает {@link nullSchema} и {@link booleanSchema}
76
- */
77
- export const booleanSchemaOptional = toNullable(booleanSchema);
78
- //...
79
- /**
80
- * Схема для числовых значений через {@link caseNumber}
81
- *
82
- * Замаскировано под эквивалент: `z.union([z.number(), z.string()]).transform((v) => Number(v))`
83
- */
84
- export const numberSchema = z.unknown().transform((value, ctx) => caseNumber(value, (result) => result === undefined
85
- ? throwValueIssue({
86
- ctx,
87
- value,
88
- message: "It isn't a number",
89
- expected: "number (or string like number)",
90
- })
91
- : result));
92
- /**
93
- * Сочетает {@link nullSchema} и {@link numberSchema}
94
- */
95
- export const numberSchemaOptional = toNullable(numberSchema);
96
- /**
97
- * Отличается типизацией от {@link numberSchema} тем, что якобы не принимает строки
98
- *
99
- * Замаскировано под эквивалент: `z.number().transform((v) => v)`
100
- *
101
- * @example
102
- * ```typescript
103
- * numberStrictSchema.parse(42); // 42
104
- * numberStrictSchema.parse("42"); // Ошибка типизации!
105
- * ```
106
- */
107
- export const numberStrictSchema = numberSchema;
108
- /**
109
- * Сочетает {@link nullSchema} и {@link numberStrictSchema}
110
- */
111
- export const numberStrictSchemaOptional = numberSchemaOptional;
112
- //...
113
- /**
114
- * Схема для строковых значений через {@link caseString}
115
- *
116
- * Замаскировано под эквивалент: `z.union([z.number(), z.string()]).transform((v) => String(v))`
117
- */
118
- export const stringSchema = z.unknown().transform((value, ctx) => caseString(value, (result) => {
119
- const trimmed = result === undefined ? "" : result.trim();
120
- return trimmed === ""
121
- ? throwValueIssue({
122
- ctx,
123
- value,
124
- message: "It isn't a string or empty string",
125
- expected: "string (or number)",
126
- })
127
- : trimmed;
128
- }));
129
- /**
130
- * Сочетает {@link nullSchema} и {@link stringSchema}
131
- */
132
- export const stringSchemaOptional = toNullable(stringSchema);
133
- /**
134
- * Отличается типизацией от {@link stringSchema} тем, что якобы не принимает числа
135
- *
136
- * Замаскировано под эквивалент: `z.string().transform((v) => v)`
137
- *
138
- * @example
139
- * ```typescript
140
- * stringStrictSchema.parse("hello"); // "hello"
141
- * stringStrictSchema.parse(42); // Ошибка типизации!
142
- * ```
143
- */
144
- export const stringStrictSchema = stringSchema;
145
- /**
146
- * Сочетает {@link nullSchema} и {@link stringStrictSchema}
147
- */
148
- export const stringStrictSchemaOptional = stringSchemaOptional;
149
- //...
150
- /**
151
- * Схема для {@link ZoneStamp}
152
- */
153
- export const zoneStampSchema = z.object({
154
- stamp: numberSchema,
155
- zone: numberSchema,
156
- });
157
- /**
158
- * Сочетает {@link nullSchema} и {@link zoneStampSchema}
159
- */
160
- export const zoneStampSchemaOptional = toNullable(zoneStampSchema);
161
- /**
162
- * Строгая версия {@link zoneStampSchema}, которая не якобы принимает строковые представления чисел
163
- *
164
- * @example
165
- * ```typescript
166
- * zoneStampStrictSchema.parse({ stamp: 1234567890, zone: 3 }); // { stamp: 1234567890, zone: 3 }
167
- * zoneStampStrictSchema.parse({ stamp: 1234567890, zone: "3" }); // Ошибка типизации!
168
- * ```
169
- */
170
- export const zoneStampStrictSchema = zoneStampSchema;
171
- /**
172
- * Сочетает {@link nullSchema} и {@link zoneStampStrictSchema}
173
- */
174
- export const zoneStampStrictSchemaOptional = zoneStampSchemaOptional;
175
- //...
176
- /**
177
- * Схема для {@link LWH}
178
- */
179
- export const lwhSchema = z.object({
180
- length: numberSchema,
181
- width: numberSchema,
182
- height: numberSchema,
183
- });
184
- /**
185
- * Сочетает {@link nullSchema} и {@link lwhSchema}
186
- */
187
- export const lwhSchemaOptional = toNullable(lwhSchema);
188
- /**
189
- * Отличается типизацией от {@link lwhSchema} тем, что якобы не принимает строковые представления чисел
190
- *
191
- * @example
192
- * ```typescript
193
- * lwhStrictSchema.parse({ length: 10, width: 20, height: 30 }); // { length: 10, width: 20, height: 30 }
194
- * lwhStrictSchema.parse({ length: "10", width: "20", height: "30" }); // Ошибка типизации!
195
- * ```
196
- */
197
- export const lwhStrictSchema = lwhSchema;
198
- /**
199
- * Сочетает {@link nullSchema} и {@link lwhStrictSchema}
200
- */
201
- export const lwhStrictSchemaOptional = lwhSchemaOptional;
202
- //...
203
- /**
204
- * Коллекция расширенных {@link https://zod.dev Zod}-схем со встроенными преобразованиями типов
205
- *
206
- * @example
207
- * ```typescript
208
- * import { xod } from "./xod.js"; // or import xod from "./xod.js";
209
- *
210
- * const userSchema = z.object({
211
- * name: xod.string, // Принимает string и number
212
- * age: xod.number, // Принимает number и string
213
- * isActive: xod.boolean, // Принимает boolean, number, string
214
- * notes: xod.stringOptional, // Принимает string, number, null, undefined
215
- * created: xod.zoneStamp, // Принимает объект с временной меткой и зоной
216
- * });
217
- * ```
218
- */
219
- export const xod = {
220
- throwValueIssue,
221
- toNullable,
222
- null: nullSchema,
223
- boolean: booleanSchema,
224
- booleanOptional: booleanSchemaOptional,
225
- number: numberSchema,
226
- numberStrict: numberStrictSchema,
227
- numberOptional: numberSchemaOptional,
228
- numberStrictOptional: numberStrictSchemaOptional,
229
- string: stringSchema,
230
- stringStrict: stringStrictSchema,
231
- stringOptional: stringSchemaOptional,
232
- stringStrictOptional: stringStrictSchemaOptional,
233
- zoneStamp: zoneStampSchema,
234
- zoneStampOptional: zoneStampSchemaOptional,
235
- zoneStampStrict: zoneStampStrictSchema,
236
- zoneStampStrictOptional: zoneStampStrictSchemaOptional,
237
- lwh: lwhSchema,
238
- lwhOptional: lwhSchemaOptional,
239
- lwhStrict: lwhStrictSchema,
240
- lwhStrictOptional: lwhStrictSchemaOptional,
241
- };