@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 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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- ```ts
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
- * ```ts
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
- * ```ts
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
- * ```ts
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
- * ```ts
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
- * ```ts
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.19",
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
  },