hono-utils 0.3.0 → 0.3.2
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.cjs +98 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +106 -2
- package/dist/index.d.ts +106 -2
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ import { Logger, Details } from 'hierarchical-area-logger';
|
|
|
4
4
|
import * as hono_utils_http_status from 'hono/utils/http-status';
|
|
5
5
|
import { ContentfulStatusCode, SuccessStatusCode, ClientErrorStatusCode, StatusCode } from 'hono/utils/http-status';
|
|
6
6
|
import z$1, { z, ZodObject } from 'zod';
|
|
7
|
-
import { Message, MessageBatch, Queue } from '@cloudflare/workers-types';
|
|
7
|
+
import { Message, MessageBatch, Queue, Iso3166Alpha2Code, ContinentCode } from '@cloudflare/workers-types';
|
|
8
8
|
import * as hono_utils_types from 'hono/utils/types';
|
|
9
9
|
import { hc, ClientResponse } from 'hono/client';
|
|
10
10
|
|
|
@@ -304,6 +304,110 @@ declare const response: hono.MiddlewareHandler<{
|
|
|
304
304
|
Variables: HonoResponseVariables & HonoLoggerVariables;
|
|
305
305
|
}, string, {}, Response>;
|
|
306
306
|
|
|
307
|
+
type CFData = {
|
|
308
|
+
isEUCountry: boolean;
|
|
309
|
+
latitude: string;
|
|
310
|
+
longitude: string;
|
|
311
|
+
city: string;
|
|
312
|
+
country: Iso3166Alpha2Code | 'T1';
|
|
313
|
+
continent: ContinentCode;
|
|
314
|
+
region?: string;
|
|
315
|
+
regionCode?: string;
|
|
316
|
+
postalCode: string;
|
|
317
|
+
timezone: string;
|
|
318
|
+
colo: string;
|
|
319
|
+
asn?: number;
|
|
320
|
+
};
|
|
321
|
+
type UserAgentData = {
|
|
322
|
+
browser: {
|
|
323
|
+
name: string;
|
|
324
|
+
version: string;
|
|
325
|
+
};
|
|
326
|
+
device: {
|
|
327
|
+
model: string;
|
|
328
|
+
vendor: string;
|
|
329
|
+
type: UAParser.IDevice['type'] | 'desktop';
|
|
330
|
+
};
|
|
331
|
+
engine: {
|
|
332
|
+
name: string;
|
|
333
|
+
version: string;
|
|
334
|
+
};
|
|
335
|
+
os: {
|
|
336
|
+
name: string;
|
|
337
|
+
version: string;
|
|
338
|
+
};
|
|
339
|
+
cpu: string;
|
|
340
|
+
};
|
|
341
|
+
type HonoClientInfoVariables = {
|
|
342
|
+
client: CFData & {
|
|
343
|
+
ip: string;
|
|
344
|
+
userAgent: string;
|
|
345
|
+
securityHash: string;
|
|
346
|
+
} & UserAgentData;
|
|
347
|
+
};
|
|
348
|
+
/**
|
|
349
|
+
* Hono middleware that extracts and injects comprehensive client information
|
|
350
|
+
* into the request context, including geolocation data from Cloudflare and
|
|
351
|
+
* parsed User-Agent details.
|
|
352
|
+
* @param {Object} [config] - Optional configuration for the middleware.
|
|
353
|
+
* @param {Function} [config.securityHashString] - A custom function to generate the seed string
|
|
354
|
+
* used for the security hash. Receives Cloudflare and User-Agent data as input.
|
|
355
|
+
* Defaults to `${city}${country}${continent}`.
|
|
356
|
+
* @param {string} [config.hashSecretBinding] - The name of the environment variable
|
|
357
|
+
* containing the hash secret. Defaults to 'HASH_SECRET'.
|
|
358
|
+
* @returns {MiddlewareHandler} A Hono middleware handler.
|
|
359
|
+
* @throws {Error} Throws an error if Cloudflare (`req.raw.cf`) data is missing.
|
|
360
|
+
* @example
|
|
361
|
+
* ```ts
|
|
362
|
+
* const app = new Hono<{ Variables: HonoClientInfoVariables }>();
|
|
363
|
+
*
|
|
364
|
+
* app.use('*', clientInfo());
|
|
365
|
+
*
|
|
366
|
+
* app.get('/me', (c) => {
|
|
367
|
+
* const client = c.get('client');
|
|
368
|
+
* return c.json({
|
|
369
|
+
* location: `${client.city}, ${client.country}`,
|
|
370
|
+
* device: client.device.type
|
|
371
|
+
* });
|
|
372
|
+
* });
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
declare const clientInfo: (config?: {
|
|
376
|
+
hashSecretBinding?: string;
|
|
377
|
+
securityHashString?: (content: CFData & UserAgentData & {
|
|
378
|
+
ip: string;
|
|
379
|
+
}) => string;
|
|
380
|
+
}) => hono.MiddlewareHandler<{
|
|
381
|
+
Bindings: Record<string, string>;
|
|
382
|
+
Variables: HonoClientInfoVariables;
|
|
383
|
+
}, string, {}, Response>;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* A Hono middleware factory that hydrates a context variable based on environment bindings or other variables.
|
|
387
|
+
* @template {Record<string, unknown>} Bindings - The environment bindings (e.g., Cloudflare Env).
|
|
388
|
+
* @template {Record<string, unknown>} Variables - The Hono context variables.
|
|
389
|
+
* @template HidratedResult - The resulting type of the hydrated variable.
|
|
390
|
+
* @param {Object} options - The configuration options for hydration.
|
|
391
|
+
* @param {keyof Variables} options.variableName - The name of the variable in the context to be set.
|
|
392
|
+
* @param {(c: Bindings & { get: <T>(key: keyof Variables) => T }) => HidratedResult} options.hydrate -
|
|
393
|
+
* A function that takes the environment and a getter, returning the hydrated value.
|
|
394
|
+
* @returns {import("hono").MiddlewareHandler} A Hono middleware that performs the hydration and calls next().
|
|
395
|
+
* @example
|
|
396
|
+
* const middleware = hydrateVariable({
|
|
397
|
+
* variableName: 'userProfile',
|
|
398
|
+
* hydrate: (c) => new UserProfile(c.USER_ID)
|
|
399
|
+
* });
|
|
400
|
+
*/
|
|
401
|
+
declare const hydrateVariable: <Bindings extends Record<string, unknown>, Variables extends Record<string, unknown>, HidratedResult>({ variableName, hydrate, }: {
|
|
402
|
+
variableName: keyof Variables;
|
|
403
|
+
hydrate: (c: Bindings & {
|
|
404
|
+
get: <T>(key: keyof Variables) => T;
|
|
405
|
+
}) => HidratedResult;
|
|
406
|
+
}) => hono.MiddlewareHandler<{
|
|
407
|
+
Bindings: Bindings;
|
|
408
|
+
Variables: Record<string, HidratedResult>;
|
|
409
|
+
}, string, {}, Response>;
|
|
410
|
+
|
|
307
411
|
/**
|
|
308
412
|
* Derives a secure hex-encoded hash from an input string using PBKDF2-HMAC-SHA256.
|
|
309
413
|
* * @example
|
|
@@ -375,4 +479,4 @@ interface CreateTypedClientOptions {
|
|
|
375
479
|
}
|
|
376
480
|
declare const createTypedClient: <TApp extends Hono<any, any, any>>(options: CreateTypedClientOptions) => <TSuccessData>(fn: (c: ReturnType<typeof hc<TApp>>) => Promise<ClientResponse<TSuccessData>>) => Promise<TSuccessData>;
|
|
377
481
|
|
|
378
|
-
export { type ContextFn, type CreateTypedClientOptions, type HonoI18nVariables, type HonoIsBotVariables, type HonoLanguageVariables, type HonoLoggerVariables, type HonoResponseVariables, type MessageHandlers, pbkdf2 as PBKDF2, QueueHandler, sha as SHA, type WrappableMiddleware, createTypedClient, i18n, isBot, jsonValidator, logger, onError, onNotFound, queue, response, withLogger };
|
|
482
|
+
export { type ContextFn, type CreateTypedClientOptions, type HonoClientInfoVariables, type HonoI18nVariables, type HonoIsBotVariables, type HonoLanguageVariables, type HonoLoggerVariables, type HonoResponseVariables, type MessageHandlers, pbkdf2 as PBKDF2, QueueHandler, sha as SHA, type WrappableMiddleware, clientInfo, createTypedClient, hydrateVariable, i18n, isBot, jsonValidator, logger, onError, onNotFound, queue, response, withLogger };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Logger, Details } from 'hierarchical-area-logger';
|
|
|
4
4
|
import * as hono_utils_http_status from 'hono/utils/http-status';
|
|
5
5
|
import { ContentfulStatusCode, SuccessStatusCode, ClientErrorStatusCode, StatusCode } from 'hono/utils/http-status';
|
|
6
6
|
import z$1, { z, ZodObject } from 'zod';
|
|
7
|
-
import { Message, MessageBatch, Queue } from '@cloudflare/workers-types';
|
|
7
|
+
import { Message, MessageBatch, Queue, Iso3166Alpha2Code, ContinentCode } from '@cloudflare/workers-types';
|
|
8
8
|
import * as hono_utils_types from 'hono/utils/types';
|
|
9
9
|
import { hc, ClientResponse } from 'hono/client';
|
|
10
10
|
|
|
@@ -304,6 +304,110 @@ declare const response: hono.MiddlewareHandler<{
|
|
|
304
304
|
Variables: HonoResponseVariables & HonoLoggerVariables;
|
|
305
305
|
}, string, {}, Response>;
|
|
306
306
|
|
|
307
|
+
type CFData = {
|
|
308
|
+
isEUCountry: boolean;
|
|
309
|
+
latitude: string;
|
|
310
|
+
longitude: string;
|
|
311
|
+
city: string;
|
|
312
|
+
country: Iso3166Alpha2Code | 'T1';
|
|
313
|
+
continent: ContinentCode;
|
|
314
|
+
region?: string;
|
|
315
|
+
regionCode?: string;
|
|
316
|
+
postalCode: string;
|
|
317
|
+
timezone: string;
|
|
318
|
+
colo: string;
|
|
319
|
+
asn?: number;
|
|
320
|
+
};
|
|
321
|
+
type UserAgentData = {
|
|
322
|
+
browser: {
|
|
323
|
+
name: string;
|
|
324
|
+
version: string;
|
|
325
|
+
};
|
|
326
|
+
device: {
|
|
327
|
+
model: string;
|
|
328
|
+
vendor: string;
|
|
329
|
+
type: UAParser.IDevice['type'] | 'desktop';
|
|
330
|
+
};
|
|
331
|
+
engine: {
|
|
332
|
+
name: string;
|
|
333
|
+
version: string;
|
|
334
|
+
};
|
|
335
|
+
os: {
|
|
336
|
+
name: string;
|
|
337
|
+
version: string;
|
|
338
|
+
};
|
|
339
|
+
cpu: string;
|
|
340
|
+
};
|
|
341
|
+
type HonoClientInfoVariables = {
|
|
342
|
+
client: CFData & {
|
|
343
|
+
ip: string;
|
|
344
|
+
userAgent: string;
|
|
345
|
+
securityHash: string;
|
|
346
|
+
} & UserAgentData;
|
|
347
|
+
};
|
|
348
|
+
/**
|
|
349
|
+
* Hono middleware that extracts and injects comprehensive client information
|
|
350
|
+
* into the request context, including geolocation data from Cloudflare and
|
|
351
|
+
* parsed User-Agent details.
|
|
352
|
+
* @param {Object} [config] - Optional configuration for the middleware.
|
|
353
|
+
* @param {Function} [config.securityHashString] - A custom function to generate the seed string
|
|
354
|
+
* used for the security hash. Receives Cloudflare and User-Agent data as input.
|
|
355
|
+
* Defaults to `${city}${country}${continent}`.
|
|
356
|
+
* @param {string} [config.hashSecretBinding] - The name of the environment variable
|
|
357
|
+
* containing the hash secret. Defaults to 'HASH_SECRET'.
|
|
358
|
+
* @returns {MiddlewareHandler} A Hono middleware handler.
|
|
359
|
+
* @throws {Error} Throws an error if Cloudflare (`req.raw.cf`) data is missing.
|
|
360
|
+
* @example
|
|
361
|
+
* ```ts
|
|
362
|
+
* const app = new Hono<{ Variables: HonoClientInfoVariables }>();
|
|
363
|
+
*
|
|
364
|
+
* app.use('*', clientInfo());
|
|
365
|
+
*
|
|
366
|
+
* app.get('/me', (c) => {
|
|
367
|
+
* const client = c.get('client');
|
|
368
|
+
* return c.json({
|
|
369
|
+
* location: `${client.city}, ${client.country}`,
|
|
370
|
+
* device: client.device.type
|
|
371
|
+
* });
|
|
372
|
+
* });
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
declare const clientInfo: (config?: {
|
|
376
|
+
hashSecretBinding?: string;
|
|
377
|
+
securityHashString?: (content: CFData & UserAgentData & {
|
|
378
|
+
ip: string;
|
|
379
|
+
}) => string;
|
|
380
|
+
}) => hono.MiddlewareHandler<{
|
|
381
|
+
Bindings: Record<string, string>;
|
|
382
|
+
Variables: HonoClientInfoVariables;
|
|
383
|
+
}, string, {}, Response>;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* A Hono middleware factory that hydrates a context variable based on environment bindings or other variables.
|
|
387
|
+
* @template {Record<string, unknown>} Bindings - The environment bindings (e.g., Cloudflare Env).
|
|
388
|
+
* @template {Record<string, unknown>} Variables - The Hono context variables.
|
|
389
|
+
* @template HidratedResult - The resulting type of the hydrated variable.
|
|
390
|
+
* @param {Object} options - The configuration options for hydration.
|
|
391
|
+
* @param {keyof Variables} options.variableName - The name of the variable in the context to be set.
|
|
392
|
+
* @param {(c: Bindings & { get: <T>(key: keyof Variables) => T }) => HidratedResult} options.hydrate -
|
|
393
|
+
* A function that takes the environment and a getter, returning the hydrated value.
|
|
394
|
+
* @returns {import("hono").MiddlewareHandler} A Hono middleware that performs the hydration and calls next().
|
|
395
|
+
* @example
|
|
396
|
+
* const middleware = hydrateVariable({
|
|
397
|
+
* variableName: 'userProfile',
|
|
398
|
+
* hydrate: (c) => new UserProfile(c.USER_ID)
|
|
399
|
+
* });
|
|
400
|
+
*/
|
|
401
|
+
declare const hydrateVariable: <Bindings extends Record<string, unknown>, Variables extends Record<string, unknown>, HidratedResult>({ variableName, hydrate, }: {
|
|
402
|
+
variableName: keyof Variables;
|
|
403
|
+
hydrate: (c: Bindings & {
|
|
404
|
+
get: <T>(key: keyof Variables) => T;
|
|
405
|
+
}) => HidratedResult;
|
|
406
|
+
}) => hono.MiddlewareHandler<{
|
|
407
|
+
Bindings: Bindings;
|
|
408
|
+
Variables: Record<string, HidratedResult>;
|
|
409
|
+
}, string, {}, Response>;
|
|
410
|
+
|
|
307
411
|
/**
|
|
308
412
|
* Derives a secure hex-encoded hash from an input string using PBKDF2-HMAC-SHA256.
|
|
309
413
|
* * @example
|
|
@@ -375,4 +479,4 @@ interface CreateTypedClientOptions {
|
|
|
375
479
|
}
|
|
376
480
|
declare const createTypedClient: <TApp extends Hono<any, any, any>>(options: CreateTypedClientOptions) => <TSuccessData>(fn: (c: ReturnType<typeof hc<TApp>>) => Promise<ClientResponse<TSuccessData>>) => Promise<TSuccessData>;
|
|
377
481
|
|
|
378
|
-
export { type ContextFn, type CreateTypedClientOptions, type HonoI18nVariables, type HonoIsBotVariables, type HonoLanguageVariables, type HonoLoggerVariables, type HonoResponseVariables, type MessageHandlers, pbkdf2 as PBKDF2, QueueHandler, sha as SHA, type WrappableMiddleware, createTypedClient, i18n, isBot, jsonValidator, logger, onError, onNotFound, queue, response, withLogger };
|
|
482
|
+
export { type ContextFn, type CreateTypedClientOptions, type HonoClientInfoVariables, type HonoI18nVariables, type HonoIsBotVariables, type HonoLanguageVariables, type HonoLoggerVariables, type HonoResponseVariables, type MessageHandlers, pbkdf2 as PBKDF2, QueueHandler, sha as SHA, type WrappableMiddleware, clientInfo, createTypedClient, hydrateVariable, i18n, isBot, jsonValidator, logger, onError, onNotFound, queue, response, withLogger };
|
package/dist/index.js
CHANGED
|
@@ -13957,6 +13957,10 @@ var response = createMiddleware6(async (c, next) => {
|
|
|
13957
13957
|
await next();
|
|
13958
13958
|
});
|
|
13959
13959
|
|
|
13960
|
+
// src/middleware/clientInfo.ts
|
|
13961
|
+
import { createMiddleware as createMiddleware7 } from "hono/factory";
|
|
13962
|
+
import { UAParser } from "ua-parser-js";
|
|
13963
|
+
|
|
13960
13964
|
// src/crypto/pbkdf2.ts
|
|
13961
13965
|
var pbkdf2_exports = {};
|
|
13962
13966
|
__export(pbkdf2_exports, {
|
|
@@ -14038,6 +14042,91 @@ async function hash3({
|
|
|
14038
14042
|
return hashedString;
|
|
14039
14043
|
}
|
|
14040
14044
|
|
|
14045
|
+
// src/middleware/clientInfo.ts
|
|
14046
|
+
var clientInfo = (config2) => createMiddleware7(async ({ env, req, set: set2 }, next) => {
|
|
14047
|
+
if (!req.raw.cf) {
|
|
14048
|
+
throw new Error("Cloudflare data is not available");
|
|
14049
|
+
}
|
|
14050
|
+
const hashSecret = env[config2?.hashSecretBinding ?? "HASH_SECRET"];
|
|
14051
|
+
if (!hashSecret) {
|
|
14052
|
+
throw new Error("Hash secret is not available");
|
|
14053
|
+
}
|
|
14054
|
+
const {
|
|
14055
|
+
latitude,
|
|
14056
|
+
longitude,
|
|
14057
|
+
city,
|
|
14058
|
+
country,
|
|
14059
|
+
continent,
|
|
14060
|
+
colo,
|
|
14061
|
+
asn,
|
|
14062
|
+
isEUCountry,
|
|
14063
|
+
region,
|
|
14064
|
+
regionCode,
|
|
14065
|
+
postalCode,
|
|
14066
|
+
timezone
|
|
14067
|
+
} = req.raw.cf;
|
|
14068
|
+
const cf = {
|
|
14069
|
+
latitude,
|
|
14070
|
+
longitude,
|
|
14071
|
+
city,
|
|
14072
|
+
country,
|
|
14073
|
+
continent,
|
|
14074
|
+
colo,
|
|
14075
|
+
asn,
|
|
14076
|
+
isEUCountry: Boolean(isEUCountry),
|
|
14077
|
+
region,
|
|
14078
|
+
regionCode,
|
|
14079
|
+
postalCode,
|
|
14080
|
+
timezone
|
|
14081
|
+
};
|
|
14082
|
+
const userAgent = req.raw.headers.get("user-agent") ?? "Unknown";
|
|
14083
|
+
const parser = new UAParser(userAgent);
|
|
14084
|
+
const userAgentParsed = parser.getResult();
|
|
14085
|
+
const { browser, device, engine, os, cpu } = userAgentParsed;
|
|
14086
|
+
const ua = {
|
|
14087
|
+
browser: {
|
|
14088
|
+
name: browser.name ?? "Unknown",
|
|
14089
|
+
version: browser.version ?? "Unknown"
|
|
14090
|
+
},
|
|
14091
|
+
device: {
|
|
14092
|
+
model: device.model ?? "Unknown",
|
|
14093
|
+
vendor: device.vendor ?? "Unknown",
|
|
14094
|
+
type: device.type ?? "desktop"
|
|
14095
|
+
},
|
|
14096
|
+
engine: {
|
|
14097
|
+
name: engine.name ?? "Unknown",
|
|
14098
|
+
version: engine.version ?? "Unknown"
|
|
14099
|
+
},
|
|
14100
|
+
os: {
|
|
14101
|
+
name: os.name ?? "Unknown",
|
|
14102
|
+
version: os.version ?? "Unknown"
|
|
14103
|
+
},
|
|
14104
|
+
cpu: cpu.architecture ?? "Unknown"
|
|
14105
|
+
};
|
|
14106
|
+
const ip = req.raw.headers.get("CF-Connecting-IP") ?? "127.0.0.1";
|
|
14107
|
+
const clientContent = { ...cf, ...ua, ip };
|
|
14108
|
+
set2("client", {
|
|
14109
|
+
...clientContent,
|
|
14110
|
+
userAgent,
|
|
14111
|
+
securityHash: await sha_exports.hash({
|
|
14112
|
+
input: config2?.securityHashString?.(clientContent) ?? `${ip}${city}${country}${userAgent}`,
|
|
14113
|
+
algorithm: "SHA-512",
|
|
14114
|
+
pepper: hashSecret
|
|
14115
|
+
})
|
|
14116
|
+
});
|
|
14117
|
+
next();
|
|
14118
|
+
});
|
|
14119
|
+
|
|
14120
|
+
// src/middleware/hydrateVariable.ts
|
|
14121
|
+
import { createMiddleware as createMiddleware8 } from "hono/factory";
|
|
14122
|
+
var hydrateVariable = ({
|
|
14123
|
+
variableName,
|
|
14124
|
+
hydrate
|
|
14125
|
+
}) => createMiddleware8(async ({ set: set2, env, get }, next) => {
|
|
14126
|
+
set2(variableName, hydrate({ ...env, get }));
|
|
14127
|
+
await next();
|
|
14128
|
+
});
|
|
14129
|
+
|
|
14041
14130
|
// src/queue/QueueHandler.ts
|
|
14042
14131
|
import { init } from "@paralleldrive/cuid2";
|
|
14043
14132
|
var QueueHandler = class {
|
|
@@ -14190,7 +14279,9 @@ export {
|
|
|
14190
14279
|
pbkdf2_exports as PBKDF2,
|
|
14191
14280
|
QueueHandler,
|
|
14192
14281
|
sha_exports as SHA,
|
|
14282
|
+
clientInfo,
|
|
14193
14283
|
createTypedClient,
|
|
14284
|
+
hydrateVariable,
|
|
14194
14285
|
i18n,
|
|
14195
14286
|
isBot,
|
|
14196
14287
|
jsonValidator,
|