@kalutskii/foundation 0.7.8 → 0.7.10
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/LICENSE +21 -0
- package/README.md +22 -16
- package/dist/index.d.ts +447 -123
- package/dist/index.js +210 -52
- package/package.json +5 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
import { SQL } from 'drizzle-orm';
|
|
2
2
|
import { ErrorHandler, MiddlewareHandler, Context, TypedResponse } from 'hono';
|
|
3
|
-
import { Locale } from 'date-fns';
|
|
4
3
|
import z$1, { z, ZodObject, ZodRawShape } from 'zod';
|
|
4
|
+
import { Locale } from 'date-fns';
|
|
5
5
|
import { SymmetricAlgorithm } from 'hono/utils/jwt/jwa';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Builds a Drizzle
|
|
9
|
-
*
|
|
10
|
-
* Maps each `where` entry to `eq(table[key], value)` and combines them with `and`.
|
|
11
|
-
* Assumes that `where` was already validated and contains only existing table fields.
|
|
8
|
+
* Builds a Drizzle `WHERE` clause by combining defined object entries with `and`.
|
|
9
|
+
* Expects the supplied keys to be validated against the table beforehand.
|
|
12
10
|
*
|
|
13
|
-
*
|
|
11
|
+
* @example
|
|
14
12
|
* await db.update(usersTable).set(values).where(sqlWhere(usersTable, { id: 1 })).returning();
|
|
15
|
-
* ```
|
|
16
13
|
*/
|
|
17
14
|
declare function sqlWhere(table: unknown, where: Record<string, unknown>): SQL;
|
|
18
15
|
|
|
19
16
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* Converts expected `HTTPException` values into shared API error envelopes.
|
|
18
|
+
* Unexpected failures are logged and represented by a traceable generic response.
|
|
22
19
|
*/
|
|
23
20
|
declare const onHandlerError: ErrorHandler;
|
|
24
21
|
|
|
25
22
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
23
|
+
* Logs request method, response status, duration, URL details, and a body preview.
|
|
24
|
+
* Multipart bodies remain unread to avoid buffering uploaded file content into logs.
|
|
28
25
|
*/
|
|
29
26
|
declare const honoLoggingHandler: MiddlewareHandler;
|
|
30
27
|
|
|
@@ -33,10 +30,10 @@ declare const EXCEPTION_STATUS_CODES: readonly [400, 401, 403, 404, 405, 409, 50
|
|
|
33
30
|
|
|
34
31
|
type SuccessStatusCode = (typeof SUCCESS_STATUS_CODES)[number];
|
|
35
32
|
type ExceptionStatusCode = (typeof EXCEPTION_STATUS_CODES)[number];
|
|
36
|
-
type APISuccess<
|
|
33
|
+
type APISuccess<TData = void> = {
|
|
37
34
|
kind: 'data';
|
|
38
35
|
status: SuccessStatusCode;
|
|
39
|
-
data:
|
|
36
|
+
data: TData;
|
|
40
37
|
};
|
|
41
38
|
type APIError = {
|
|
42
39
|
kind: 'error';
|
|
@@ -46,48 +43,55 @@ type APIError = {
|
|
|
46
43
|
type APIContractResult<TData = void> = APISuccess<TData> | APIError;
|
|
47
44
|
type APIContractData<TResult extends APIContractResult<unknown>> = TResult extends APISuccess<infer TData> ? TData : never;
|
|
48
45
|
type APIContractError<TResult extends APIContractResult<unknown>> = Extract<TResult, APIError>;
|
|
49
|
-
|
|
50
|
-
* Discriminated union result of a fetch operation.
|
|
51
|
-
* If `error` is set, `data` is null and vice versa.
|
|
52
|
-
*/
|
|
53
|
-
type FetchResult<T> = {
|
|
46
|
+
type FetchResult<TData> = {
|
|
54
47
|
error: null;
|
|
55
|
-
data:
|
|
48
|
+
data: TData;
|
|
56
49
|
} | {
|
|
57
50
|
error: string;
|
|
58
51
|
data: null;
|
|
59
52
|
};
|
|
60
53
|
|
|
61
54
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
55
|
+
* Options for a typed JSON response wrapped in the shared API success envelope.
|
|
56
|
+
* The status generic preserves the literal code inferred by the route contract.
|
|
64
57
|
*/
|
|
65
|
-
|
|
66
|
-
status:
|
|
67
|
-
data?:
|
|
68
|
-
}
|
|
58
|
+
type HonoRespondOptions<TData extends object, TStatus extends SuccessStatusCode> = {
|
|
59
|
+
status: TStatus;
|
|
60
|
+
data?: TData;
|
|
61
|
+
};
|
|
69
62
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
63
|
+
* Options for a downloadable binary response with attachment metadata.
|
|
64
|
+
* The content type remains optional and falls back to a generic binary type.
|
|
72
65
|
*/
|
|
73
|
-
|
|
74
|
-
status:
|
|
66
|
+
type HonoFileRespondOptions<TStatus extends SuccessStatusCode> = {
|
|
67
|
+
status: TStatus;
|
|
75
68
|
content: Uint8Array<ArrayBuffer>;
|
|
76
69
|
filename: string;
|
|
77
70
|
contentType?: string;
|
|
78
|
-
}
|
|
71
|
+
};
|
|
79
72
|
|
|
80
73
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
74
|
+
* Wraps `c.json` in the shared success envelope while preserving its literal status.
|
|
75
|
+
* Missing response data is represented by an empty object for contract consistency.
|
|
76
|
+
*/
|
|
77
|
+
declare function respond<T extends object = Record<string, never>, S extends SuccessStatusCode = SuccessStatusCode>(c: Context, options: HonoRespondOptions<T, S>): Response & TypedResponse<APISuccess<T> | APIError, S, 'json'>;
|
|
78
|
+
/**
|
|
79
|
+
* Responds with downloadable binary content and its attachment headers.
|
|
80
|
+
* Unknown/undefined content types default to `application/octet-stream`.
|
|
81
|
+
*/
|
|
82
|
+
declare function fileRespond<S extends SuccessStatusCode>(c: Context, options: HonoFileRespondOptions<S>): Response;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Creates a successful API envelope without cloning its data.
|
|
86
|
+
* Generic inference preserves the exact supplied payload type.
|
|
83
87
|
*/
|
|
84
88
|
declare function success<T = unknown>({ status, data }: {
|
|
85
89
|
status: SuccessStatusCode;
|
|
86
90
|
data: T;
|
|
87
91
|
}): APISuccess<T>;
|
|
88
92
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
93
|
+
* Creates a failed API envelope with one supported exception status.
|
|
94
|
+
* The supplied message remains unchanged for downstream presentation.
|
|
91
95
|
*/
|
|
92
96
|
declare function failure({ status, error }: {
|
|
93
97
|
status: ExceptionStatusCode;
|
|
@@ -95,132 +99,434 @@ declare function failure({ status, error }: {
|
|
|
95
99
|
}): APIError;
|
|
96
100
|
|
|
97
101
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* Example usage: const result = await fetchSafely(() => api.fetchUser(userId));
|
|
102
|
+
* Converts an API contract envelope into a mutually exclusive safe result.
|
|
103
|
+
* Only `APIError` values are normalized; rejected fetchers still reject.
|
|
101
104
|
*/
|
|
102
105
|
declare function fetchSafely<TResult extends APIContractResult<unknown>>(fetcher: () => Promise<TResult>): Promise<FetchResult<APIContractData<TResult>>>;
|
|
103
106
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
107
|
+
* Returns successful API data and throws for an `APIError` envelope.
|
|
108
|
+
* Rejected fetchers propagate their original error without replacement.
|
|
106
109
|
*/
|
|
107
110
|
declare function fetchAndThrow<TResult extends APIContractResult<unknown>>(fetcher: () => Promise<TResult>): Promise<APIContractData<TResult>>;
|
|
108
111
|
|
|
109
112
|
/**
|
|
110
|
-
*
|
|
113
|
+
* Canonical metadata shared by upload controls and runtime validation.
|
|
114
|
+
* Every supported format defines display, MIME, and extension values.
|
|
115
|
+
*/
|
|
116
|
+
declare const fileFormatsConfig: {
|
|
117
|
+
readonly png: {
|
|
118
|
+
readonly name: "PNG";
|
|
119
|
+
readonly mimeTypes: readonly ["image/png"];
|
|
120
|
+
readonly extensions: readonly [".png"];
|
|
121
|
+
};
|
|
122
|
+
readonly jpg: {
|
|
123
|
+
readonly name: "JPG";
|
|
124
|
+
readonly mimeTypes: readonly ["image/jpeg"];
|
|
125
|
+
readonly extensions: readonly [".jpg", ".jpeg"];
|
|
126
|
+
};
|
|
127
|
+
readonly webp: {
|
|
128
|
+
readonly name: "WEBP";
|
|
129
|
+
readonly mimeTypes: readonly ["image/webp"];
|
|
130
|
+
readonly extensions: readonly [".webp"];
|
|
131
|
+
};
|
|
132
|
+
readonly avif: {
|
|
133
|
+
readonly name: "AVIF";
|
|
134
|
+
readonly mimeTypes: readonly ["image/avif"];
|
|
135
|
+
readonly extensions: readonly [".avif"];
|
|
136
|
+
};
|
|
137
|
+
readonly heic: {
|
|
138
|
+
readonly name: "HEIC";
|
|
139
|
+
readonly mimeTypes: readonly ["image/heic", "image/heif"];
|
|
140
|
+
readonly extensions: readonly [".heic", ".heif"];
|
|
141
|
+
};
|
|
142
|
+
readonly pdf: {
|
|
143
|
+
readonly name: "PDF";
|
|
144
|
+
readonly mimeTypes: readonly ["application/pdf"];
|
|
145
|
+
readonly extensions: readonly [".pdf"];
|
|
146
|
+
};
|
|
147
|
+
readonly rtf: {
|
|
148
|
+
readonly name: "RTF";
|
|
149
|
+
readonly mimeTypes: readonly ["application/rtf"];
|
|
150
|
+
readonly extensions: readonly [".rtf"];
|
|
151
|
+
};
|
|
152
|
+
readonly txt: {
|
|
153
|
+
readonly name: "TXT";
|
|
154
|
+
readonly mimeTypes: readonly ["text/plain"];
|
|
155
|
+
readonly extensions: readonly [".txt"];
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
declare const fileFormatsArray: readonly ["png", "jpg", "webp", "avif", "heic", "pdf", "rtf", "txt"];
|
|
160
|
+
type FileFormat = (typeof fileFormatsArray)[number];
|
|
161
|
+
declare const fileFormatsRecord: Readonly<{
|
|
162
|
+
AVIF: "avif";
|
|
163
|
+
JPG: "jpg";
|
|
164
|
+
PDF: "pdf";
|
|
165
|
+
PNG: "png";
|
|
166
|
+
RTF: "rtf";
|
|
167
|
+
TXT: "txt";
|
|
168
|
+
WEBP: "webp";
|
|
169
|
+
HEIC: "heic";
|
|
170
|
+
}>;
|
|
171
|
+
declare const fileFormat: Readonly<{
|
|
172
|
+
AVIF: "avif";
|
|
173
|
+
JPG: "jpg";
|
|
174
|
+
PDF: "pdf";
|
|
175
|
+
PNG: "png";
|
|
176
|
+
RTF: "rtf";
|
|
177
|
+
TXT: "txt";
|
|
178
|
+
WEBP: "webp";
|
|
179
|
+
HEIC: "heic";
|
|
180
|
+
}>;
|
|
181
|
+
declare const uploadValidationErrorsArray: readonly ["empty_file", "unsupported_file_format", "file_size_exceeded", "files_count_exceeded"];
|
|
182
|
+
type UploadValidationError = (typeof uploadValidationErrorsArray)[number];
|
|
183
|
+
declare const uploadValidationErrorsRecord: Readonly<{
|
|
184
|
+
EMPTY_FILE: "empty_file";
|
|
185
|
+
UNSUPPORTED_FILE_FORMAT: "unsupported_file_format";
|
|
186
|
+
FILE_SIZE_EXCEEDED: "file_size_exceeded";
|
|
187
|
+
FILES_COUNT_EXCEEDED: "files_count_exceeded";
|
|
188
|
+
}>;
|
|
189
|
+
declare const uploadValidationError: Readonly<{
|
|
190
|
+
EMPTY_FILE: "empty_file";
|
|
191
|
+
UNSUPPORTED_FILE_FORMAT: "unsupported_file_format";
|
|
192
|
+
FILE_SIZE_EXCEEDED: "file_size_exceeded";
|
|
193
|
+
FILES_COUNT_EXCEEDED: "files_count_exceeded";
|
|
194
|
+
}>;
|
|
195
|
+
|
|
196
|
+
type FileFormatConfig = (typeof fileFormatsConfig)[FileFormat];
|
|
197
|
+
/**
|
|
198
|
+
* Shared upload policy consumed by browser controls and backend validation.
|
|
199
|
+
* One preset keeps format, size, capacity, and fallback rules synchronized.
|
|
200
|
+
*/
|
|
201
|
+
type UploadPreset<TFormats extends readonly FileFormat[] = readonly FileFormat[]> = Readonly<{
|
|
202
|
+
/**
|
|
203
|
+
* Supported formats accepted by every consumer of the preset.
|
|
204
|
+
* Const inference preserves the supplied format tuple without widening.
|
|
205
|
+
*/
|
|
206
|
+
formats: TFormats;
|
|
207
|
+
/**
|
|
208
|
+
* Maximum accepted size of one uploaded file measured in bytes.
|
|
209
|
+
* Schema and client validation can share this exact numeric boundary.
|
|
210
|
+
*/
|
|
211
|
+
maxFileSize: number;
|
|
212
|
+
/**
|
|
213
|
+
* Optional maximum number of files retained by one upload collection.
|
|
214
|
+
* Single-file controls can set this value to `1` for shared capacity rules.
|
|
215
|
+
*/
|
|
216
|
+
maxFilesCount?: number;
|
|
217
|
+
/**
|
|
218
|
+
* Allows extensions to compensate for absent or unreliable MIME metadata.
|
|
219
|
+
* The fallback remains disabled when this option is omitted.
|
|
220
|
+
*/
|
|
221
|
+
extensionFallback?: boolean;
|
|
222
|
+
}>;
|
|
223
|
+
/**
|
|
224
|
+
* Constraints used to validate an incoming collection of browser files.
|
|
225
|
+
* Existing and incoming counts are combined when enforcing capacity.
|
|
226
|
+
*/
|
|
227
|
+
type UploadFilesValidationOptions = Readonly<{
|
|
228
|
+
/**
|
|
229
|
+
* Number of files already retained before the incoming batch is validated.
|
|
230
|
+
* Existing entries reduce the remaining capacity without being revalidated.
|
|
231
|
+
*/
|
|
232
|
+
currentFilesCount: number;
|
|
233
|
+
/**
|
|
234
|
+
* Supported formats used to validate every file in the incoming batch.
|
|
235
|
+
* MIME and extension metadata are resolved through the canonical catalog.
|
|
236
|
+
*/
|
|
237
|
+
formats: readonly FileFormat[];
|
|
238
|
+
/**
|
|
239
|
+
* Maximum accepted size of one uploaded file measured in bytes.
|
|
240
|
+
* Files exceeding this boundary receive the stable size error key.
|
|
241
|
+
*/
|
|
242
|
+
maxFileSize: number;
|
|
243
|
+
/**
|
|
244
|
+
* Optional maximum number of retained files after accepting the batch.
|
|
245
|
+
* Omitting this value leaves collection capacity unrestricted.
|
|
246
|
+
*/
|
|
247
|
+
maxFilesCount?: number;
|
|
248
|
+
}>;
|
|
249
|
+
/**
|
|
250
|
+
* Accepted files and the final rejection encountered in one batch.
|
|
251
|
+
* Valid entries remain available when another entry fails validation.
|
|
252
|
+
*/
|
|
253
|
+
type UploadFilesValidationResult = Readonly<{
|
|
254
|
+
/**
|
|
255
|
+
* Valid incoming files that fit the remaining collection capacity.
|
|
256
|
+
* Accepted file objects preserve their original identity and ordering.
|
|
257
|
+
*/
|
|
258
|
+
acceptedFiles: File[];
|
|
259
|
+
/**
|
|
260
|
+
* Final stable rejection encountered while processing the incoming batch.
|
|
261
|
+
* The field remains absent when every supplied file is accepted.
|
|
262
|
+
*/
|
|
263
|
+
validationError?: UploadValidationError;
|
|
264
|
+
}>;
|
|
265
|
+
/**
|
|
266
|
+
* Options used to construct one reusable Zod file schema.
|
|
267
|
+
* Extension fallback is disabled by default to preserve strict MIME checks.
|
|
268
|
+
*/
|
|
269
|
+
type ZodUploadFileSchemaOptions = Readonly<{
|
|
270
|
+
/**
|
|
271
|
+
* Supported formats accepted by the generated file schema.
|
|
272
|
+
* Strict MIME validation uses metadata from the canonical format catalog.
|
|
273
|
+
*/
|
|
274
|
+
formats: readonly FileFormat[];
|
|
275
|
+
/**
|
|
276
|
+
* Maximum accepted file size measured in bytes for the generated file schema.
|
|
277
|
+
* Empty files remain invalid independently of this configured boundary.
|
|
278
|
+
*/
|
|
279
|
+
maxFileSize: number;
|
|
280
|
+
/**
|
|
281
|
+
* Allows a supported extension to compensate for missing MIME metadata.
|
|
282
|
+
* The fallback remains disabled by default to preserve strict validation.
|
|
283
|
+
*/
|
|
284
|
+
extensionFallback?: boolean;
|
|
285
|
+
}>;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Defines one shared upload policy while preserving its literal format tuple.
|
|
289
|
+
* The resulting preset can drive schemas, picker hints, and batch validation.
|
|
111
290
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
291
|
+
* @example
|
|
292
|
+
* const imageUploadPreset = defineUploadPreset({
|
|
293
|
+
* formats: [fileFormat.JPG, fileFormat.PNG, fileFormat.WEBP],
|
|
294
|
+
* maxFileSize: 8 * 1024 * 1024,
|
|
295
|
+
* maxFilesCount: 1,
|
|
296
|
+
* });
|
|
114
297
|
*/
|
|
115
|
-
declare const
|
|
116
|
-
|
|
117
|
-
|
|
298
|
+
declare function defineUploadPreset<const TFormats extends readonly FileFormat[]>(preset: UploadPreset<TFormats>): UploadPreset<TFormats>;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Default maximum size of one file accepted by the built-in upload presets.
|
|
302
|
+
* The 20 MiB boundary matches the existing upload component policy.
|
|
303
|
+
*/
|
|
304
|
+
declare const DEFAULT_UPLOAD_MAX_FILE_SIZE: number;
|
|
305
|
+
/**
|
|
306
|
+
* Ready-to-use policy for every image format supported by the upload catalog.
|
|
307
|
+
* Each image may occupy up to 20 MiB while collection capacity remains unrestricted.
|
|
308
|
+
*/
|
|
309
|
+
declare const imageUploadPreset: Readonly<{
|
|
310
|
+
formats: readonly ["png", "jpg", "webp", "avif", "heic"];
|
|
311
|
+
maxFileSize: number;
|
|
312
|
+
maxFilesCount?: number;
|
|
313
|
+
extensionFallback?: boolean;
|
|
314
|
+
}>;
|
|
315
|
+
/**
|
|
316
|
+
* Ready-to-use policy for every document format supported by the upload catalog.
|
|
317
|
+
* Each document may occupy up to 20 MiB while collection capacity remains unrestricted.
|
|
318
|
+
*/
|
|
319
|
+
declare const documentUploadPreset: Readonly<{
|
|
320
|
+
formats: readonly ["pdf", "rtf", "txt"];
|
|
321
|
+
maxFileSize: number;
|
|
322
|
+
maxFilesCount?: number;
|
|
323
|
+
extensionFallback?: boolean;
|
|
324
|
+
}>;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Builds a reusable Zod schema for one uploaded file with format and size.
|
|
328
|
+
* MIME matching is strict unless extension fallback is explicitly enabled.
|
|
329
|
+
*/
|
|
330
|
+
declare function zodUploadFileSchema(options: ZodUploadFileSchemaOptions): z.ZodFile;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Extracts a normalized trailing extension from a complete file name.
|
|
334
|
+
* Returns an empty string when no valid dot-delimited suffix exists.
|
|
335
|
+
*/
|
|
336
|
+
declare function getFileExtension(fileName: string): string;
|
|
337
|
+
/**
|
|
338
|
+
* Normalizes a configured extension to a lowercase dot-prefixed value.
|
|
339
|
+
* Existing prefixes remain intact so repeated normalization is stable.
|
|
340
|
+
*/
|
|
341
|
+
declare function normalizeFileExtension(extension: string): string;
|
|
342
|
+
/**
|
|
343
|
+
* Compares a concrete MIME type with an exact or wildcard configuration.
|
|
344
|
+
* Wildcards match every subtype belonging to the configured media group.
|
|
345
|
+
*/
|
|
346
|
+
declare function matchesMimeType(fileMimeType: string, configuredMimeType: string): boolean;
|
|
347
|
+
/**
|
|
348
|
+
* Checks whether a file MIME type belongs to one selected format.
|
|
349
|
+
* File names and extensions cannot make an unsupported MIME type valid.
|
|
350
|
+
*/
|
|
351
|
+
declare function isFileMimeTypeSupported(file: File, formats: readonly FileFormat[]): boolean;
|
|
352
|
+
/**
|
|
353
|
+
* Checks whether a file extension belongs to one selected format.
|
|
354
|
+
* The comparison is case-insensitive and requires a complete suffix.
|
|
355
|
+
*/
|
|
356
|
+
declare function isFileExtensionSupported(file: File, formats: readonly FileFormat[]): boolean;
|
|
357
|
+
/**
|
|
358
|
+
* Checks whether a file matches one configured MIME type or extension.
|
|
359
|
+
* This permissive predicate supports clients where MIME metadata is absent.
|
|
360
|
+
*/
|
|
361
|
+
declare function isFileFormatSupported(file: File, formats: readonly FileFormat[]): boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Builds a native file-picker hint from configured MIME types and extensions.
|
|
364
|
+
* Duplicate values are removed while their configuration order is retained.
|
|
365
|
+
*/
|
|
366
|
+
declare function createUploadAccept(formats: readonly FileFormat[]): string;
|
|
367
|
+
|
|
118
368
|
/**
|
|
119
|
-
*
|
|
369
|
+
* Validates one file against configured format and size constraints.
|
|
370
|
+
* Returns the first stable error key or nothing for a valid file.
|
|
371
|
+
*/
|
|
372
|
+
declare function validateUploadFile(file: File, formats: readonly FileFormat[], maxFileSize: number): UploadValidationError | undefined;
|
|
373
|
+
/**
|
|
374
|
+
* Validates an incoming collection while preserving every accepted file.
|
|
375
|
+
* Returns accepted entries and the final rejection key from the batch.
|
|
376
|
+
*/
|
|
377
|
+
declare function validateUploadFiles(incomingFiles: readonly File[], options: UploadFilesValidationOptions): UploadFilesValidationResult;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Projects the current instant onto the wall-clock fields of another timezone.
|
|
381
|
+
* The timezone defaults to `Europe/London` when no option is provided.
|
|
120
382
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* offsets may change depending on daylight saving time or historical rules.
|
|
383
|
+
* @example
|
|
384
|
+
* const londonTime = getZonedTime({ tz: 'Europe/London' });
|
|
124
385
|
*/
|
|
125
|
-
declare
|
|
386
|
+
declare function getZonedTime({ tz }?: {
|
|
387
|
+
tz?: string;
|
|
388
|
+
}): Date;
|
|
126
389
|
/**
|
|
127
|
-
*
|
|
390
|
+
* Formats the UTC offset of a timezone at the supplied date.
|
|
391
|
+
* An explicit date preserves daylight-saving and historical offset rules.
|
|
128
392
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
|
|
393
|
+
* @example
|
|
394
|
+
* getUTCOffset(date, 'Europe/Moscow'); // `(+3 UTC)`
|
|
395
|
+
*/
|
|
396
|
+
declare function getUTCOffset(date: Date, tz: string): string;
|
|
397
|
+
/**
|
|
398
|
+
* Formats the current time and UTC offset in the selected timezone.
|
|
399
|
+
* The timezone defaults to `Europe/London` when no option is provided.
|
|
132
400
|
*
|
|
133
|
-
*
|
|
401
|
+
* @example
|
|
402
|
+
* getFormattedTime({ tz: 'Europe/Moscow' }); // `03:04:05 (+3 UTC)`
|
|
134
403
|
*/
|
|
135
|
-
declare
|
|
404
|
+
declare function getFormattedTime({ tz }?: {
|
|
136
405
|
tz?: string;
|
|
137
|
-
})
|
|
406
|
+
}): string;
|
|
138
407
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
* By default, the result includes date, time, and UTC offset. This is useful for
|
|
142
|
-
* complete timestamps displayed in UI, bot messages, reports, or diagnostics.
|
|
408
|
+
* Formats the current date with optional time and UTC offset components.
|
|
409
|
+
* Time is included by default and uses the selected timezone for display.
|
|
143
410
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
411
|
+
* @example
|
|
412
|
+
* getFormattedDate({ tz: 'UTC', withTime: false }); // `02.01.2024`
|
|
146
413
|
*/
|
|
147
|
-
declare
|
|
414
|
+
declare function getFormattedDate({ tz, withTime, }?: {
|
|
148
415
|
tz?: string;
|
|
149
416
|
withTime?: boolean;
|
|
150
|
-
})
|
|
417
|
+
}): string;
|
|
151
418
|
/**
|
|
152
|
-
* Formats
|
|
153
|
-
*
|
|
154
|
-
* Unlike helpers that always use the current moment, this function accepts an
|
|
155
|
-
* explicit Date value and formats that exact point in time for another timezone.
|
|
419
|
+
* Formats an explicit instant in another timezone using the selected locale.
|
|
420
|
+
* The result includes localized date text, wall-clock time, and UTC offset.
|
|
156
421
|
*
|
|
157
|
-
*
|
|
422
|
+
* @example
|
|
423
|
+
* formatTime(date, { locale: ru, tz: 'Europe/Moscow' });
|
|
158
424
|
*/
|
|
159
|
-
declare
|
|
425
|
+
declare function formatTime(time: Date, { locale, tz }?: {
|
|
160
426
|
locale?: Locale;
|
|
161
427
|
tz?: string;
|
|
162
|
-
})
|
|
428
|
+
}): string;
|
|
163
429
|
|
|
164
430
|
/**
|
|
165
|
-
* Recursively replaces dots in a string with underscores
|
|
166
|
-
*
|
|
431
|
+
* Recursively replaces dots in a string literal with underscores.
|
|
432
|
+
* Every other character remains unchanged in the resulting type.
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* type Key = ReplaceDotsWithUnderscores<'foo.bar.baz'>; // `foo_bar_baz`
|
|
167
436
|
*/
|
|
168
|
-
type ReplaceDotsWithUnderscores<
|
|
437
|
+
type ReplaceDotsWithUnderscores<TValue extends string> = TValue extends `${infer Head}.${infer Tail}` ? `${Head}_${ReplaceDotsWithUnderscores<Tail>}` : TValue;
|
|
169
438
|
/**
|
|
170
|
-
*
|
|
171
|
-
*
|
|
439
|
+
* Maps string literals to immutable uppercase enum-like keys.
|
|
440
|
+
* Dots become underscores while every value preserves its original literal.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* type Statuses = StringEnumRecord<readonly ['review.pending', 'published']>;
|
|
172
444
|
*/
|
|
173
|
-
type StringEnumRecord<
|
|
174
|
-
[Value in
|
|
445
|
+
type StringEnumRecord<TValues extends readonly string[]> = Readonly<{
|
|
446
|
+
[Value in TValues[number] as Uppercase<ReplaceDotsWithUnderscores<Value>>]: Value;
|
|
175
447
|
}>;
|
|
176
448
|
/**
|
|
177
449
|
* Creates an immutable enum-like record from a readonly string array.
|
|
178
|
-
*
|
|
450
|
+
* Keys are uppercased and every dot is replaced with an underscore.
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* createStringEnumRecord(['foo.s', 'baz'] as const); // `{ FOO_S: 'foo.s', BAZ: 'baz' }`
|
|
179
454
|
*/
|
|
180
455
|
declare function createStringEnumRecord<const T extends readonly string[]>(values: T): StringEnumRecord<T>;
|
|
181
456
|
|
|
182
457
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
458
|
+
* Resolves synchronous and asynchronous executions through one promise-based contract.
|
|
459
|
+
* Failures use the supplied fallback or propagate unchanged when none is available.
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* await safeExecute(() => fetchData(), (error) => console.error(error));
|
|
463
|
+
*/
|
|
464
|
+
declare function safeExecute<T, E = never>(fn: () => Promise<T> | T, onError?: (error: unknown) => E | Promise<E>): Promise<T | E>;
|
|
465
|
+
/**
|
|
466
|
+
* Result returned after measuring one successful asynchronous execution.
|
|
467
|
+
* The original value is preserved beside its rounded millisecond duration.
|
|
185
468
|
*/
|
|
186
|
-
declare function safeExecute<T, E = never>(fn: () => Promise<T> | T, onError?: (error?: unknown) => E | Promise<E>): Promise<T | E>;
|
|
187
469
|
type MeasuredExecution<T> = {
|
|
188
|
-
/**
|
|
470
|
+
/**
|
|
471
|
+
* Value resolved by the measured execution without cloning or transformation.
|
|
472
|
+
* Its generic type remains identical to the original asynchronous result.
|
|
473
|
+
*/
|
|
189
474
|
result: T;
|
|
190
|
-
/**
|
|
475
|
+
/**
|
|
476
|
+
* Rounded wall-clock duration of the measured execution in milliseconds.
|
|
477
|
+
* The value is always collected after the supplied promise resolves.
|
|
478
|
+
*/
|
|
191
479
|
executionTime: number;
|
|
192
480
|
};
|
|
193
481
|
/**
|
|
194
|
-
*
|
|
195
|
-
*
|
|
482
|
+
* Measures an asynchronous execution while preserving its resolved result.
|
|
483
|
+
* Rejected executions propagate unchanged and do not produce a measurement.
|
|
196
484
|
*
|
|
197
|
-
*
|
|
485
|
+
* @example
|
|
198
486
|
* const { result, executionTime } = await measureExecutionTime(async () => {
|
|
199
487
|
* return await fetchData();
|
|
200
488
|
* });
|
|
201
489
|
* console.log(`Execution time: ${executionTime}ms`);
|
|
202
|
-
* ```
|
|
203
490
|
*/
|
|
204
491
|
declare function measureExecutionTime<T>(execution: () => Promise<T>): Promise<MeasuredExecution<T>>;
|
|
205
492
|
|
|
206
493
|
/**
|
|
207
|
-
* Creates a
|
|
208
|
-
*
|
|
494
|
+
* Creates a cryptographically sourced string from the alphanumeric set.
|
|
495
|
+
* Requested length defaults to `10` characters when omitted.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* generateRandomString(5); // `aZ3fG`
|
|
499
|
+
* generateRandomString(); // `G5kLm2P9sQ`
|
|
209
500
|
*/
|
|
210
501
|
declare function generateRandomString(length?: number): string;
|
|
211
502
|
|
|
212
503
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
504
|
+
* Selects a terminal color function for one HTTP response status.
|
|
505
|
+
* Successes are green, client errors yellow, and server errors red.
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* getColoredHTTPStatus(404)('404');
|
|
215
509
|
*/
|
|
216
510
|
declare function getColoredHTTPStatus(status: number): (text: string) => string;
|
|
217
511
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
512
|
+
* Shared logging interface for informational, warning, and error messages.
|
|
513
|
+
* Every level supports a service label while errors may include a stack trace.
|
|
220
514
|
*/
|
|
221
515
|
declare const log: {
|
|
516
|
+
/**
|
|
517
|
+
* Writes an informational message with an optional service label.
|
|
518
|
+
* Missing service names use the shared `log` fallback label.
|
|
519
|
+
*/
|
|
222
520
|
info: (message: string, service?: string) => void;
|
|
521
|
+
/**
|
|
522
|
+
* Writes a warning message with an optional service label.
|
|
523
|
+
* Missing service names use the shared `log` fallback label.
|
|
524
|
+
*/
|
|
223
525
|
warn: (message: string, service?: string) => void;
|
|
526
|
+
/**
|
|
527
|
+
* Writes an error message with optional service and stack trace context.
|
|
528
|
+
* Stack traces are rendered beneath the primary error message when supplied.
|
|
529
|
+
*/
|
|
224
530
|
error: (message: string, service?: string, stack?: string) => void;
|
|
225
531
|
};
|
|
226
532
|
|
|
@@ -244,13 +550,13 @@ type Simplify<T> = {
|
|
|
244
550
|
* identifierSchema: z.string().min(1),
|
|
245
551
|
* });
|
|
246
552
|
*/
|
|
247
|
-
declare
|
|
553
|
+
declare function zodBulkSelectionSchema<const TIdentifierSchema extends z.ZodType<string | number>>({ identifierSchema, }: {
|
|
248
554
|
/**
|
|
249
555
|
* Schema used to validate every included or excluded entity identifier.
|
|
250
556
|
* Its transforms and exact inferred output are preserved in both branches.
|
|
251
557
|
*/
|
|
252
558
|
identifierSchema: TIdentifierSchema;
|
|
253
|
-
})
|
|
559
|
+
}): z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
254
560
|
mode: z.ZodLiteral<"include">;
|
|
255
561
|
identifiers: z.ZodArray<TIdentifierSchema>;
|
|
256
562
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -278,30 +584,47 @@ type ZodBulkExcludeSelection<TIdentifier extends string | number = string> = Ext
|
|
|
278
584
|
mode: 'exclude';
|
|
279
585
|
}>;
|
|
280
586
|
|
|
281
|
-
/**
|
|
587
|
+
/**
|
|
588
|
+
* Configures the algorithm and default expiration used by `ZodJWTService`.
|
|
589
|
+
* Omitted values fall back to `HS256` and fifteen minutes respectively.
|
|
590
|
+
*/
|
|
282
591
|
type JWTServiceOptions = {
|
|
283
|
-
/**
|
|
592
|
+
/**
|
|
593
|
+
* Symmetric algorithm used to sign and verify every token handled by the service.
|
|
594
|
+
* Defaults to `HS256` when the configuration does not provide another value.
|
|
595
|
+
*/
|
|
284
596
|
algorithm?: SymmetricAlgorithm;
|
|
285
|
-
/**
|
|
597
|
+
/**
|
|
598
|
+
* Default lifetime assigned to signed tokens, expressed in seconds.
|
|
599
|
+
* Defaults to `900` seconds, which is equivalent to fifteen minutes.
|
|
600
|
+
*/
|
|
286
601
|
defaultExpirationSeconds?: number;
|
|
287
602
|
};
|
|
288
|
-
/**
|
|
603
|
+
/**
|
|
604
|
+
* Configures one JWT signing operation without changing service defaults.
|
|
605
|
+
* A supplied expiration takes precedence over `defaultExpirationSeconds`.
|
|
606
|
+
*/
|
|
289
607
|
type JWTSignOptions = {
|
|
290
|
-
/**
|
|
608
|
+
/**
|
|
609
|
+
* Lifetime assigned to the token created by this signing operation.
|
|
610
|
+
* Overrides the service default and remains expressed in seconds.
|
|
611
|
+
*/
|
|
291
612
|
expiresInSeconds?: number;
|
|
292
613
|
};
|
|
293
614
|
/**
|
|
294
|
-
*
|
|
615
|
+
* Resolves the parsed payload of a Zod schema or preserves a direct payload type.
|
|
616
|
+
* Schema transforms are reflected in the resulting inferred payload.
|
|
295
617
|
*/
|
|
296
618
|
type Payload<T> = T extends z$1.ZodType ? z$1.infer<T> : T;
|
|
297
619
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
620
|
+
* Preserves a Zod payload schema and rejects direct payload types with `never`.
|
|
621
|
+
* The result controls whether runtime payload validation is available.
|
|
622
|
+
*/
|
|
300
623
|
type PayloadSchema<T> = T extends z$1.ZodType ? T : never;
|
|
301
624
|
|
|
302
625
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
626
|
+
* Signs, decodes, and verifies JWTs with optional Zod payload validation.
|
|
627
|
+
* A supplied schema parses payloads returned by decoding and verification.
|
|
305
628
|
*/
|
|
306
629
|
declare class ZodJWTService<TPayloadOrSchema> {
|
|
307
630
|
readonly payloadSchema: PayloadSchema<TPayloadOrSchema> | undefined;
|
|
@@ -309,23 +632,27 @@ declare class ZodJWTService<TPayloadOrSchema> {
|
|
|
309
632
|
protected readonly defaultExpirationSeconds: number;
|
|
310
633
|
constructor(payloadSchema?: PayloadSchema<TPayloadOrSchema>, options?: JWTServiceOptions);
|
|
311
634
|
/**
|
|
312
|
-
* Signs a
|
|
313
|
-
*
|
|
635
|
+
* Signs a payload using the configured algorithm and expiration settings.
|
|
636
|
+
* Per-call expiration overrides the default configured by the service.
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* const token = await jwtService.sign({ userId: '123' }, secret, { expiresInSeconds: 300 });
|
|
314
640
|
*/
|
|
315
641
|
sign(payload: Payload<TPayloadOrSchema>, secret: string, options?: JWTSignOptions): Promise<string>;
|
|
316
642
|
/**
|
|
317
|
-
* Decodes
|
|
318
|
-
*
|
|
643
|
+
* Decodes without authenticating it and parses its payload when a schema exists.
|
|
644
|
+
* Schema validation failures return `null`, while malformed tokens still reject.
|
|
319
645
|
*
|
|
320
|
-
*
|
|
646
|
+
* @example
|
|
647
|
+
* const payload = await jwtService.decode(token);
|
|
321
648
|
*/
|
|
322
649
|
decode(token: string): Promise<Payload<TPayloadOrSchema> | null>;
|
|
323
650
|
/**
|
|
324
|
-
* Verifies
|
|
325
|
-
*
|
|
651
|
+
* Verifies a token using the configured algorithm and parses its payload.
|
|
652
|
+
* Signature, expiration, and schema validation failures reject the operation.
|
|
326
653
|
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
654
|
+
* @example
|
|
655
|
+
* const payload = await jwtService.verifyOrThrow(token, secret);
|
|
329
656
|
*/
|
|
330
657
|
verifyOrThrow(token: string, secret: string): Promise<Payload<TPayloadOrSchema>>;
|
|
331
658
|
}
|
|
@@ -462,11 +789,10 @@ type AsQuery<T> = T extends null | undefined ? T : T extends QueryPrimitive ? st
|
|
|
462
789
|
* This is useful for scenarios where you want to enforce that at least one
|
|
463
790
|
* of several optional (nullable) properties must be provided in an object.
|
|
464
791
|
*
|
|
465
|
-
*
|
|
792
|
+
* @example
|
|
466
793
|
* type Example = AtLeastOne<{ a?: string; b?: number; c?: boolean }>;
|
|
467
794
|
* // Valid: { a: "hello" }, { b: 42 }, { c: true }, { a: "hello", b: 42 }
|
|
468
795
|
* // Invalid: {}, { a: undefined, b: undefined, c: undefined }
|
|
469
|
-
* ```
|
|
470
796
|
*/
|
|
471
797
|
type AtLeastOne<T, Keys extends keyof T = keyof T> = Keys extends keyof T ? Simplify<Required<Pick<T, Keys>> & Partial<Omit<T, Keys>>> : never;
|
|
472
798
|
|
|
@@ -476,9 +802,8 @@ type AtLeastOne<T, Keys extends keyof T = keyof T> = Keys extends keyof T ? Simp
|
|
|
476
802
|
* 2. A `.transform()` that narrows the output type to `AtLeastOne<T>`,
|
|
477
803
|
* making it directly assignable to domain `*Select` and `*Update` types without casting.
|
|
478
804
|
*
|
|
479
|
-
*
|
|
805
|
+
* @example
|
|
480
806
|
* zQuery(zodAtLeastOne(userSelectSchema)) // result: UserSelect ✓
|
|
481
|
-
* ```
|
|
482
807
|
*/
|
|
483
808
|
declare const zodAtLeastOne: <T extends ZodObject<ZodRawShape>>(schema: T) => z.ZodPipe<T, z.ZodTransform<Awaited<AtLeastOne<z.core.output<T>>>, z.core.output<T>>>;
|
|
484
809
|
|
|
@@ -490,7 +815,7 @@ declare const parseQueryValue: (value: unknown) => unknown;
|
|
|
490
815
|
* numbers or booleans. This helper converts only clear primitive values, allowing
|
|
491
816
|
* regular schemas like `z.number()` and `z.boolean()` to validate query input directly.
|
|
492
817
|
*
|
|
493
|
-
*
|
|
818
|
+
* @example
|
|
494
819
|
* const schema = asQuery(z.object({
|
|
495
820
|
* page: z.number().int().positive(),
|
|
496
821
|
* isActive: z.boolean(),
|
|
@@ -498,7 +823,6 @@ declare const parseQueryValue: (value: unknown) => unknown;
|
|
|
498
823
|
*
|
|
499
824
|
* schema.parse({ page: '2', isActive: 'true' });
|
|
500
825
|
* // { page: 2, isActive: true }
|
|
501
|
-
* ```
|
|
502
826
|
*/
|
|
503
827
|
declare const asQuery: <T extends z.ZodTypeAny>(schema: T) => z.ZodPreprocess<T>;
|
|
504
828
|
|
|
@@ -508,4 +832,4 @@ declare const asQuery: <T extends z.ZodTypeAny>(schema: T) => z.ZodPreprocess<T>
|
|
|
508
832
|
*/
|
|
509
833
|
declare const isPlainObject: (value: unknown) => value is Record<string, unknown>;
|
|
510
834
|
|
|
511
|
-
export { type APIContractData, type APIContractError, type APIContractResult, type APIError, type APISuccess, type AsQuery, type AtLeastOne, EXCEPTION_STATUS_CODES, type ExceptionStatusCode, type FetchResult, type JWTServiceOptions, type JWTSignOptions, type MeasuredExecution, type Payload, type PayloadSchema, type ReplaceDotsWithUnderscores, SUCCESS_STATUS_CODES, type Simplify, type StringEnumRecord, type SuccessStatusCode, type ZodBulkExcludeSelection, type ZodBulkIncludeSelection, type ZodBulkSelection, ZodJWTService, type ZodPaginationOptions, type ZodSearchSchemaOptions, asQuery, createStringEnumRecord, failure, fetchAndThrow, fetchSafely, fileRespond, formatTime, generateRandomString, getColoredHTTPStatus, getFormattedDate, getFormattedTime, getUTCOffset, getZonedTime, honoLoggingHandler, isPlainObject, log, measureExecutionTime, onHandlerError, parseQueryValue, respond, safeExecute, sqlWhere, success, zodAtLeastOne, zodBulkSelectionSchema, zodPaginationSchema, zodPaginationShape, zodSearchSchema };
|
|
835
|
+
export { type APIContractData, type APIContractError, type APIContractResult, type APIError, type APISuccess, type AsQuery, type AtLeastOne, DEFAULT_UPLOAD_MAX_FILE_SIZE, EXCEPTION_STATUS_CODES, type ExceptionStatusCode, type FetchResult, type FileFormat, type FileFormatConfig, type HonoFileRespondOptions, type HonoRespondOptions, type JWTServiceOptions, type JWTSignOptions, type MeasuredExecution, type Payload, type PayloadSchema, type ReplaceDotsWithUnderscores, SUCCESS_STATUS_CODES, type Simplify, type StringEnumRecord, type SuccessStatusCode, type UploadFilesValidationOptions, type UploadFilesValidationResult, type UploadPreset, type UploadValidationError, type ZodBulkExcludeSelection, type ZodBulkIncludeSelection, type ZodBulkSelection, ZodJWTService, type ZodPaginationOptions, type ZodSearchSchemaOptions, type ZodUploadFileSchemaOptions, asQuery, createStringEnumRecord, createUploadAccept, createZodSearchWhereSchema, defineUploadPreset, documentUploadPreset, failure, fetchAndThrow, fetchSafely, fileFormat, fileFormatsArray, fileFormatsConfig, fileFormatsRecord, fileRespond, formatTime, generateRandomString, getColoredHTTPStatus, getFileExtension, getFormattedDate, getFormattedTime, getUTCOffset, getZonedTime, honoLoggingHandler, imageUploadPreset, isFileExtensionSupported, isFileFormatSupported, isFileMimeTypeSupported, isPlainObject, log, matchesMimeType, measureExecutionTime, normalizeFileExtension, onHandlerError, parseQueryValue, respond, safeExecute, sqlWhere, success, uploadValidationError, uploadValidationErrorsArray, uploadValidationErrorsRecord, validateUploadFile, validateUploadFiles, zodAtLeastOne, zodBulkSelectionSchema, zodPaginationSchema, zodPaginationShape, zodSearchQuerySchema, zodSearchSchema, zodUploadFileSchema };
|