takos-common 1.0.0

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.
Files changed (50) hide show
  1. package/dist/abort.d.ts +14 -0
  2. package/dist/abort.d.ts.map +1 -0
  3. package/dist/abort.js +26 -0
  4. package/dist/abort.js.map +1 -0
  5. package/dist/env-parse.d.ts +74 -0
  6. package/dist/env-parse.d.ts.map +1 -0
  7. package/dist/env-parse.js +124 -0
  8. package/dist/env-parse.js.map +1 -0
  9. package/dist/errors.d.ts +181 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +271 -0
  12. package/dist/errors.js.map +1 -0
  13. package/dist/id.d.ts +23 -0
  14. package/dist/id.d.ts.map +1 -0
  15. package/dist/id.js +32 -0
  16. package/dist/id.js.map +1 -0
  17. package/dist/index.d.ts +17 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +43 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/jwt.d.ts +54 -0
  22. package/dist/jwt.d.ts.map +1 -0
  23. package/dist/jwt.js +149 -0
  24. package/dist/jwt.js.map +1 -0
  25. package/dist/logger.d.ts +22 -0
  26. package/dist/logger.d.ts.map +1 -0
  27. package/dist/logger.js +99 -0
  28. package/dist/logger.js.map +1 -0
  29. package/dist/middleware/hono.d.ts +151 -0
  30. package/dist/middleware/hono.d.ts.map +1 -0
  31. package/dist/middleware/hono.js +189 -0
  32. package/dist/middleware/hono.js.map +1 -0
  33. package/dist/validation.d.ts +21 -0
  34. package/dist/validation.d.ts.map +1 -0
  35. package/dist/validation.js +102 -0
  36. package/dist/validation.js.map +1 -0
  37. package/package.json +55 -0
  38. package/src/__tests__/jwt.test.ts +208 -0
  39. package/src/__tests__/validation.test.ts +42 -0
  40. package/src/abort.ts +30 -0
  41. package/src/env-parse.ts +153 -0
  42. package/src/errors.ts +341 -0
  43. package/src/id.ts +33 -0
  44. package/src/index.ts +81 -0
  45. package/src/jwt.ts +218 -0
  46. package/src/logger.ts +136 -0
  47. package/src/middleware/hono.ts +310 -0
  48. package/src/validation.ts +105 -0
  49. package/tsconfig.json +18 -0
  50. package/tsconfig.tsbuildinfo +1 -0
