@kalutskii/foundation 0.6.19 → 0.6.21
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/README.md +11 -11
- package/dist/index.d.ts +24 -6
- package/dist/index.js +6 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ Status code groups are exported as constants and used by types:
|
|
|
42
42
|
|
|
43
43
|
### 1. Build typed contracts
|
|
44
44
|
|
|
45
|
-
```
|
|
45
|
+
```typescript
|
|
46
46
|
import { failure, success } from '@kalutskii/foundation';
|
|
47
47
|
import type { APIContractResult } from '@kalutskii/foundation';
|
|
48
48
|
|
|
@@ -56,7 +56,7 @@ const result: APIContractResult<User> = Math.random() > 0.5 ? ok : bad;
|
|
|
56
56
|
|
|
57
57
|
### 2. Resolve fetchers safely
|
|
58
58
|
|
|
59
|
-
```
|
|
59
|
+
```typescript
|
|
60
60
|
import { fetchAndThrow, fetchSafely } from '@kalutskii/foundation';
|
|
61
61
|
import type { APIContractResult } from '@kalutskii/foundation';
|
|
62
62
|
|
|
@@ -81,7 +81,7 @@ try {
|
|
|
81
81
|
|
|
82
82
|
### 3. Use typed Hono JSON responses
|
|
83
83
|
|
|
84
|
-
```
|
|
84
|
+
```typescript
|
|
85
85
|
import { respond } from '@kalutskii/foundation';
|
|
86
86
|
import { Hono } from 'hono';
|
|
87
87
|
|
|
@@ -99,7 +99,7 @@ app.get('/health', (c) => {
|
|
|
99
99
|
|
|
100
100
|
### 4. Wire up Hono error handler and logging middleware
|
|
101
101
|
|
|
102
|
-
```
|
|
102
|
+
```typescript
|
|
103
103
|
import { honoLoggingHandler, onHandlerError } from '@kalutskii/foundation';
|
|
104
104
|
import { Hono } from 'hono';
|
|
105
105
|
|
|
@@ -116,7 +116,7 @@ Example: `[12:12:12 (+4 UTC)] hono | POST 200 123ms /api/v1/users (se
|
|
|
116
116
|
|
|
117
117
|
### 5. Execute functions safely and measure performance
|
|
118
118
|
|
|
119
|
-
```
|
|
119
|
+
```typescript
|
|
120
120
|
import { measureExecutionTime, safeExecute } from '@kalutskii/foundation';
|
|
121
121
|
|
|
122
122
|
const result = await safeExecute(
|
|
@@ -130,7 +130,7 @@ console.log(`Done in ${executionTime}ms`);
|
|
|
130
130
|
|
|
131
131
|
### 6. Parse query params with `asQuery`
|
|
132
132
|
|
|
133
|
-
```
|
|
133
|
+
```typescript
|
|
134
134
|
import { asQuery } from '@kalutskii/foundation';
|
|
135
135
|
import { z } from 'zod';
|
|
136
136
|
|
|
@@ -146,7 +146,7 @@ schema.parse({ page: '2', isActive: 'true' }); // { page: 2, isActive: true }
|
|
|
146
146
|
|
|
147
147
|
### 8. Build flat query schemas from nested objects
|
|
148
148
|
|
|
149
|
-
```
|
|
149
|
+
```typescript
|
|
150
150
|
import { asQuerySchema } from '@kalutskii/foundation';
|
|
151
151
|
import { z } from 'zod';
|
|
152
152
|
|
|
@@ -173,7 +173,7 @@ schema.parse({ sort: { field: 'name', order: 'asc' } }); // throws
|
|
|
173
173
|
|
|
174
174
|
### 8. Use pagination schema
|
|
175
175
|
|
|
176
|
-
```
|
|
176
|
+
```typescript
|
|
177
177
|
import { refinePagination, zodPaginationSchema, zodPaginationShape } from '@kalutskii/foundation';
|
|
178
178
|
import { z } from 'zod';
|
|
179
179
|
|
|
@@ -195,7 +195,7 @@ await db.query.users.findMany({
|
|
|
195
195
|
|
|
196
196
|
### 9. Work with JWT using `ZodJWTService`
|
|
197
197
|
|
|
198
|
-
```
|
|
198
|
+
```typescript
|
|
199
199
|
import { ZodJWTService } from '@kalutskii/foundation';
|
|
200
200
|
import { z } from 'zod';
|
|
201
201
|
|
|
@@ -212,7 +212,7 @@ const decoded = await jwt.decode(token);
|
|
|
212
212
|
|
|
213
213
|
### 10. Datetime helpers
|
|
214
214
|
|
|
215
|
-
```
|
|
215
|
+
```typescript
|
|
216
216
|
import { formatTime, getFormattedDate, getFormattedTime, getZonedTime } from '@kalutskii/foundation';
|
|
217
217
|
|
|
218
218
|
getFormattedTime({ tz: 'Europe/Moscow' }); // '15:30:00 (+3 UTC)'
|
|
@@ -223,7 +223,7 @@ formatTime(new Date(), { tz: 'Europe/Moscow' }); // '15:30:00, 22 июня 2026
|
|
|
223
223
|
|
|
224
224
|
### 11. Logging
|
|
225
225
|
|
|
226
|
-
```
|
|
226
|
+
```typescript
|
|
227
227
|
import { log } from '@kalutskii/foundation';
|
|
228
228
|
|
|
229
229
|
log.info('Server started', 'app');
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import z, { ZodObject, ZodRawShape, z as z$1 } from 'zod';
|
|
|
10
10
|
* Maps each `where` entry to `eq(table[key], value)` and combines them with `and`.
|
|
11
11
|
* Assumes that `where` was already validated and contains only existing table fields.
|
|
12
12
|
*
|
|
13
|
-
* ```
|
|
13
|
+
* ```typescript
|
|
14
14
|
* await db.update(usersTable).set(values).where(sqlWhere(usersTable, { id: 1 })).returning();
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
@@ -73,7 +73,7 @@ type AsQuery<T> = T extends null | undefined ? T : T extends QueryPrimitive ? st
|
|
|
73
73
|
* This is useful for scenarios where you want to enforce that at least one
|
|
74
74
|
* of several optional (nullable) properties must be provided in an object.
|
|
75
75
|
*
|
|
76
|
-
* ```
|
|
76
|
+
* ```typescript
|
|
77
77
|
* type Example = AtLeastOne<{ a?: string; b?: number; c?: boolean }>;
|
|
78
78
|
* // Valid: { a: "hello" }, { b: 42 }, { c: true }, { a: "hello", b: 42 }
|
|
79
79
|
* // Invalid: {}, { a: undefined, b: undefined, c: undefined }
|
|
@@ -174,6 +174,24 @@ declare const formatTime: (time: Date, { locale, tz }?: {
|
|
|
174
174
|
tz?: string;
|
|
175
175
|
}) => string;
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Recursively replaces dots in a string with underscores in a type-safe manner.
|
|
179
|
+
* Example: `ReplaceDotsWithUnderscores<'foo.bar.baz.ok'>` → `'foo_bar_baz_ok'`.
|
|
180
|
+
*/
|
|
181
|
+
type ReplaceDotsWithUnderscores<T extends string> = T extends `${infer A}.${infer B}` ? `${A}_${ReplaceDotsWithUnderscores<B>}` : T;
|
|
182
|
+
/**
|
|
183
|
+
* Type-safe record mapping string values to ergonomic enum-like keys.
|
|
184
|
+
* Keys are uppercased and dots are replaced with underscores.
|
|
185
|
+
*/
|
|
186
|
+
type StringEnumRecord<T extends readonly string[]> = Readonly<{
|
|
187
|
+
[Value in T[number] as Uppercase<ReplaceDotsWithUnderscores<Value>>]: Value;
|
|
188
|
+
}>;
|
|
189
|
+
/**
|
|
190
|
+
* Creates an immutable enum-like record from a readonly string array.
|
|
191
|
+
* Example: `['foo.s', 'baz'] as const` → `{ FOO_S: 'foo.s', BAZ: 'baz' }`.
|
|
192
|
+
*/
|
|
193
|
+
declare function createStringEnumRecord<const T extends readonly string[]>(values: T): StringEnumRecord<T>;
|
|
194
|
+
|
|
177
195
|
/**
|
|
178
196
|
* Safely executes functions and handles errors without using try/catch in the calling code.
|
|
179
197
|
* Example usage: `safeExecute(() => fetchData(), (error) => console.error(error))`
|
|
@@ -189,7 +207,7 @@ type MeasuredExecution<T> = {
|
|
|
189
207
|
* Utility function to measure the execution time of an asynchronous function.
|
|
190
208
|
* @returns An object containing the result of the execution and the time taken in milliseconds.
|
|
191
209
|
*
|
|
192
|
-
* ```
|
|
210
|
+
* ```typescript
|
|
193
211
|
* const { result, executionTime } = await measureExecutionTime(async () => {
|
|
194
212
|
* return await fetchData();
|
|
195
213
|
* });
|
|
@@ -306,7 +324,7 @@ type ZodPaginationOptions = z.infer<typeof zodPaginationSchema>;
|
|
|
306
324
|
* 2. A `.transform()` that narrows the output type to `AtLeastOne<T>`,
|
|
307
325
|
* making it directly assignable to domain `*Select` and `*Update` types without casting.
|
|
308
326
|
*
|
|
309
|
-
* ```
|
|
327
|
+
* ```typescript
|
|
310
328
|
* zQuery(zodAtLeastOne(userSelectSchema)) // result: UserSelect ✓
|
|
311
329
|
* ```
|
|
312
330
|
*/
|
|
@@ -320,7 +338,7 @@ declare const parseQueryValue: (value: unknown) => unknown;
|
|
|
320
338
|
* numbers or booleans. This helper converts only clear primitive values, allowing
|
|
321
339
|
* regular schemas like `z.number()` and `z.boolean()` to validate query input directly.
|
|
322
340
|
*
|
|
323
|
-
* ```
|
|
341
|
+
* ```typescript
|
|
324
342
|
* const schema = asQuery(z.object({
|
|
325
343
|
* page: z.number().int().positive(),
|
|
326
344
|
* isActive: z.boolean(),
|
|
@@ -338,4 +356,4 @@ declare const asQuery: <T extends z.ZodTypeAny>(schema: T) => z.ZodPreprocess<T>
|
|
|
338
356
|
*/
|
|
339
357
|
declare const isPlainObject: (value: unknown) => value is Record<string, unknown>;
|
|
340
358
|
|
|
341
|
-
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, SUCCESS_STATUS_CODES, type Simplify, type SuccessStatusCode, ZodJWTService, type ZodPaginationOptions, asQuery, failure, fetchAndThrow, fetchSafely, formatTime, generateRandomString, getColoredHTTPStatus, getFormattedDate, getFormattedTime, getUTCOffset, getZonedTime, honoLoggingHandler, isPlainObject, log, measureExecutionTime, onHandlerError, parseQueryValue, respond, safeExecute, sqlWhere, success, zodAtLeastOne, zodPaginationSchema, zodPaginationShape };
|
|
359
|
+
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, ZodJWTService, type ZodPaginationOptions, asQuery, createStringEnumRecord, failure, fetchAndThrow, fetchSafely, formatTime, generateRandomString, getColoredHTTPStatus, getFormattedDate, getFormattedTime, getUTCOffset, getZonedTime, honoLoggingHandler, isPlainObject, log, measureExecutionTime, onHandlerError, parseQueryValue, respond, safeExecute, sqlWhere, success, zodAtLeastOne, zodPaginationSchema, zodPaginationShape };
|
package/dist/index.js
CHANGED
|
@@ -142,6 +142,11 @@ async function fetchAndThrow(fetcher) {
|
|
|
142
142
|
return response.data;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
// src/utilities/enums.utilities.ts
|
|
146
|
+
function createStringEnumRecord(values) {
|
|
147
|
+
return Object.freeze(Object.fromEntries(values.map((value) => [value.replace(/\./g, "_").toUpperCase(), value])));
|
|
148
|
+
}
|
|
149
|
+
|
|
145
150
|
// src/utilities/execution.utilities.ts
|
|
146
151
|
async function safeExecute(fn, onError) {
|
|
147
152
|
try {
|
|
@@ -260,6 +265,7 @@ export {
|
|
|
260
265
|
SUCCESS_STATUS_CODES,
|
|
261
266
|
ZodJWTService,
|
|
262
267
|
asQuery,
|
|
268
|
+
createStringEnumRecord,
|
|
263
269
|
failure,
|
|
264
270
|
fetchAndThrow,
|
|
265
271
|
fetchSafely,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kalutskii/foundation",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.21",
|
|
4
4
|
"description": "Typescript collection of most common utilities, schemas and functions among private projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsup",
|
|
15
|
-
"lint": "eslint . --ext .ts",
|
|
15
|
+
"lint": "eslint . --ext .ts --fix",
|
|
16
16
|
"format": "prettier --write .",
|
|
17
17
|
"typecheck": "tsc --noEmit"
|
|
18
18
|
},
|