hono-utils 0.4.0 → 0.5.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.mjs ADDED
@@ -0,0 +1,366 @@
1
+ import { createMiddleware } from 'hono/factory';
2
+ import { Logger } from 'hierarchical-area-logger';
3
+ import { HTTPException } from 'hono/http-exception';
4
+ import { validator } from 'hono/validator';
5
+ import { z } from 'zod';
6
+ import { UAParser } from 'ua-parser-js';
7
+ import { h as hash } from './shared/hono-utils.BOXr1V_a.mjs';
8
+ import { init } from '@paralleldrive/cuid2';
9
+
10
+ const logger = (details, parentEventIdHeader) => createMiddleware(async (c, next) => {
11
+ const logger2 = new Logger({
12
+ details,
13
+ withParentEventId: !!parentEventIdHeader,
14
+ parentEventId: parentEventIdHeader ? c.req.raw.headers.get(parentEventIdHeader) ?? void 0 : void 0,
15
+ defaultArea: new URL(c.req.raw.url).pathname,
16
+ path: new URL(c.req.raw.url).pathname
17
+ });
18
+ c.set("logger", logger2);
19
+ c.set("eventId", logger2.eventId);
20
+ await next();
21
+ });
22
+
23
+ const jsonValidator = (schema) => validator("json", (value) => {
24
+ const parsed = schema.safeParse(value);
25
+ if (!parsed.success) {
26
+ throw new HTTPException(400, {
27
+ message: z.prettifyError(parsed.error)
28
+ });
29
+ }
30
+ return parsed.data;
31
+ });
32
+
33
+ const isBot = ({ threshold, allowVerifiedBot, useLogger } = {
34
+ threshold: 49
35
+ }) => createMiddleware(async (c, next) => {
36
+ const logger = useLogger ? (c.get("logger") ?? new Logger({
37
+ details: {
38
+ service: "dummy"
39
+ }
40
+ })).getArea("middeware:isBot") : void 0;
41
+ logger?.debug("Retrieving bot management data from cloudflare data");
42
+ const botManagement = c.req.raw.cf?.botManagement;
43
+ if (!botManagement) {
44
+ throw new Error("botManagement is not available");
45
+ }
46
+ const score = botManagement?.score ?? 54;
47
+ const verifiedBot = botManagement?.verifiedBot ?? false;
48
+ const isBotByScore = score < threshold;
49
+ const isVerifiedAllowed = !!(allowVerifiedBot && verifiedBot);
50
+ const isBot2 = isBotByScore;
51
+ logger?.debug("Setting isBot variable in context", {
52
+ isBotByScore,
53
+ isVerifiedAllowed,
54
+ isBot: isBot2
55
+ });
56
+ logger?.info("isBot variable set");
57
+ c.set("isBot", isBot2);
58
+ if (isBotByScore && !isVerifiedAllowed) {
59
+ throw new HTTPException(401, { message: "Bot detected" });
60
+ }
61
+ await next();
62
+ });
63
+
64
+ const setI18n = (translations, language, defaultLanguage) => (input, params, overrideLanguage) => {
65
+ const result = input.split(".").reduce(
66
+ (acc, key) => {
67
+ if (acc && typeof acc === "object" && key in acc) {
68
+ return acc[key];
69
+ } else {
70
+ if (translations[defaultLanguage] && typeof translations[defaultLanguage] === "object" && key in translations[defaultLanguage]) {
71
+ return translations[defaultLanguage][key];
72
+ } else {
73
+ return input;
74
+ }
75
+ }
76
+ },
77
+ translations[overrideLanguage ?? language]
78
+ );
79
+ if (params) {
80
+ return Object.keys(params).reduce(
81
+ (acc, key) => {
82
+ return acc.replace(
83
+ new RegExp(`{{${key}}}`, "g"),
84
+ params[key].toString()
85
+ );
86
+ },
87
+ typeof result === "string" ? result : input
88
+ );
89
+ }
90
+ return typeof result === "string" ? result : input;
91
+ };
92
+ const i18n = (translations, defaultLanguage) => ({
93
+ middleware: createMiddleware(async ({ set, var: { language } }, next) => {
94
+ if (!language) {
95
+ throw new Error(
96
+ "Language variable should be initialized before translations middleware"
97
+ );
98
+ }
99
+ set("t", setI18n(translations, language, defaultLanguage));
100
+ await next();
101
+ }),
102
+ queue: (language) => setI18n(translations, language ?? defaultLanguage, defaultLanguage)
103
+ });
104
+
105
+ const queue = ({
106
+ name,
107
+ queueHandler,
108
+ finalizeLogHandler
109
+ }) => createMiddleware(async ({ env, set, get }, next) => {
110
+ const queueEnv = env[name];
111
+ const language = get("language");
112
+ if (!queueEnv) {
113
+ throw new Error(
114
+ `Queue environment variable ${name} is not defined`
115
+ );
116
+ }
117
+ const logger = get("logger");
118
+ let parentEventId;
119
+ if (finalizeLogHandler) {
120
+ if (!logger) {
121
+ throw new Error("Logger should be initialized before queue middleware");
122
+ }
123
+ parentEventId = logger?.eventId;
124
+ }
125
+ const producer = queueHandler.getProducer(queueEnv, {
126
+ parentEventId,
127
+ language
128
+ });
129
+ set(name, producer);
130
+ await next();
131
+ if (finalizeLogHandler) {
132
+ await producer(
133
+ finalizeLogHandler,
134
+ logger.dump()
135
+ );
136
+ }
137
+ });
138
+
139
+ const setResponseHandlers = (c) => {
140
+ return {
141
+ raw: (data) => {
142
+ const { status, ...rest } = data;
143
+ return c.json(rest, status || 200);
144
+ },
145
+ success: (message, data, status) => {
146
+ const statusCode = status || 200;
147
+ return c.json({ message, data }, statusCode);
148
+ },
149
+ successNoContent: (message, status) => {
150
+ const statusCode = status || 200;
151
+ return c.json({ message }, statusCode);
152
+ },
153
+ error: (message, status) => {
154
+ throw new HTTPException(status, {
155
+ message
156
+ });
157
+ },
158
+ websocket: (socket) => {
159
+ return new Response(null, {
160
+ status: 101,
161
+ webSocket: socket
162
+ });
163
+ }
164
+ };
165
+ };
166
+ const response = createMiddleware(async (c, next) => {
167
+ c.set("res", setResponseHandlers(c));
168
+ if (c.var.eventId) {
169
+ c.header("x-event-id", c.var.eventId);
170
+ }
171
+ await next();
172
+ });
173
+
174
+ const clientInfo = (config) => createMiddleware(async ({ env, req, set, get }, next) => {
175
+ const logger = config?.useLogger ? (get("logger") ?? new Logger({
176
+ details: {
177
+ service: "dummy"
178
+ }
179
+ })).getArea("middeware:clientInfo") : void 0;
180
+ if (!req.raw.cf) {
181
+ throw new Error("Cloudflare data is not available");
182
+ }
183
+ logger?.debug("Retrieving hash secret from environment");
184
+ const hashSecret = env[config?.hashSecretBinding ?? "HASH_SECRET"];
185
+ if (!hashSecret) {
186
+ throw new Error("Hash secret is not available");
187
+ }
188
+ const {
189
+ latitude,
190
+ longitude,
191
+ city,
192
+ country,
193
+ continent,
194
+ colo,
195
+ asn,
196
+ isEUCountry,
197
+ region,
198
+ regionCode,
199
+ postalCode,
200
+ timezone
201
+ } = req.raw.cf;
202
+ logger?.debug("Forming cloudflare client data object");
203
+ const cf = {
204
+ latitude,
205
+ longitude,
206
+ city,
207
+ country,
208
+ continent,
209
+ colo,
210
+ asn,
211
+ isEUCountry: Boolean(isEUCountry),
212
+ region,
213
+ regionCode,
214
+ postalCode,
215
+ timezone
216
+ };
217
+ logger?.debug("Parsing user agent");
218
+ const userAgent = req.raw.headers.get("user-agent") ?? "Unknown";
219
+ const parser = new UAParser(userAgent);
220
+ const userAgentParsed = parser.getResult();
221
+ const { browser, device, engine, os, cpu } = userAgentParsed;
222
+ const ua = {
223
+ browser: {
224
+ name: browser.name ?? "Unknown",
225
+ version: browser.version ?? "Unknown"
226
+ },
227
+ device: {
228
+ model: device.model ?? "Unknown",
229
+ vendor: device.vendor ?? "Unknown",
230
+ type: device.type ?? "desktop"
231
+ },
232
+ engine: {
233
+ name: engine.name ?? "Unknown",
234
+ version: engine.version ?? "Unknown"
235
+ },
236
+ os: {
237
+ name: os.name ?? "Unknown",
238
+ version: os.version ?? "Unknown"
239
+ },
240
+ cpu: cpu.architecture ?? "Unknown"
241
+ };
242
+ logger?.debug("Getting ip address");
243
+ const ip = req.raw.headers.get("CF-Connecting-IP") ?? "127.0.0.1";
244
+ const clientContent = { ...cf, ...ua, ip };
245
+ logger?.debug("Setting client data into context");
246
+ set("client", {
247
+ ...clientContent,
248
+ userAgent,
249
+ securityHash: await hash({
250
+ input: config?.securityHashString?.(clientContent) ?? `${ip}${city}${country}${userAgent}`,
251
+ algorithm: "SHA-512",
252
+ pepper: hashSecret
253
+ })
254
+ });
255
+ logger?.info("Client data variable set");
256
+ await next();
257
+ });
258
+
259
+ var __defProp = Object.defineProperty;
260
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
261
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
262
+ class QueueHandler {
263
+ /**
264
+ * @param config - Configuration object.
265
+ * @param config.schema - The Zod schema used to parse and validate incoming message content.
266
+ * @param config.setContext - A factory function to generate context (e.g., DB connections, logging) for each message.
267
+ */
268
+ constructor(config) {
269
+ this.config = config;
270
+ __publicField(this, "handlers", {});
271
+ }
272
+ /**
273
+ * Registers a specific processing function for a given message type (handlerName).
274
+ * * @template {keyof z.infer<Schema>} HandlerName - A specific key defined in your Zod schema.
275
+ * @param handlerName - The key identifying which handler to use.
276
+ * @param handler - The asynchronous logic to execute when this message type is received.
277
+ * @returns The current instance for fluent chaining.
278
+ */
279
+ addHandler(handlerName, handler) {
280
+ this.handlers[handlerName] = handler;
281
+ return this;
282
+ }
283
+ /**
284
+ * Generates the Cloudflare Worker queue consumer function.
285
+ * * This handles the batch processing loop, parses the message body against the
286
+ * schema, injects context, and manages concurrency via `Promise.allSettled`.
287
+ * * @returns An async function compatible with the Cloudflare `queue` export.
288
+ */
289
+ getConsumer() {
290
+ return async (batch, env) => {
291
+ await Promise.allSettled(
292
+ batch.messages.map(
293
+ async ({ body: { handler, content, ...restMessage }, ...rest }) => {
294
+ const handlerFunction = this.handlers[handler];
295
+ if (!handlerFunction) {
296
+ console.warn(
297
+ `No handler registered for handlerName "${String(handler)}"`
298
+ );
299
+ return;
300
+ }
301
+ const parsedContent = this.config.schema.shape[handler].parse(content);
302
+ const { retry, ack, ...metadata } = rest;
303
+ const context = this.config.setContext(env, restMessage);
304
+ await handlerFunction(parsedContent, {
305
+ context: { ...context, retry, ack },
306
+ metadata: {
307
+ ...restMessage,
308
+ handler,
309
+ ...metadata
310
+ }
311
+ });
312
+ }
313
+ )
314
+ );
315
+ };
316
+ }
317
+ /**
318
+ * Creates a factory function for sending typed messages to a specific queue.
319
+ * * @param queue - The Cloudflare Queue binding (e.g., `env.MY_QUEUE`).
320
+ * @param params - Global parameters to include in every message (e.g., trace IDs).
321
+ * @returns A producer function that accepts a `handler` key and the corresponding typed content.
322
+ */
323
+ getProducer(queue, params) {
324
+ const createId = init({ fingerprint: "queue" });
325
+ return async (handler, content) => {
326
+ const eventId = createId();
327
+ return queue.send(
328
+ { content, handler, eventId, ...params },
329
+ { contentType: "json" }
330
+ );
331
+ };
332
+ }
333
+ }
334
+
335
+ const defaultMessageMap = {
336
+ internalError: "internal-error",
337
+ notFound: "not-found"
338
+ };
339
+
340
+ const onError = (parseError) => async (err, { json, env, get }) => {
341
+ try {
342
+ const status = "status" in err ? err.status : 500;
343
+ return json(
344
+ {
345
+ message: !parseError ? err.message : await parseError(err, env, get) ?? defaultMessageMap.internalError
346
+ },
347
+ status
348
+ );
349
+ } catch (error) {
350
+ console.error("Failed on error handler:", err);
351
+ console.error("Failed to parse error:", error);
352
+ return json({ message: defaultMessageMap.internalError }, 500);
353
+ }
354
+ };
355
+
356
+ const onNotFound = async (c) => {
357
+ return c.json(
358
+ {
359
+ message: defaultMessageMap.notFound
360
+ },
361
+ 404
362
+ );
363
+ };
364
+
365
+ export { QueueHandler, clientInfo, i18n, isBot, jsonValidator, logger, onError, onNotFound, queue, response };
366
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/middleware/logger.ts","../src/middleware/validator.ts","../src/middleware/isBot.ts","../src/middleware/i18n.ts","../src/middleware/queue.ts","../src/middleware/response.ts","../src/middleware/clientInfo.ts","../src/queue/QueueHandler.ts","../src/router/constants.ts","../src/router/onError.ts","../src/router/onNotFound.ts"],"sourcesContent":["import { createMiddleware } from 'hono/factory';\nimport { type Details, Logger } from 'hierarchical-area-logger';\n\nexport type HonoLoggerVariables = {\n logger: Logger;\n eventId: string;\n};\n\n/**\n * Logger middleware\n *\n * @description\n * This middleware sets up a logger.\n *\n * @param details - Details to pass to the logger\n * @param parentEventIdHeader - Header name to use for parent event ID\n *\n * @example\n * ```ts\n * app.use('*', logger(\n * {\n * service: 'logger',\n * },\n * parentEventIdHeader: 'parent-event-id',\n * ));\n * ```\n */\nexport const logger = (details: Details, parentEventIdHeader?: string) =>\n createMiddleware<{\n Variables: HonoLoggerVariables;\n }>(async (c, next) => {\n const logger = new Logger({\n details,\n withParentEventId: !!parentEventIdHeader,\n parentEventId: parentEventIdHeader\n ? (c.req.raw.headers.get(parentEventIdHeader) ?? undefined)\n : undefined,\n defaultArea: new URL(c.req.raw.url).pathname,\n path: new URL(c.req.raw.url).pathname,\n });\n\n c.set('logger', logger);\n c.set('eventId', logger.eventId);\n\n await next();\n });\n","import { HTTPException } from 'hono/http-exception';\nimport { validator } from 'hono/validator';\nimport { z } from 'zod';\n\n/**\n * @description\n * Validator middleware for JSON data.\n *\n * @param schema - Zod schema for validation\n *\n * @example\n * ```ts\n * app.post('/user', jsonValidator(z.object({\n * name: z.string(),\n * age: z.number(),\n * })), (c) => {\n * const { name, age } = await c.req.valid('json');\n * return c.json({ name, age });\n * });\n * ```\n */\nexport const jsonValidator = <T extends z.ZodRawShape>(\n schema: z.ZodObject<T>\n) =>\n validator('json', (value) => {\n const parsed = schema.safeParse(value);\n if (!parsed.success) {\n throw new HTTPException(400, {\n message: z.prettifyError(parsed.error),\n });\n }\n return parsed.data;\n });\n","import { HTTPException } from 'hono/http-exception';\nimport { Logger } from 'hierarchical-area-logger';\nimport type { IncomingRequestCfPropertiesBotManagementBase } from '@cloudflare/workers-types';\nimport { createMiddleware } from 'hono/factory';\nimport { MiddlewareWithLoggingCapability } from './types';\nimport { HonoLoggerVariables } from './logger';\n\nexport type HonoIsBotVariables = {\n isBot: boolean;\n};\n\n/**\n * Middleware to detect and optionally block requests based on Cloudflare's Bot Management score.\n * @param {Object} options - Configuration options for bot detection.\n * @param {number} [options.threshold=49] - The bot score threshold (1-100).\n * Cloudflare scores below this value are treated as bots. A lower score indicates a higher\n * probability that the request is automated.\n * @param {boolean} [options.allowVerifiedBot] - If true, the middleware strictly requires\n * bots to be \"verified\" (e.g., Googlebot, Bingbot).\n * Note: If this is enabled, non-verified bots will be blocked regardless of their score.\n * @returns {MiddlewareHandler} A Hono middleware handler.\n * @throws {HTTPException} Throws a 401 \"Bot detected\" error if the score is below the\n * threshold or if a non-verified bot is detected when `allowVerifiedBot` is true.\n * @example\n * ```ts\n * const app = new Hono<{ Variables: HonoIsBotVariables }>();\n * // Block suspected bots with a score lower than 50\n * app.use('/api/*', isBot({ threshold: 50, allowVerifiedBot: true }));\n * ```\n */\nexport const isBot: MiddlewareWithLoggingCapability<{\n threshold: number;\n allowVerifiedBot?: boolean;\n}> = (\n { threshold, allowVerifiedBot, useLogger } = {\n threshold: 49,\n }\n) =>\n createMiddleware<{\n Variables: HonoIsBotVariables & HonoLoggerVariables;\n }>(async (c, next) => {\n const logger = useLogger\n ? (\n c.get('logger') ??\n new Logger({\n details: {\n service: 'dummy',\n },\n })\n ).getArea('middeware:isBot')\n : undefined;\n\n logger?.debug('Retrieving bot management data from cloudflare data');\n const botManagement = c.req.raw.cf?.botManagement as\n IncomingRequestCfPropertiesBotManagementBase | undefined;\n\n if (!botManagement) {\n throw new Error('botManagement is not available');\n }\n\n const score = botManagement?.score ?? 54;\n const verifiedBot = botManagement?.verifiedBot ?? false;\n\n // Determine if this request should be treated as a bot based on score,\n // allowing verified bots when configured.\n const isBotByScore = score < threshold;\n const isVerifiedAllowed = !!(allowVerifiedBot && verifiedBot);\n const isBot = isBotByScore;\n\n logger?.debug('Setting isBot variable in context', {\n isBotByScore,\n isVerifiedAllowed,\n isBot,\n });\n\n logger?.info('isBot variable set');\n c.set('isBot', isBot);\n\n // Block non-verified bots when score is below threshold, or when non-verified\n // bots are not allowed by configuration.\n if (isBotByScore && !isVerifiedAllowed) {\n throw new HTTPException(401, { message: 'Bot detected' });\n }\n\n await next();\n });\n","import { createMiddleware } from 'hono/factory';\n\nexport type HonoLanguageVariables = {\n language: string;\n};\n\ntype I18nShape = {\n [key: string]: I18nShape | string;\n};\n\nexport type HonoI18nVariables = {\n t: ReturnType<typeof setI18n>;\n};\n\n/**\n * Set i18n\n *\n * @param translations - Translations object\n * @param language - Language\n * @param defaultLanguage - Default language\n */\nconst setI18n =\n <T extends I18nShape>(\n translations: T,\n language: keyof T,\n defaultLanguage: string\n ) =>\n (\n input: string,\n params?: Record<string, string | number>,\n overrideLanguage?: keyof T\n ): string => {\n const result = input.split('.').reduce(\n (acc: unknown, key: string) => {\n if (acc && typeof acc === 'object' && key in acc) {\n return (acc as I18nShape)[key];\n } else {\n if (\n translations[defaultLanguage] &&\n typeof translations[defaultLanguage] === 'object' &&\n key in translations[defaultLanguage]\n ) {\n return (translations[defaultLanguage] as I18nShape)[key];\n } else {\n return input;\n }\n }\n },\n translations[overrideLanguage ?? language]\n );\n\n if (params) {\n return Object.keys(params).reduce(\n (acc, key) => {\n return acc.replace(\n new RegExp(`{{${key}}}`, 'g'),\n params[key].toString()\n );\n },\n typeof result === 'string' ? result : input\n );\n }\n\n return typeof result === 'string' ? result : input;\n };\n\n/**\n * I18n Middleware and Queue Factory.\n * @description\n * Sets up the `t` translation function in the Hono context.\n * Note: Requires a preceding middleware to set the `language` variable.\n * @template T - The shape of the translations object.\n * @param translations - The dictionary of translations.\n * @param defaultLanguage - The fallback language code.\n * @returns An object containing the `middleware` for Hono and a `queue` helper for background tasks.\n * @example\n * ```ts\n * const translations = { en: { hi: \"Hi {{name}}\" }, fr: { hi: \"Salut {{name}}\" } };\n * // 1. Set language first\n * app.use('*', async (c, next) => {\n * c.set('language', 'en');\n * await next();\n * });\n * // 2. Initialize i18n\n * const { middleware } = i18n(translations, 'en');\n * app.use('*', middleware);\n * // 3. Use in routes\n * app.get('/', (c) => c.text(c.var.t('hi', { name: 'User' })));\n * ```\n */\nexport const i18n = <T extends I18nShape>(\n translations: T,\n defaultLanguage: string\n) => ({\n middleware: createMiddleware<{\n Variables: HonoLanguageVariables & HonoI18nVariables;\n }>(async ({ set, var: { language } }, next) => {\n if (!language) {\n throw new Error(\n 'Language variable should be initialized before translations middleware'\n );\n }\n set('t', setI18n<T>(translations, language, defaultLanguage));\n await next();\n }),\n queue: (language?: keyof T) =>\n setI18n(translations, language ?? defaultLanguage, defaultLanguage),\n});\n","import { createMiddleware } from 'hono/factory';\nimport z, { type ZodObject } from 'zod';\nimport type { Queue } from '@cloudflare/workers-types';\nimport { QueueHandler } from '../queue/QueueHandler';\nimport { HonoLoggerVariables } from './logger';\n\n/**\n * Middleware to initialize a Queue producer and attach it to the Hono context.\n * @description\n * This middleware manages Cloudflare Queue interactions. If `finalizeLogHandler` is provided,\n * it will automatically capture the current logger state and send it to the queue after\n * the request is processed (post-`next()`).\n * @param options.name - The name of the Queue binding defined in your `wrangler.toml`.\n * @param options.queueHandler - An instance of your custom QueueHandler.\n * @param [options.finalizeLogHandler] - Optional: The specific message type/key to use when finalizing the log.\n * @example\n * ```ts\n * // OPTIONAL\n * app.use('*', logger(\n * {\n * service: 'logger',\n * },\n * parentEventIdHeader: 'parent-event-id',\n * ));\n *\n * app.use('*', queue({\n * name: 'queue',\n * queueHandler: new QueueHandler(),\n * finalizeLogHandler: 'log'\n * }));\n * ```\n */\nexport const queue = <\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Schema extends ZodObject<any>,\n Environment,\n Context,\n Key extends keyof z.infer<Schema>,\n>({\n name,\n queueHandler,\n finalizeLogHandler,\n}: {\n name: string;\n queueHandler: QueueHandler<Schema, Environment, Context>;\n finalizeLogHandler?: Key;\n}) =>\n createMiddleware<{\n Bindings: Record<string, Queue>;\n Variables: HonoLoggerVariables &\n Record<\n string,\n ReturnType<QueueHandler<Schema, Environment, Context>['getProducer']>\n >;\n }>(async ({ env, set, get }, next) => {\n const queueEnv = env[name] as Queue | undefined;\n\n const language = get('language') as unknown as string | undefined;\n\n if (!queueEnv) {\n throw new Error(\n `Queue environment variable ${name as string} is not defined`\n );\n }\n\n const logger = get('logger');\n\n let parentEventId: string | undefined;\n\n if (finalizeLogHandler) {\n if (!logger) {\n throw new Error('Logger should be initialized before queue middleware');\n }\n parentEventId = logger?.eventId;\n }\n\n const producer = queueHandler.getProducer(queueEnv, {\n parentEventId,\n language,\n });\n set(name, producer);\n\n await next();\n\n if (finalizeLogHandler) {\n await producer(\n finalizeLogHandler,\n logger!.dump() as z.infer<Schema>[Key]\n );\n }\n });\n","import type { Context } from 'hono';\nimport { createMiddleware } from 'hono/factory';\nimport type {\n ClientErrorStatusCode,\n ContentfulStatusCode,\n SuccessStatusCode,\n} from 'hono/utils/http-status';\nimport { HTTPException } from 'hono/http-exception';\nimport type { HonoLoggerVariables } from './logger';\n\nexport type HonoResponseVariables = {\n res: ReturnType<typeof setResponseHandlers>;\n};\n\nconst setResponseHandlers = (c: Context) => {\n return {\n raw: <T extends { status?: ContentfulStatusCode }>(data: T) => {\n const { status, ...rest } = data;\n return c.json(rest, status || (200 as ContentfulStatusCode));\n },\n success: <T extends object>(\n message: string,\n data: T,\n status?: SuccessStatusCode\n ) => {\n const statusCode: ContentfulStatusCode =\n (status as ContentfulStatusCode) || 200;\n\n return c.json({ message, data }, statusCode);\n },\n successNoContent: (message: string, status?: SuccessStatusCode) => {\n const statusCode: ContentfulStatusCode =\n (status as ContentfulStatusCode) || 200;\n return c.json({ message }, statusCode);\n },\n error: (message: string, status: ClientErrorStatusCode) => {\n throw new HTTPException(status, {\n message,\n });\n },\n websocket: (socket: WebSocket) => {\n return new Response(null, {\n status: 101,\n webSocket: socket,\n });\n },\n };\n};\n\n/**\n * Response Middleware\n * @description\n * Injects a `res` object into the Hono context (`c.var.res`).\n * This ensures all outgoing responses follow a consistent schema and include\n * tracing metadata (like `eventId`) automatically.\n * @example\n * ```ts\n * app.use('*', response());\n * ```\n */\nexport const response = createMiddleware<{\n Variables: HonoResponseVariables & HonoLoggerVariables;\n}>(async (c, next) => {\n c.set('res', setResponseHandlers(c));\n if (c.var.eventId) {\n c.header('x-event-id', c.var.eventId);\n }\n await next();\n});\n","import { createMiddleware } from 'hono/factory';\nimport { UAParser } from 'ua-parser-js';\nimport type {\n Iso3166Alpha2Code,\n ContinentCode,\n} from '@cloudflare/workers-types';\nimport { SHA } from '../crypto';\nimport { MiddlewareWithLoggingCapability } from './types';\nimport { Logger } from 'hierarchical-area-logger';\nimport { HonoLoggerVariables } from './logger';\n\ntype CFData = {\n isEUCountry: boolean;\n latitude: string;\n longitude: string;\n city: string;\n country: Iso3166Alpha2Code | 'T1';\n continent: ContinentCode;\n region?: string;\n regionCode?: string;\n postalCode: string;\n timezone: string;\n colo: string;\n asn?: number;\n};\n\ntype UserAgentData = {\n browser: {\n name: string;\n version: string;\n };\n device: {\n model: string;\n vendor: string;\n type: UAParser.IDevice['type'] | 'desktop';\n };\n engine: {\n name: string;\n version: string;\n };\n os: {\n name: string;\n version: string;\n };\n cpu: string;\n};\n\nexport type HonoClientInfoVariables = {\n client: CFData & {\n ip: string;\n userAgent: string;\n securityHash: string;\n } & UserAgentData;\n};\n\n/**\n * Hono middleware that extracts and injects comprehensive client information\n * into the request context, including geolocation data from Cloudflare and\n * parsed User-Agent details.\n * @param {Object} [config] - Optional configuration for the middleware.\n * @param {Function} [config.securityHashString] - A custom function to generate the seed string\n * used for the security hash. Receives Cloudflare and User-Agent data as input.\n * Defaults to `${city}${country}${continent}`.\n * @param {string} [config.hashSecretBinding] - The name of the environment variable\n * containing the hash secret. Defaults to 'HASH_SECRET'.\n * @returns {MiddlewareHandler} A Hono middleware handler.\n * @throws {Error} Throws an error if Cloudflare (`req.raw.cf`) data is missing.\n * @example\n * ```ts\n * const app = new Hono<{ Variables: HonoClientInfoVariables }>();\n *\n * app.use('*', clientInfo({\n * useLogger: true // for debugging purposes\n * }));\n *\n * app.get('/me', (c) => {\n * const client = c.get('client');\n * return c.json({\n * location: `${client.city}, ${client.country}`,\n * device: client.device.type\n * });\n * });\n * ```\n */\nexport const clientInfo: MiddlewareWithLoggingCapability<{\n hashSecretBinding?: string;\n securityHashString?: (\n content: CFData & UserAgentData & { ip: string }\n ) => string;\n}> = (config) =>\n createMiddleware<{\n Bindings: Record<string, string>;\n Variables: HonoClientInfoVariables & HonoLoggerVariables;\n }>(async ({ env, req, set, get }, next) => {\n const logger = config?.useLogger\n ? (\n get('logger') ??\n new Logger({\n details: {\n service: 'dummy',\n },\n })\n ).getArea('middeware:clientInfo')\n : undefined;\n\n if (!req.raw.cf) {\n throw new Error('Cloudflare data is not available');\n }\n\n logger?.debug('Retrieving hash secret from environment');\n const hashSecret = env[config?.hashSecretBinding ?? 'HASH_SECRET'] as\n string | undefined;\n\n if (!hashSecret) {\n throw new Error('Hash secret is not available');\n }\n\n const {\n latitude,\n longitude,\n city,\n country,\n continent,\n colo,\n asn,\n isEUCountry,\n region,\n regionCode,\n postalCode,\n timezone,\n } = req.raw.cf as CFData;\n\n logger?.debug('Forming cloudflare client data object');\n const cf = {\n latitude,\n longitude,\n city,\n country,\n continent,\n colo,\n asn,\n isEUCountry: Boolean(isEUCountry),\n region,\n regionCode,\n postalCode,\n timezone,\n };\n\n logger?.debug('Parsing user agent');\n const userAgent = req.raw.headers.get('user-agent') ?? 'Unknown';\n const parser = new UAParser(userAgent);\n const userAgentParsed = parser.getResult();\n\n const { browser, device, engine, os, cpu } = userAgentParsed;\n\n const ua = {\n browser: {\n name: browser.name ?? 'Unknown',\n version: browser.version ?? 'Unknown',\n },\n device: {\n model: device.model ?? 'Unknown',\n vendor: device.vendor ?? 'Unknown',\n type: device.type ?? 'desktop',\n },\n engine: {\n name: engine.name ?? 'Unknown',\n version: engine.version ?? 'Unknown',\n },\n os: {\n name: os.name ?? 'Unknown',\n version: os.version ?? 'Unknown',\n },\n cpu: cpu.architecture ?? 'Unknown',\n };\n\n logger?.debug('Getting ip address');\n const ip =\n (req.raw.headers.get('CF-Connecting-IP') as string) ?? '127.0.0.1';\n\n const clientContent = { ...cf, ...ua, ip };\n\n logger?.debug('Setting client data into context');\n set('client', {\n ...clientContent,\n userAgent,\n securityHash: await SHA.hash({\n input:\n config?.securityHashString?.(clientContent) ??\n `${ip}${city}${country}${userAgent}`,\n algorithm: 'SHA-512',\n pepper: hashSecret,\n }),\n });\n logger?.info('Client data variable set');\n await next();\n });\n","import { init } from '@paralleldrive/cuid2';\nimport type { z, ZodObject } from 'zod';\nimport type { Queue, MessageBatch } from '@cloudflare/workers-types';\nimport type {\n GenericQueueData,\n Variables,\n Handler,\n QueueSendParams,\n MessageHandlers,\n ContextFn,\n} from './types';\n\n/**\n * A type-safe wrapper for Cloudflare Worker Queues using Zod for validation.\n * * This class orchestrates the relationship between incoming queue messages and\n * specific logic handlers, ensuring that data is validated at the edge before\n * reaching your business logic.\n *\n * @template Schema - The Zod schema defining the message shapes.\n * @template Environment - The Cloudflare Worker environment bindings (Env).\n * @template Context - The application context derived from the environment and message.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class QueueHandler<Schema extends ZodObject<any>, Environment, Context> {\n private readonly handlers: Partial<\n MessageHandlers<z.infer<Schema>, Context>\n > = {};\n\n /**\n * @param config - Configuration object.\n * @param config.schema - The Zod schema used to parse and validate incoming message content.\n * @param config.setContext - A factory function to generate context (e.g., DB connections, logging) for each message.\n */\n constructor(\n private readonly config: {\n schema: Schema;\n setContext: ContextFn<Environment, Context>;\n }\n ) {}\n\n /**\n * Registers a specific processing function for a given message type (handlerName).\n * * @template {keyof z.infer<Schema>} HandlerName - A specific key defined in your Zod schema.\n * @param handlerName - The key identifying which handler to use.\n * @param handler - The asynchronous logic to execute when this message type is received.\n * @returns The current instance for fluent chaining.\n */\n public addHandler<HandlerName extends keyof z.infer<Schema>>(\n handlerName: HandlerName,\n handler: Handler<z.infer<Schema>[HandlerName], Variables<Context>>\n ): this {\n this.handlers[handlerName] = handler;\n return this;\n }\n\n /**\n * Generates the Cloudflare Worker queue consumer function.\n * * This handles the batch processing loop, parses the message body against the\n * schema, injects context, and manages concurrency via `Promise.allSettled`.\n * * @returns An async function compatible with the Cloudflare `queue` export.\n */\n public getConsumer() {\n return async (\n batch: MessageBatch<GenericQueueData<z.infer<Schema>>>,\n env: Environment\n ): Promise<void> => {\n await Promise.allSettled(\n batch.messages.map(\n async ({ body: { handler, content, ...restMessage }, ...rest }) => {\n const handlerFunction =\n this.handlers[handler as keyof typeof this.handlers];\n if (!handlerFunction) {\n console.warn(\n `No handler registered for handlerName \"${String(handler)}\"`\n );\n return;\n }\n const parsedContent = this.config.schema.shape[\n handler as keyof typeof this.config.schema.shape\n ].parse(content) as z.infer<Schema>[typeof handler];\n const { retry, ack, ...metadata } = rest;\n const context = this.config.setContext(env, restMessage);\n await handlerFunction(parsedContent, {\n context: { ...context, retry, ack },\n metadata: {\n ...restMessage,\n handler: handler as string,\n ...metadata,\n },\n });\n }\n )\n );\n };\n }\n\n /**\n * Creates a factory function for sending typed messages to a specific queue.\n * * @param queue - The Cloudflare Queue binding (e.g., `env.MY_QUEUE`).\n * @param params - Global parameters to include in every message (e.g., trace IDs).\n * @returns A producer function that accepts a `handler` key and the corresponding typed content.\n */\n public getProducer(queue: Queue<unknown>, params: QueueSendParams) {\n const createId = init({ fingerprint: 'queue' });\n return async <HandlerName extends keyof z.infer<Schema>>(\n handler: HandlerName,\n content: z.infer<Schema>[HandlerName]\n ) => {\n const eventId = createId();\n return queue.send(\n { content, handler, eventId, ...params } as GenericQueueData<\n z.infer<Schema>\n >,\n { contentType: 'json' }\n );\n };\n }\n}\n","export const defaultMessageMap = {\n internalError: 'internal-error',\n notFound: 'not-found',\n};\n","import { HTTPException } from 'hono/http-exception';\nimport type { ErrorHandler, Env } from 'hono';\nimport { defaultMessageMap } from './constants';\n\nexport const onError =\n <Environment extends Env>(\n parseError?: (\n err: Error | HTTPException,\n env: Environment['Bindings'],\n get: <K extends keyof Environment['Variables']>(\n key: K\n ) => Environment['Variables'][K]\n ) => Promise<string>\n ): ErrorHandler<Environment> =>\n async (err: Error | HTTPException, { json, env, get }) => {\n try {\n const status =\n 'status' in err ? (err.status as HTTPException['status']) : 500;\n\n return json(\n {\n message: !parseError\n ? err.message\n : ((await parseError(err, env, get)) ??\n defaultMessageMap.internalError),\n },\n status\n );\n } catch (error) {\n console.error('Failed on error handler:', err);\n console.error('Failed to parse error:', error);\n return json({ message: defaultMessageMap.internalError }, 500);\n }\n };\n","import type { NotFoundHandler } from 'hono';\nimport { defaultMessageMap } from './constants';\n\nexport const onNotFound: NotFoundHandler = async (c) => {\n return c.json(\n {\n message: defaultMessageMap.notFound,\n },\n 404\n );\n};\n"],"names":["logger","isBot","SHA.hash"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ function generateSalt(length = 16) {
2
+ const buffer = new Uint8Array(length);
3
+ crypto.getRandomValues(buffer);
4
+ return btoa(String.fromCharCode(...buffer));
5
+ }
6
+ async function hash({
7
+ input,
8
+ algorithm = "SHA-256",
9
+ pepper,
10
+ salt
11
+ }) {
12
+ let textToHash = input;
13
+ if (pepper) {
14
+ textToHash = `${pepper}${input}`;
15
+ }
16
+ if (salt) {
17
+ textToHash = `${textToHash}${salt}`;
18
+ }
19
+ const buffer = new TextEncoder().encode(textToHash);
20
+ const hashBuffer = await crypto.subtle.digest(algorithm, buffer);
21
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
22
+ const hashedString = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
23
+ return hashedString;
24
+ }
25
+
26
+ const sha = {
27
+ __proto__: null,
28
+ generateSalt: generateSalt,
29
+ hash: hash
30
+ };
31
+
32
+ export { hash as h, sha as s };
33
+ //# sourceMappingURL=hono-utils.BOXr1V_a.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono-utils.BOXr1V_a.mjs","sources":["../../src/crypto/sha.ts"],"sourcesContent":["/**\n * Generates a cryptographically strong random salt.\n */\nexport function generateSalt(length: number = 16): string {\n const buffer = new Uint8Array(length);\n crypto.getRandomValues(buffer);\n return btoa(String.fromCharCode(...buffer));\n}\n\n/**\n * Calculates the SHA hash of the given input string.\n * @param algorithm - The algorithm to be used for hashing. Defaults to 256.\n * @param pepper - An optional string to be prepended to the input before hashing.\n * @param salt - An optional string to be appended to the input before hashing.\n * @returns A Promise that resolves to the hashed string.\n */\nexport async function hash({\n input,\n algorithm = 'SHA-256',\n pepper,\n salt,\n}: {\n input: string;\n algorithm: 'SHA-256' | 'SHA-384' | 'SHA-512';\n pepper?: string;\n salt?: string;\n}): Promise<string> {\n let textToHash = input;\n if (pepper) {\n textToHash = `${pepper}${input}`;\n }\n if (salt) {\n textToHash = `${textToHash}${salt}`;\n }\n const buffer = new TextEncoder().encode(textToHash);\n const hashBuffer = await crypto.subtle.digest(algorithm, buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashedString = hashArray\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n\n return hashedString;\n}\n"],"names":[],"mappings":"AAGO,SAAS,YAAA,CAAa,SAAiB,EAAA,EAAY;AACxD,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,MAAM,CAAA;AACpC,EAAA,MAAA,CAAO,gBAAgB,MAAM,CAAA;AAC7B,EAAA,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAG,MAAM,CAAC,CAAA;AAC5C;AASA,eAAsB,IAAA,CAAK;AAAA,EACzB,KAAA;AAAA,EACA,SAAA,GAAY,SAAA;AAAA,EACZ,MAAA;AAAA,EACA;AACF,CAAA,EAKoB;AAClB,EAAA,IAAI,UAAA,GAAa,KAAA;AACjB,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,UAAA,GAAa,CAAA,EAAG,MAAM,CAAA,EAAG,KAAK,CAAA,CAAA;AAAA,EAChC;AACA,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,UAAA,GAAa,CAAA,EAAG,UAAU,CAAA,EAAG,IAAI,CAAA,CAAA;AAAA,EACnC;AACA,EAAA,MAAM,MAAA,GAAS,IAAI,WAAA,EAAY,CAAE,OAAO,UAAU,CAAA;AAClD,EAAA,MAAM,aAAa,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,MAAM,CAAA;AAC/D,EAAA,MAAM,YAAY,KAAA,CAAM,IAAA,CAAK,IAAI,UAAA,CAAW,UAAU,CAAC,CAAA;AACvD,EAAA,MAAM,YAAA,GAAe,SAAA,CAClB,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAChD,KAAK,EAAE,CAAA;AAEV,EAAA,OAAO,YAAA;AACT;;;;;;;;;;"}
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ function generateSalt(length = 16) {
4
+ const buffer = new Uint8Array(length);
5
+ crypto.getRandomValues(buffer);
6
+ return btoa(String.fromCharCode(...buffer));
7
+ }
8
+ async function hash({
9
+ input,
10
+ algorithm = "SHA-256",
11
+ pepper,
12
+ salt
13
+ }) {
14
+ let textToHash = input;
15
+ if (pepper) {
16
+ textToHash = `${pepper}${input}`;
17
+ }
18
+ if (salt) {
19
+ textToHash = `${textToHash}${salt}`;
20
+ }
21
+ const buffer = new TextEncoder().encode(textToHash);
22
+ const hashBuffer = await crypto.subtle.digest(algorithm, buffer);
23
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
24
+ const hashedString = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
25
+ return hashedString;
26
+ }
27
+
28
+ const sha = {
29
+ __proto__: null,
30
+ generateSalt: generateSalt,
31
+ hash: hash
32
+ };
33
+
34
+ exports.hash = hash;
35
+ exports.sha = sha;
36
+ //# sourceMappingURL=hono-utils.DX3fyaCt.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono-utils.DX3fyaCt.cjs","sources":["../../src/crypto/sha.ts"],"sourcesContent":["/**\n * Generates a cryptographically strong random salt.\n */\nexport function generateSalt(length: number = 16): string {\n const buffer = new Uint8Array(length);\n crypto.getRandomValues(buffer);\n return btoa(String.fromCharCode(...buffer));\n}\n\n/**\n * Calculates the SHA hash of the given input string.\n * @param algorithm - The algorithm to be used for hashing. Defaults to 256.\n * @param pepper - An optional string to be prepended to the input before hashing.\n * @param salt - An optional string to be appended to the input before hashing.\n * @returns A Promise that resolves to the hashed string.\n */\nexport async function hash({\n input,\n algorithm = 'SHA-256',\n pepper,\n salt,\n}: {\n input: string;\n algorithm: 'SHA-256' | 'SHA-384' | 'SHA-512';\n pepper?: string;\n salt?: string;\n}): Promise<string> {\n let textToHash = input;\n if (pepper) {\n textToHash = `${pepper}${input}`;\n }\n if (salt) {\n textToHash = `${textToHash}${salt}`;\n }\n const buffer = new TextEncoder().encode(textToHash);\n const hashBuffer = await crypto.subtle.digest(algorithm, buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashedString = hashArray\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n\n return hashedString;\n}\n"],"names":[],"mappings":";;AAGO,SAAS,YAAA,CAAa,SAAiB,EAAA,EAAY;AACxD,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,MAAM,CAAA;AACpC,EAAA,MAAA,CAAO,gBAAgB,MAAM,CAAA;AAC7B,EAAA,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAG,MAAM,CAAC,CAAA;AAC5C;AASA,eAAsB,IAAA,CAAK;AAAA,EACzB,KAAA;AAAA,EACA,SAAA,GAAY,SAAA;AAAA,EACZ,MAAA;AAAA,EACA;AACF,CAAA,EAKoB;AAClB,EAAA,IAAI,UAAA,GAAa,KAAA;AACjB,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,UAAA,GAAa,CAAA,EAAG,MAAM,CAAA,EAAG,KAAK,CAAA,CAAA;AAAA,EAChC;AACA,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,UAAA,GAAa,CAAA,EAAG,UAAU,CAAA,EAAG,IAAI,CAAA,CAAA;AAAA,EACnC;AACA,EAAA,MAAM,MAAA,GAAS,IAAI,WAAA,EAAY,CAAE,OAAO,UAAU,CAAA;AAClD,EAAA,MAAM,aAAa,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,MAAM,CAAA;AAC/D,EAAA,MAAM,YAAY,KAAA,CAAM,IAAA,CAAK,IAAI,UAAA,CAAW,UAAU,CAAC,CAAA;AACvD,EAAA,MAAM,YAAA,GAAe,SAAA,CAClB,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAChD,KAAK,EAAE,CAAA;AAEV,EAAA,OAAO,YAAA;AACT;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,7 +1,22 @@
1
1
  {
2
2
  "name": "hono-utils",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
+ "scripts": {
6
+ "prepare": "husky",
7
+ "build": "unbuild",
8
+ "dev": "unbuild --stub",
9
+ "test": "vitest",
10
+ "test:ui": "vitest --ui",
11
+ "coverage": "vitest --coverage",
12
+ "lint": "eslint .",
13
+ "lint:fix": "eslint . --fix",
14
+ "lint:check": "eslint . --max-warnings=0",
15
+ "format": "prettier --write .",
16
+ "format:check": "prettier --check .",
17
+ "prepack": "unbuild",
18
+ "prepublishOnly": "npm run format && npm run lint && npm run test && npm run build"
19
+ },
5
20
  "pre-commit": [
6
21
  "lint"
7
22
  ],
@@ -19,29 +34,37 @@
19
34
  "node": ">=18.0.0"
20
35
  },
21
36
  "description": "Hono Utils",
22
- "devDependencies": {
23
- "@cloudflare/workers-types": "^4.20260124.0",
24
- "@eslint/js": "^9.0.0",
25
- "@types/node": "^25.0.10",
26
- "@typescript-eslint/eslint-plugin": "^8.0.0",
27
- "@typescript-eslint/parser": "^8.0.0",
28
- "@vitest/coverage-v8": "^4.0.18",
29
- "eslint": "^9.0.0",
30
- "husky": "^9.1.7",
31
- "prettier": "^3.8.1",
32
- "tsup": "^8.5.1",
33
- "typescript": "^5.0.0",
34
- "vitest": "^4.0.18",
35
- "zod": "4.3.6"
36
- },
37
37
  "dependencies": {
38
38
  "@paralleldrive/cuid2": "^3.3.0",
39
- "hierarchical-area-logger": "^0.2.7",
40
- "hono": "^4.10.3",
41
- "ua-parser-js": "^2.0.8"
39
+ "hierarchical-area-logger": "^0.3.0",
40
+ "hono": "^4.12.30",
41
+ "ua-parser-js": "^2.0.10",
42
+ "zod": "4.4.3"
42
43
  },
43
- "main": "dist/index.js",
44
+ "main": "dist/index.cjs",
45
+ "module": "dist/index.mjs",
44
46
  "types": "dist/index.d.ts",
47
+ "exports": {
48
+ ".": {
49
+ "types": "./dist/index.d.ts",
50
+ "import": "./dist/index.mjs",
51
+ "require": "./dist/index.cjs",
52
+ "default": "./dist/index.mjs"
53
+ },
54
+ "./crypto": {
55
+ "types": "./dist/crypto/index.d.ts",
56
+ "import": "./dist/crypto/index.mjs",
57
+ "require": "./dist/crypto/index.cjs",
58
+ "default": "./dist/crypto/index.mjs"
59
+ },
60
+ "./client": {
61
+ "types": "./dist/client/createTypedClient.d.ts",
62
+ "import": "./dist/client/createTypedClient.mjs",
63
+ "require": "./dist/client/createTypedClient.cjs",
64
+ "default": "./dist/client/createTypedClient.mjs"
65
+ },
66
+ "./package.json": "./package.json"
67
+ },
45
68
  "files": [
46
69
  "dist"
47
70
  ],
@@ -51,16 +74,18 @@
51
74
  "typescript",
52
75
  "nodejs"
53
76
  ],
54
- "scripts": {
55
- "build": "tsup",
56
- "dev": "tsup --watch",
57
- "test": "vitest",
58
- "test:ui": "vitest --ui",
59
- "coverage": "vitest --coverage",
60
- "lint": "eslint .",
61
- "lint:fix": "eslint . --fix",
62
- "lint:check": "eslint . --max-warnings=0",
63
- "format": "prettier --write .",
64
- "format:check": "prettier --check ."
77
+ "devDependencies": {
78
+ "@cloudflare/workers-types": "^5.20260713.1",
79
+ "@eslint/js": "^10.0.1",
80
+ "@types/node": "^26.1.1",
81
+ "@typescript-eslint/eslint-plugin": "^8.63.0",
82
+ "@typescript-eslint/parser": "^8.63.0",
83
+ "@vitest/coverage-v8": "^4.1.10",
84
+ "eslint": "^10.7.0",
85
+ "husky": "^9.1.7",
86
+ "prettier": "^3.9.5",
87
+ "unbuild": "^3.6.1",
88
+ "typescript": "^5.9.3",
89
+ "vitest": "^4.1.10"
65
90
  }
66
- }
91
+ }