package/dist/logger.js ADDED
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Structured Logger for Takos Platform
3
+ *
4
+ * Zero-dependency structured logging compatible with Cloudflare Workers.
5
+ * Outputs JSON to console methods so CF observability picks up the correct level.
6
+ */
7
+ const LEVEL_ORDER = {
8
+ debug: 0,
9
+ info: 1,
10
+ warn: 2,
11
+ error: 3,
12
+ };
13
+ function serializeError(value) {
14
+ if (value instanceof Error) {
15
+ return {
16
+ name: value.name,
17
+ message: value.message,
18
+ stack: value.stack,
19
+ };
20
+ }
21
+ return { message: String(value) };
22
+ }
23
+ function formatData(data) {
24
+ if (!data)
25
+ return undefined;
26
+ const result = {};
27
+ for (const [key, value] of Object.entries(data)) {
28
+ if (value instanceof Error) {
29
+ result[key] = serializeError(value);
30
+ }
31
+ else {
32
+ result[key] = value;
33
+ }
34
+ }
35
+ return result;
36
+ }
37
+ const LEVEL_NAMES = Object.fromEntries(Object.entries(LEVEL_ORDER).map(([k, v]) => [v, k]));
38
+ class LoggerImpl {
39
+ minLevel;
40
+ service;
41
+ fields;
42
+ constructor(opts) {
43
+ this.minLevel = LEVEL_ORDER[opts?.level ?? 'debug'];
44
+ this.service = opts?.service;
45
+ this.fields = { ...opts?.defaultFields, ...opts?._fields };
46
+ }
47
+ emit(level, msg, data) {
48
+ if (LEVEL_ORDER[level] < this.minLevel)
49
+ return;
50
+ const entry = {
51
+ level,
52
+ msg,
53
+ ts: new Date().toISOString(),
54
+ ...(this.service ? { service: this.service } : {}),
55
+ ...this.fields,
56
+ ...formatData(data),
57
+ };
58
+ const line = JSON.stringify(entry);
59
+ switch (level) {
60
+ case 'debug':
61
+ // eslint-disable-next-line no-console -- logger implementation
62
+ console.log(line);
63
+ break;
64
+ case 'info':
65
+ // eslint-disable-next-line no-console -- logger implementation
66
+ console.log(line);
67
+ break;
68
+ case 'warn':
69
+ console.warn(line);
70
+ break;
71
+ case 'error':
72
+ console.error(line);
73
+ break;
74
+ }
75
+ }
76
+ debug(msg, data) {
77
+ this.emit('debug', msg, data);
78
+ }
79
+ info(msg, data) {
80
+ this.emit('info', msg, data);
81
+ }
82
+ warn(msg, data) {
83
+ this.emit('warn', msg, data);
84
+ }
85
+ error(msg, data) {
86
+ this.emit('error', msg, data);
87
+ }
88
+ child(fields) {
89
+ return new LoggerImpl({
90
+ level: LEVEL_NAMES[this.minLevel],
91
+ service: this.service,
92
+ _fields: { ...this.fields, ...fields },
93
+ });
94
+ }
95
+ }
96
+ export function createLogger(opts) {
97
+ return new LoggerImpl(opts);
98
+ }
99
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Hono Middleware for takos-runtime
3
+ *
4
+ * Provides:
5
+ * - Service-to-service JWT authentication (RS256)
6
+ * - Consistent error handling
7
+ */
8
+ import type { Context, Next, Env, ErrorHandler } from 'hono';
9
+ import { type ServiceTokenPayloadWithClaims } from '../jwt.js';
10
+ export type { ServiceTokenPayloadWithClaims };
11
+ import { AppError } from '../errors.js';
12
+ /**
13
+ * Environment bindings for service token middleware.
14
+ * Use this as a type parameter for Hono to get typed context variables.
15
+ *
16
+ * Usage:
17
+ * ```typescript
18
+ * import type { ServiceTokenEnv } from 'takos-common/middleware/hono';
19
+ * const app = new Hono<ServiceTokenEnv>();
20
+ * ```
21
+ */
22
+ export interface ServiceTokenEnv extends Env {
23
+ Variables: {
24
+ serviceToken: ServiceTokenPayloadWithClaims;
25
+ serviceAuthMethod: 'jwt';
26
+ };
27
+ }
28
+ /**
29
+ * Configuration for service token middleware
30
+ */
31
+ export interface ServiceTokenConfig {
32
+ /** Public key for JWT verification (PEM format) */
33
+ jwtPublicKey?: string;
34
+ /** Expected issuer for JWT tokens (required when jwtPublicKey is set) */
35
+ expectedIssuer?: string;
36
+ /** Expected audience for JWT tokens (required when jwtPublicKey is set) */
37
+ expectedAudience?: string;
38
+ /** Paths to skip authentication (e.g., health checks) */
39
+ skipPaths?: string[];
40
+ /** Clock tolerance in seconds (default: 30) */
41
+ clockToleranceSeconds?: number;
42
+ }
43
+ /**
44
+ * Extract service token from Authorization header.
45
+ *
46
+ * Note: `takos/packages/control/src/shared/utils/url-utils.ts` contains an
47
+ * equivalent lower-level helper `extractBearerToken(header: string | null)`
48
+ * that operates on a raw header string. The two cannot be unified here
49
+ * because `takos-common` must not import from the `control` package.
50
+ * If the extraction logic ever needs to change, update both places.
51
+ */
52
+ export declare function getServiceTokenFromHeader(c: Context): string | null;
53
+ /**
54
+ * Create Hono middleware for service token authentication.
55
+ * Only RS256 JWTs are accepted.
56
+ *
57
+ * @param config - Configuration for the middleware
58
+ * @returns Hono middleware function
59
+ *
60
+ * Usage:
61
+ * ```typescript
62
+ * import { createServiceTokenMiddleware } from 'takos-common/middleware/hono';
63
+ *
64
+ * const app = new Hono<ServiceTokenEnv>();
65
+ * app.use('*', createServiceTokenMiddleware({ jwtPublicKey: '...' }));
66
+ * ```
67
+ */
68
+ export declare function createServiceTokenMiddleware(config: ServiceTokenConfig): (c: Context, next: Next) => Promise<Response | void>;
69
+ /**
70
+ * Error handler options
71
+ */
72
+ export interface ErrorHandlerOptions {
73
+ /** Include stack traces in responses (only for development) */
74
+ includeStack?: boolean;
75
+ /** Custom error logger */
76
+ logger?: (error: unknown, context?: Record<string, unknown>) => void;
77
+ /** Custom error transformer */
78
+ transformError?: (error: unknown) => AppError;
79
+ }
80
+ /**
81
+ * Create Hono error handler (for use with `app.onError`)
82
+ *
83
+ * Usage:
84
+ * ```typescript
85
+ * import { createErrorHandler } from 'takos-common/middleware/hono';
86
+ *
87
+ * const app = new Hono();
88
+ * app.onError(createErrorHandler({ includeStack: true }));
89
+ * ```
90
+ */
91
+ export declare function createErrorHandler(options?: ErrorHandlerOptions): ErrorHandler;
92
+ /**
93
+ * Not found handler for Hono
94
+ * Use with `app.notFound()`
95
+ *
96
+ * Usage:
97
+ * ```typescript
98
+ * import { notFoundHandler } from 'takos-common/middleware/hono';
99
+ *
100
+ * const app = new Hono();
101
+ * app.notFound(notFoundHandler);
102
+ * ```
103
+ */
104
+ export declare function notFoundHandler(c: Context): Response & import("hono").TypedResponse<{
105
+ error: {
106
+ code: string;
107
+ message: string;
108
+ details?: import("hono/utils/types").JSONValue | undefined;
109
+ };
110
+ }, 404, "json">;
111
+ /**
112
+ * 400 Bad Request
113
+ */
114
+ export declare function badRequest(c: Context, message?: string, details?: unknown): Response & import("hono").TypedResponse<{
115
+ error: {
116
+ code: string;
117
+ message: string;
118
+ details?: import("hono/utils/types").JSONValue | undefined;
119
+ };
120
+ }, 400, "json">;
121
+ /**
122
+ * 404 Not Found
123
+ */
124
+ export declare function notFound(c: Context, message?: string, details?: unknown): Response & import("hono").TypedResponse<{
125
+ error: {
126
+ code: string;
127
+ message: string;
128
+ details?: import("hono/utils/types").JSONValue | undefined;
129
+ };
130
+ }, 404, "json">;
131
+ /**
132
+ * 403 Forbidden
133
+ */
134
+ export declare function forbidden(c: Context, message?: string, details?: unknown): Response & import("hono").TypedResponse<{
135
+ error: {
136
+ code: string;
137
+ message: string;
138
+ details?: import("hono/utils/types").JSONValue | undefined;
139
+ };
140
+ }, 403, "json">;
141
+ /**
142
+ * 500 Internal Server Error
143
+ */
144
+ export declare function internalError(c: Context, message?: string, details?: unknown): Response & import("hono").TypedResponse<{
145
+ error: {
146
+ code: string;
147
+ message: string;
148
+ details?: import("hono/utils/types").JSONValue | undefined;
149
+ };
150
+ }, 500, "json">;
151
+ //# sourceMappingURL=hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../src/middleware/hono.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EAEL,KAAK,6BAA6B,EACnC,MAAM,WAAW,CAAC;AAEnB,YAAY,EAAE,6BAA6B,EAAE,CAAC;AAC9C,OAAO,EACL,QAAQ,EAWT,MAAM,cAAc,CAAC;AAMtB;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAgB,SAAQ,GAAG;IAC1C,SAAS,EAAE;QACT,YAAY,EAAE,6BAA6B,CAAC;QAC5C,iBAAiB,EAAE,KAAK,CAAC;KAC1B,CAAC;CACH;AAMD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,+CAA+C;IAC/C,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAMnE;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,kBAAkB,IASvD,GAAG,OAAO,EAAE,MAAM,IAAI,KAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAgDhE;AAMD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACrE,+BAA+B;IAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,QAAQ,CAAC;CAC/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,mBAAwB,GAChC,YAAY,CAoCd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO;;;;;;gBAGzC;AAoBD;;GAEG;AACH,wBAAgB,UAAU,CACxB,CAAC,EAAE,OAAO,EACV,OAAO,SAAgB,EACvB,OAAO,CAAC,EAAE,OAAO;;;;;;gBAGlB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,CAAC,EAAE,OAAO,EACV,OAAO,SAAc,EACrB,OAAO,CAAC,EAAE,OAAO;;;;;;gBAGlB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,SAAkB,EAAE,OAAO,CAAC,EAAE,OAAO;;;;;;gBAEjF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,CAAC,EAAE,OAAO,EACV,OAAO,SAA0B,EACjC,OAAO,CAAC,EAAE,OAAO;;;;;;gBAGlB"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Hono Middleware for takos-runtime
3
+ *
4
+ * Provides:
5
+ * - Service-to-service JWT authentication (RS256)
6
+ * - Consistent error handling
7
+ */
8
+ import { verifyServiceToken, } from '../jwt.js';
9
+ import { AuthenticationError, ErrorCodes, InternalError, isAppError, logError, NotFoundError, RateLimitError, ServiceUnavailableError, } from '../errors.js';
10
+ /**
11
+ * Extract service token from Authorization header.
12
+ *
13
+ * Note: `takos/packages/control/src/shared/utils/url-utils.ts` contains an
14
+ * equivalent lower-level helper `extractBearerToken(header: string | null)`
15
+ * that operates on a raw header string. The two cannot be unified here
16
+ * because `takos-common` must not import from the `control` package.
17
+ * If the extraction logic ever needs to change, update both places.
18
+ */
19
+ export function getServiceTokenFromHeader(c) {
20
+ const authHeader = c.req.header('Authorization');
21
+ if (authHeader?.startsWith('Bearer ')) {
22
+ return authHeader.slice('Bearer '.length).trim();
23
+ }
24
+ return null;
25
+ }
26
+ /**
27
+ * Check if the token looks like a JWT (has 3 parts separated by dots)
28
+ */
29
+ function isJwtFormat(token) {
30
+ const parts = token.split('.');
31
+ return parts.length === 3;
32
+ }
33
+ /**
34
+ * Create Hono middleware for service token authentication.
35
+ * Only RS256 JWTs are accepted.
36
+ *
37
+ * @param config - Configuration for the middleware
38
+ * @returns Hono middleware function
39
+ *
40
+ * Usage:
41
+ * ```typescript
42
+ * import { createServiceTokenMiddleware } from 'takos-common/middleware/hono';
43
+ *
44
+ * const app = new Hono<ServiceTokenEnv>();
45
+ * app.use('*', createServiceTokenMiddleware({ jwtPublicKey: '...' }));
46
+ * ```
47
+ */
48
+ export function createServiceTokenMiddleware(config) {
49
+ const { jwtPublicKey, expectedIssuer, expectedAudience, skipPaths = ['/health'], clockToleranceSeconds = 30, } = config;
50
+ return async (c, next) => {
51
+ // Skip authentication for certain paths (e.g., health checks)
52
+ const path = new URL(c.req.url).pathname;
53
+ if (skipPaths.includes(path)) {
54
+ await next();
55
+ return;
56
+ }
57
+ if (!jwtPublicKey) {
58
+ const error = new ServiceUnavailableError('Service token not configured');
59
+ return c.json(error.toResponse(), error.statusCode);
60
+ }
61
+ if (!expectedIssuer || !expectedAudience) {
62
+ const error = new ServiceUnavailableError('JWT verification requires expectedIssuer and expectedAudience');
63
+ return c.json(error.toResponse(), error.statusCode);
64
+ }
65
+ // Extract token from request
66
+ const token = getServiceTokenFromHeader(c);
67
+ if (!token) {
68
+ const error = new AuthenticationError('Authorization token is required');
69
+ return c.json(error.toResponse(), error.statusCode);
70
+ }
71
+ if (!isJwtFormat(token)) {
72
+ const error = new AuthenticationError('Service token must be a JWT');
73
+ return c.json(error.toResponse(), error.statusCode);
74
+ }
75
+ const result = verifyServiceToken({
76
+ token,
77
+ publicKey: jwtPublicKey,
78
+ expectedAudience,
79
+ expectedIssuer,
80
+ clockToleranceSeconds,
81
+ });
82
+ if (result.valid && result.payload) {
83
+ c.set('serviceToken', result.payload);
84
+ c.set('serviceAuthMethod', 'jwt');
85
+ await next();
86
+ return;
87
+ }
88
+ const error = new AuthenticationError(result.error || 'Invalid JWT token');
89
+ return c.json(error.toResponse(), error.statusCode);
90
+ };
91
+ }
92
+ /**
93
+ * Create Hono error handler (for use with `app.onError`)
94
+ *
95
+ * Usage:
96
+ * ```typescript
97
+ * import { createErrorHandler } from 'takos-common/middleware/hono';
98
+ *
99
+ * const app = new Hono();
100
+ * app.onError(createErrorHandler({ includeStack: true }));
101
+ * ```
102
+ */
103
+ export function createErrorHandler(options = {}) {
104
+ const { includeStack = false, logger = logError, transformError } = options;
105
+ return (err, c) => {
106
+ // Transform error if transformer provided
107
+ let appError;
108
+ if (transformError) {
109
+ appError = transformError(err);
110
+ }
111
+ else if (isAppError(err)) {
112
+ appError = err;
113
+ }
114
+ else {
115
+ // Log non-operational errors with full details
116
+ const path = new URL(c.req.url).pathname;
117
+ logger(err, {
118
+ path,
119
+ method: c.req.method,
120
+ requestId: c.req.header('x-request-id'),
121
+ });
122
+ appError = new InternalError('An unexpected error occurred');
123
+ }
124
+ // Build response
125
+ const response = appError.toResponse();
126
+ // Add stack trace in development mode
127
+ if (includeStack && appError.stack) {
128
+ response.error.stack = appError.stack;
129
+ }
130
+ // Set special headers for rate limiting
131
+ if (appError instanceof RateLimitError && appError.retryAfter) {
132
+ c.header('Retry-After', String(appError.retryAfter));
133
+ }
134
+ return c.json(response, appError.statusCode);
135
+ };
136
+ }
137
+ /**
138
+ * Not found handler for Hono
139
+ * Use with `app.notFound()`
140
+ *
141
+ * Usage:
142
+ * ```typescript
143
+ * import { notFoundHandler } from 'takos-common/middleware/hono';
144
+ *
145
+ * const app = new Hono();
146
+ * app.notFound(notFoundHandler);
147
+ * ```
148
+ */
149
+ export function notFoundHandler(c) {
150
+ const error = new NotFoundError('Route');
151
+ return c.json(error.toResponse(), 404);
152
+ }
153
+ // ============================================================================
154
+ // Helper functions for route handlers
155
+ // ============================================================================
156
+ function buildErrorBody(message, code, details) {
157
+ return {
158
+ error: {
159
+ code,
160
+ message,
161
+ ...(details !== undefined && { details }),
162
+ },
163
+ };
164
+ }
165
+ /**
166
+ * 400 Bad Request
167
+ */
168
+ export function badRequest(c, message = 'Bad request', details) {
169
+ return c.json(buildErrorBody(message, ErrorCodes.BAD_REQUEST, details), 400);
170
+ }
171
+ /**
172
+ * 404 Not Found
173
+ */
174
+ export function notFound(c, message = 'Not found', details) {
175
+ return c.json(buildErrorBody(message, ErrorCodes.NOT_FOUND, details), 404);
176
+ }
177
+ /**
178
+ * 403 Forbidden
179
+ */
180
+ export function forbidden(c, message = 'Access denied', details) {
181
+ return c.json(buildErrorBody(message, ErrorCodes.FORBIDDEN, details), 403);
182
+ }
183
+ /**
184
+ * 500 Internal Server Error
185
+ */
186
+ export function internalError(c, message = 'Internal server error', details) {
187
+ return c.json(buildErrorBody(message, ErrorCodes.INTERNAL_ERROR, details), 500);
188
+ }
189
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../../src/middleware/hono.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Validation Utilities
3
+ *
4
+ * Provides common validation functions for input sanitization
5
+ * and security across all takos packages.
6
+ */
7
+ /**
8
+ * Check if a hostname is localhost or a local address.
9
+ *
10
+ * @param hostname - Hostname to check
11
+ * @returns true if the hostname is local
12
+ */
13
+ export declare function isLocalhost(hostname: string): boolean;
14
+ /**
15
+ * Check if an IP address is a private/internal address.
16
+ *
17
+ * @param ip - IP address to check
18
+ * @returns true if the IP is private
19
+ */
20
+ export declare function isPrivateIP(ip: string): boolean;
21
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWrD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAwE/C"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Validation Utilities
3
+ *
4
+ * Provides common validation functions for input sanitization
5
+ * and security across all takos packages.
6
+ */
7
+ /**
8
+ * Check if a hostname is localhost or a local address.
9
+ *
10
+ * @param hostname - Hostname to check
11
+ * @returns true if the hostname is local
12
+ */
13
+ export function isLocalhost(hostname) {
14
+ const lower = hostname.toLowerCase();
15
+ return (lower === 'localhost' ||
16
+ lower === '127.0.0.1' ||
17
+ lower === '::1' ||
18
+ lower.endsWith('.localhost') ||
19
+ lower.endsWith('.local') ||
20
+ lower.endsWith('.localdomain') ||
21
+ lower.endsWith('.internal'));
22
+ }
23
+ /**
24
+ * Check if an IP address is a private/internal address.
25
+ *
26
+ * @param ip - IP address to check
27
+ * @returns true if the IP is private
28
+ */
29
+ export function isPrivateIP(ip) {
30
+ // Check for IPv4 private ranges
31
+ const ipv4Match = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
32
+ if (ipv4Match) {
33
+ const [, a, b, c] = ipv4Match.map(Number);
34
+ // 0.0.0.0/8 - Current network
35
+ if (a === 0)
36
+ return true;
37
+ // 10.0.0.0/8 - Private network
38
+ if (a === 10)
39
+ return true;
40
+ // 127.0.0.0/8 - Loopback
41
+ if (a === 127)
42
+ return true;
43
+ // 169.254.0.0/16 - Link-local
44
+ if (a === 169 && b === 254)
45
+ return true;
46
+ // 172.16.0.0/12 - Private network
47
+ if (a === 172 && b >= 16 && b <= 31)
48
+ return true;
49
+ // 192.168.0.0/16 - Private network
50
+ if (a === 192 && b === 168)
51
+ return true;
52
+ // 100.64.0.0/10 - Carrier-grade NAT
53
+ if (a === 100 && b >= 64 && b <= 127)
54
+ return true;
55
+ // 192.0.0.0/24 - IETF Protocol Assignments
56
+ if (a === 192 && b === 0 && c === 0)
57
+ return true;
58
+ // 192.0.2.0/24 - Documentation (TEST-NET-1)
59
+ if (a === 192 && b === 0 && c === 2)
60
+ return true;
61
+ // 198.18.0.0/15 - Benchmarking
62
+ if (a === 198 && (b === 18 || b === 19))
63
+ return true;
64
+ // 198.51.100.0/24 - Documentation (TEST-NET-2)
65
+ if (a === 198 && b === 51 && c === 100)
66
+ return true;
67
+ // 203.0.113.0/24 - Documentation (TEST-NET-3)
68
+ if (a === 203 && b === 0 && c === 113)
69
+ return true;
70
+ // 224.0.0.0+ - Multicast and reserved
71
+ if (a >= 224)
72
+ return true;
73
+ }
74
+ // IPv6 private ranges
75
+ if (ip.startsWith('::1'))
76
+ return true; // Loopback
77
+ if (ip.startsWith('fe80:'))
78
+ return true; // Link-local
79
+ if (ip.startsWith('fc') || ip.startsWith('fd'))
80
+ return true; // Unique local
81
+ // IPv4-mapped IPv6 addresses (e.g. ::ffff:192.168.1.1 or ::ffff:0a00:0001)
82
+ const ipLower = ip.toLowerCase();
83
+ if (ipLower.startsWith('::ffff:')) {
84
+ const rest = ipLower.slice('::ffff:'.length);
85
+ // Handle dotted-decimal form: ::ffff:192.168.1.1
86
+ if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(rest)) {
87
+ return isPrivateIP(rest);
88
+ }
89
+ // Handle hex form: ::ffff:c0a8:0101 → convert to dotted-decimal
90
+ const hexParts = rest.split(':');
91
+ if (hexParts.length === 2) {
92
+ const hi = parseInt(hexParts[0], 16);
93
+ const lo = parseInt(hexParts[1], 16);
94
+ if (!isNaN(hi) && !isNaN(lo)) {
95
+ const dotted = `${(hi >> 8) & 0xff}.${hi & 0xff}.${(lo >> 8) & 0xff}.${lo & 0xff}`;
96
+ return isPrivateIP(dotted);
97
+ }
98
+ }
99
+ }
100
+ return false;
101
+ }
102
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "takos-common",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./id": {
13
+ "types": "./dist/id.d.ts",
14
+ "import": "./dist/id.js"
15
+ },
16
+ "./validation": {
17
+ "types": "./dist/validation.d.ts",
18
+ "import": "./dist/validation.js"
19
+ },
20
+ "./abort": {
21
+ "types": "./dist/abort.d.ts",
22
+ "import": "./dist/abort.js"
23
+ },
24
+ "./errors": {
25
+ "types": "./dist/errors.d.ts",
26
+ "import": "./dist/errors.js"
27
+ },
28
+ "./middleware/hono": {
29
+ "types": "./dist/middleware/hono.d.ts",
30
+ "import": "./dist/middleware/hono.js"
31
+ },
32
+ "./logger": {
33
+ "types": "./dist/logger.d.ts",
34
+ "import": "./dist/logger.js"
35
+ },
36
+ "./env-parse": {
37
+ "types": "./dist/env-parse.d.ts",
38
+ "import": "./dist/env-parse.js"
39
+ }
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "typecheck": "tsc --noEmit",
44
+ "clean": "rm -rf dist",
45
+ "test": "vitest run"
46
+ },
47
+ "dependencies": {
48
+ "hono": "^4.12.4"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.0.0",
52
+ "typescript": "^5.7.0",
53
+ "vitest": "^2.1.0"
54
+ }
55
+ }