@kalutskii/foundation 0.2.3 → 0.3.1
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 +20 -18
- package/dist/index.js +24 -25
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import * as hono from 'hono';
|
|
1
2
|
import { ErrorHandler, MiddlewareHandler, Context, TypedResponse, ValidationTargets } from 'hono';
|
|
2
|
-
import
|
|
3
|
+
import * as zod from 'zod';
|
|
4
|
+
import zod__default, { z, ZodNumber, ZodType } from 'zod';
|
|
5
|
+
import * as hono_utils_types from 'hono/utils/types';
|
|
6
|
+
import * as zod_v4_core from 'zod/v4/core';
|
|
7
|
+
import * as zod_v3 from 'zod/v3';
|
|
3
8
|
import { Locale } from 'date-fns';
|
|
4
9
|
import { SymmetricAlgorithm } from 'hono/utils/jwt/jwa';
|
|
5
10
|
|
|
@@ -87,19 +92,11 @@ declare function respond<T extends object = Record<string, never>, S extends Suc
|
|
|
87
92
|
data?: T;
|
|
88
93
|
}): Response & TypedResponse<APISuccess<SerializeDates<T>> | APIError, S, 'json'>;
|
|
89
94
|
|
|
90
|
-
/**
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
query: (c: Context) => unknown;
|
|
96
|
-
param: (c: Context) => unknown;
|
|
97
|
-
};
|
|
98
|
-
/**
|
|
99
|
-
* Reads the raw payload from the request and validates it against the provided Zod schema.
|
|
100
|
-
* Throws an `HTTPException(400)` when validation fails or when the payload cannot be read.
|
|
101
|
-
*/
|
|
102
|
-
declare function requirePayload<TSchema extends z.ZodTypeAny>(c: Context, target: PayloadTarget, schema: TSchema): Promise<z.infer<TSchema>>;
|
|
95
|
+
/** Wrapper around the standard hono/zod-validator, throws HTTPException on validation failure. */
|
|
96
|
+
declare const zQuery: <T extends ZodType, Target extends keyof ValidationTargets>(target: Target, schema: T) => hono.MiddlewareHandler<hono.Env, string, {
|
|
97
|
+
in: (undefined extends (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) ? true : false) extends true ? { [K in Target]?: ([T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never] extends [ValidationTargets[K]] ? ValidationTargets[K] & (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) : [Exclude<T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never, undefined>] extends [never] ? {} : [Exclude<T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never, undefined>] extends [object] ? undefined extends (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) ? ((T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) & undefined) | (((Exclude<T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never, (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) & undefined> extends infer T_3 ? { [K_4 in keyof T_3]: ([Exclude<T_3[K_4], undefined>] extends [string] ? [string & Exclude<T_3[K_4], undefined>] extends [hono_utils_types.UnionToIntersection<string & Exclude<T_3[K_4], undefined>>] ? false : true : false) extends true ? T_3[K_4] : ([unknown] extends [T_3[K_4]] ? false : undefined extends T_3[K_4] ? true : false) extends true ? T_3[K_4] : Target_1 extends "form" ? T$1 | T$1[] : Target_1 extends "query" ? string | string[] : Target_1 extends "param" ? string : Target_1 extends "header" ? string : Target_1 extends "cookie" ? string : unknown; } : never) extends infer T_2 ? { [K_3 in keyof T_2]: T_2[K_3]; } : never) extends infer T_1 ? { [K_2 in keyof T_1]: T_1[K_2]; } : never) : (((T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) extends infer T_6 ? { [K_7 in keyof T_6]: ([Exclude<T_6[K_7], undefined>] extends [string] ? [string & Exclude<T_6[K_7], undefined>] extends [hono_utils_types.UnionToIntersection<string & Exclude<T_6[K_7], undefined>>] ? false : true : false) extends true ? T_6[K_7] : ([unknown] extends [T_6[K_7]] ? false : undefined extends T_6[K_7] ? true : false) extends true ? T_6[K_7] : Target_1 extends "form" ? T$1 | T$1[] : Target_1 extends "query" ? string | string[] : Target_1 extends "param" ? string : Target_1 extends "header" ? string : Target_1 extends "cookie" ? string : unknown; } : never) extends infer T_5 ? { [K_6 in keyof T_5]: T_5[K_6]; } : never) extends infer T_4 ? { [K_5 in keyof T_4]: T_4[K_5]; } : never : {}) | undefined; } : { [K_1 in Target]: [T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never] extends [ValidationTargets[K_1]] ? ValidationTargets[K_1] & (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) : [Exclude<T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never, undefined>] extends [never] ? {} : [Exclude<T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never, undefined>] extends [object] ? undefined extends (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) ? ((T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) & undefined) | (((Exclude<T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never, (T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) & undefined> extends infer T_3 ? { [K_5 in keyof T_3]: ([Exclude<T_3[K_5], undefined>] extends [string] ? [string & Exclude<T_3[K_5], undefined>] extends [hono_utils_types.UnionToIntersection<string & Exclude<T_3[K_5], undefined>>] ? false : true : false) extends true ? T_3[K_5] : ([unknown] extends [T_3[K_5]] ? false : undefined extends T_3[K_5] ? true : false) extends true ? T_3[K_5] : Target_1 extends "form" ? T$1 | T$1[] : Target_1 extends "query" ? string | string[] : Target_1 extends "param" ? string : Target_1 extends "header" ? string : Target_1 extends "cookie" ? string : unknown; } : never) extends infer T_2 ? { [K_4 in keyof T_2]: T_2[K_4]; } : never) extends infer T_1 ? { [K_3 in keyof T_1]: T_1[K_3]; } : never) : (((T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.input<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.input<T> : never) extends infer T_6 ? { [K_8 in keyof T_6]: ([Exclude<T_6[K_8], undefined>] extends [string] ? [string & Exclude<T_6[K_8], undefined>] extends [hono_utils_types.UnionToIntersection<string & Exclude<T_6[K_8], undefined>>] ? false : true : false) extends true ? T_6[K_8] : ([unknown] extends [T_6[K_8]] ? false : undefined extends T_6[K_8] ? true : false) extends true ? T_6[K_8] : Target_1 extends "form" ? T$1 | T$1[] : Target_1 extends "query" ? string | string[] : Target_1 extends "param" ? string : Target_1 extends "header" ? string : Target_1 extends "cookie" ? string : unknown; } : never) extends infer T_5 ? { [K_7 in keyof T_5]: T_5[K_7]; } : never) extends infer T_4 ? { [K_6 in keyof T_4]: T_4[K_6]; } : never : {}; };
|
|
98
|
+
out: { [K_2 in Target]: T extends zod_v3.ZodType<any, zod_v3.ZodTypeDef, any> ? zod_v3.output<T> : T extends zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>> ? zod.infer<T> : never; };
|
|
99
|
+
}, never>;
|
|
103
100
|
|
|
104
101
|
/**
|
|
105
102
|
* Returns the current time in the specified timezone.
|
|
@@ -178,7 +175,7 @@ type JWTSignOptions = {
|
|
|
178
175
|
expiresInSeconds?: number;
|
|
179
176
|
};
|
|
180
177
|
|
|
181
|
-
declare class ZodJWTService<TSchema extends
|
|
178
|
+
declare class ZodJWTService<TSchema extends zod__default.ZodObject<zod__default.ZodRawShape>> {
|
|
182
179
|
readonly payloadSchema: TSchema;
|
|
183
180
|
protected readonly algorithm: SymmetricAlgorithm;
|
|
184
181
|
protected readonly defaultExpirationSeconds: number;
|
|
@@ -187,12 +184,17 @@ declare class ZodJWTService<TSchema extends z$1.ZodObject<z$1.ZodRawShape>> {
|
|
|
187
184
|
* Signs a JWT token with the provided payload and secret, using the configured algorithm and expiration settings.
|
|
188
185
|
* Example usage: `const accessToken = await JWTServiceInstance.sign({ userId: 123 }, 'my-secret', { expiresInSeconds: 300 });`
|
|
189
186
|
*/
|
|
190
|
-
sign(payload:
|
|
187
|
+
sign(payload: zod__default.infer<TSchema>, secret: string, options?: JWTSignOptions): Promise<string>;
|
|
188
|
+
/**
|
|
189
|
+
* Decodes a JWT token, and validates the payload against the Zod schema.
|
|
190
|
+
* Note: This method does NOT verify the token's signature or check for expiration.
|
|
191
|
+
*/
|
|
192
|
+
decode(token: string): Promise<zod__default.infer<TSchema> | null>;
|
|
191
193
|
/**
|
|
192
194
|
* Verifies and decodes a JWT token using the provided secret and configured algorithm,
|
|
193
195
|
* then validates the payload against the Zod schema, also throws on expired tokens.
|
|
194
196
|
*/
|
|
195
|
-
verifyOrThrow(token: string, secret: string): Promise<
|
|
197
|
+
verifyOrThrow(token: string, secret: string): Promise<zod__default.infer<TSchema>>;
|
|
196
198
|
}
|
|
197
199
|
|
|
198
|
-
export { type APIContractData, type APIContractError, type APIContractResult, type APIError, type APISuccess, EXCEPTION_STATUS_CODES, type ExceptionStatusCode, type FetchResult, type JWTServiceOptions, type JWTSignOptions, SUCCESS_STATUS_CODES, type SerializeDates, type SuccessStatusCode, ZodJWTService, asQueryBoolean, asQueryNumber, failure, fetchAndThrow, fetchSafely, formatTime, generateRandomString, getColoredHTTPStatus, getFormattedDate, getFormattedTime, getUTCOffset, getZonedTime, honoLoggingHandler, log, onHandlerError,
|
|
200
|
+
export { type APIContractData, type APIContractError, type APIContractResult, type APIError, type APISuccess, EXCEPTION_STATUS_CODES, type ExceptionStatusCode, type FetchResult, type JWTServiceOptions, type JWTSignOptions, SUCCESS_STATUS_CODES, type SerializeDates, type SuccessStatusCode, ZodJWTService, asQueryBoolean, asQueryNumber, failure, fetchAndThrow, fetchSafely, formatTime, generateRandomString, getColoredHTTPStatus, getFormattedDate, getFormattedTime, getUTCOffset, getZonedTime, honoLoggingHandler, log, onHandlerError, respond, safeExecute, success, zQuery };
|
package/dist/index.js
CHANGED
|
@@ -75,13 +75,13 @@ function getColoredHTTPStatus(status) {
|
|
|
75
75
|
{ range: [400, 499], colorFn: yellow },
|
|
76
76
|
{ range: [500, 599], colorFn: red }
|
|
77
77
|
];
|
|
78
|
-
const statusColor = colorMap.find(({ range: [min, max] }) => status >=
|
|
78
|
+
const statusColor = colorMap.find(({ range: [min, max] }) => status >= min && status <= max);
|
|
79
79
|
return statusColor ? statusColor.colorFn : (text) => text;
|
|
80
80
|
}
|
|
81
81
|
function writeLog(message, level, service = "log", stack) {
|
|
82
82
|
const logColorMap = { info: blue, warn: yellow, error: red };
|
|
83
83
|
const timestamp = dim(getFormattedTime());
|
|
84
|
-
const serviceName = logColorMap[level](service
|
|
84
|
+
const serviceName = logColorMap[level](service.padEnd(12));
|
|
85
85
|
const formattedMessage = white(message);
|
|
86
86
|
console.log(`[${timestamp}] ${serviceName} | ${formattedMessage}`);
|
|
87
87
|
if (stack)
|
|
@@ -96,7 +96,7 @@ var log = {
|
|
|
96
96
|
// src/hono/hono.execution.ts
|
|
97
97
|
function proceedUnhandledError(error) {
|
|
98
98
|
const errorId = generateRandomString(6);
|
|
99
|
-
const errorMessage = error instanceof Error ? error.
|
|
99
|
+
const errorMessage = error instanceof Error ? error.stack ?? error.message : JSON.stringify(error);
|
|
100
100
|
log.error(`Unhandled error: ${red2(errorMessage)}`, errorId);
|
|
101
101
|
return failure({ status: 500, error: `Internal server error | ${errorId}` });
|
|
102
102
|
}
|
|
@@ -131,7 +131,15 @@ function respond(c, options) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// src/hono/hono.validation.ts
|
|
134
|
+
import { zValidator as zv } from "@hono/zod-validator";
|
|
134
135
|
import { HTTPException as HTTPException2 } from "hono/http-exception";
|
|
136
|
+
var zQuery = (target, schema) => {
|
|
137
|
+
return zv(target, schema, (result, _c) => {
|
|
138
|
+
if (result.success)
|
|
139
|
+
return;
|
|
140
|
+
throw new HTTPException2(400, { message: result.error.message });
|
|
141
|
+
});
|
|
142
|
+
};
|
|
135
143
|
|
|
136
144
|
// src/utilities/execution.utilities.ts
|
|
137
145
|
async function safeExecute(fn, onError) {
|
|
@@ -144,23 +152,6 @@ async function safeExecute(fn, onError) {
|
|
|
144
152
|
}
|
|
145
153
|
}
|
|
146
154
|
|
|
147
|
-
// src/hono/hono.validation.ts
|
|
148
|
-
var FALLBACK_ERROR_MESSAGE = "Failed to decode request payload, please ensure it is correctly formatted.";
|
|
149
|
-
var requestReaders = {
|
|
150
|
-
json: async (c) => safeExecute(() => c.req.json(), () => {
|
|
151
|
-
throw new HTTPException2(400, { message: FALLBACK_ERROR_MESSAGE });
|
|
152
|
-
}),
|
|
153
|
-
query: (c) => c.req.query(),
|
|
154
|
-
param: (c) => c.req.param()
|
|
155
|
-
};
|
|
156
|
-
async function requirePayload(c, target, schema) {
|
|
157
|
-
const rawPayload = await requestReaders[target](c);
|
|
158
|
-
const parsedPayload = await schema.safeParseAsync(rawPayload);
|
|
159
|
-
if (parsedPayload.success)
|
|
160
|
-
return parsedPayload.data;
|
|
161
|
-
throw new HTTPException2(400, { message: parsedPayload.error.message });
|
|
162
|
-
}
|
|
163
|
-
|
|
164
155
|
// src/utilities/serialization.utilities.ts
|
|
165
156
|
import { z } from "zod";
|
|
166
157
|
var asQueryNumber = (schema) => z.preprocess((v) => typeof v === "string" ? Number(v) : v, schema);
|
|
@@ -182,7 +173,7 @@ var asQueryBoolean = (schema) => {
|
|
|
182
173
|
};
|
|
183
174
|
|
|
184
175
|
// src/zod-jwt/zod-jwt.schemas.ts
|
|
185
|
-
import { sign as signJWT, verify as verifyJWT } from "hono/jwt";
|
|
176
|
+
import { decode as decodeJWT, sign as signJWT, verify as verifyJWT } from "hono/jwt";
|
|
186
177
|
var ZodJWTService = class {
|
|
187
178
|
payloadSchema;
|
|
188
179
|
algorithm;
|
|
@@ -200,13 +191,22 @@ var ZodJWTService = class {
|
|
|
200
191
|
const exp = Math.floor(Date.now() / 1e3) + (options?.expiresInSeconds ?? this.defaultExpirationSeconds);
|
|
201
192
|
return signJWT({ ...payload, exp }, secret, this.algorithm);
|
|
202
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Decodes a JWT token, and validates the payload against the Zod schema.
|
|
196
|
+
* Note: This method does NOT verify the token's signature or check for expiration.
|
|
197
|
+
*/
|
|
198
|
+
async decode(token) {
|
|
199
|
+
const { payload } = decodeJWT(token);
|
|
200
|
+
const { success: success2, data } = await this.payloadSchema.safeParseAsync(payload);
|
|
201
|
+
return success2 ? data : null;
|
|
202
|
+
}
|
|
203
203
|
/**
|
|
204
204
|
* Verifies and decodes a JWT token using the provided secret and configured algorithm,
|
|
205
205
|
* then validates the payload against the Zod schema, also throws on expired tokens.
|
|
206
206
|
*/
|
|
207
207
|
async verifyOrThrow(token, secret) {
|
|
208
208
|
const payload = await verifyJWT(token, secret, this.algorithm);
|
|
209
|
-
return this.payloadSchema.
|
|
209
|
+
return this.payloadSchema.parseAsync(payload);
|
|
210
210
|
}
|
|
211
211
|
};
|
|
212
212
|
export {
|
|
@@ -228,9 +228,8 @@ export {
|
|
|
228
228
|
honoLoggingHandler,
|
|
229
229
|
log,
|
|
230
230
|
onHandlerError,
|
|
231
|
-
requestReaders,
|
|
232
|
-
requirePayload,
|
|
233
231
|
respond,
|
|
234
232
|
safeExecute,
|
|
235
|
-
success
|
|
233
|
+
success,
|
|
234
|
+
zQuery
|
|
236
235
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kalutskii/foundation",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Typescript collection of most common utilities, schemas and functions among private projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dist"
|
|
26
26
|
],
|
|
27
27
|
"peerDependencies": {
|
|
28
|
+
"@hono/zod-validator": "^0.8.0",
|
|
28
29
|
"date-fns": "^4.1.0",
|
|
29
30
|
"date-fns-tz": "^3.2.0",
|
|
30
31
|
"hono": "^4.12.18",
|