@hazeljs/core 0.2.0-beta.8 → 0.2.0-beta.80

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.
@@ -19,45 +19,80 @@ function HazelModule(options) {
19
19
  // Alias for backward compatibility
20
20
  exports.Module = HazelModule;
21
21
  function getModuleMetadata(target) {
22
- return Reflect.getMetadata(MODULE_METADATA_KEY, target);
22
+ const fromDecorator = Reflect.getMetadata(MODULE_METADATA_KEY, target);
23
+ if (fromDecorator)
24
+ return fromDecorator;
25
+ // Support dynamic modules: { module, providers?, controllers?, imports? }
26
+ if (target && typeof target === 'object' && 'module' in target) {
27
+ const dyn = target;
28
+ return {
29
+ providers: dyn.providers,
30
+ controllers: dyn.controllers,
31
+ imports: dyn.imports,
32
+ };
33
+ }
34
+ return undefined;
23
35
  }
24
36
  class HazelModuleInstance {
25
37
  constructor(moduleType) {
26
38
  this.moduleType = moduleType;
27
- logger_1.default.debug(`Initializing HazelModule: ${moduleType.name}`);
39
+ const name = moduleType?.name ?? moduleType?.module?.name ?? 'DynamicModule';
40
+ logger_1.default.debug(`Initializing HazelModule: ${name}`);
28
41
  this.container = container_1.Container.getInstance();
29
42
  this.initialize();
30
43
  }
31
44
  initialize() {
32
45
  const metadata = getModuleMetadata(this.moduleType) || {};
33
46
  logger_1.default.debug('Module metadata:', metadata);
47
+ // Initialize imported modules first (so their providers are available)
48
+ if (metadata.imports) {
49
+ logger_1.default.debug('Initializing imported modules:', metadata.imports.map((m) => (m && typeof m === 'object' && 'module' in m ? m.module?.name : m?.name)));
50
+ metadata.imports.forEach((moduleType) => {
51
+ new HazelModuleInstance(moduleType);
52
+ });
53
+ }
34
54
  // Register providers
35
55
  if (metadata.providers) {
36
- logger_1.default.debug('Registering providers:', metadata.providers.map((p) => p.name));
56
+ logger_1.default.debug('Registering providers:', metadata.providers.map((p) => {
57
+ const val = p && typeof p === 'object' && 'provide' in p ? p.provide : p?.name;
58
+ return typeof val === 'symbol' ? val.toString() : val;
59
+ }));
37
60
  metadata.providers.forEach((provider) => {
38
- logger_1.default.debug(`Registering provider: ${provider.name}`);
61
+ // Dynamic module provider: { provide, useFactory?, useClass?, useValue? } (NestJS-style)
62
+ if (provider && typeof provider === 'object' && ('provide' in provider || 'token' in provider)) {
63
+ const p = provider;
64
+ const token = p.token ?? p.provide;
65
+ logger_1.default.debug(`Registering provider config for: ${typeof token === 'symbol' ? token.toString() : token}`);
66
+ this.container.registerProvider({
67
+ token,
68
+ useFactory: p.useFactory,
69
+ useClass: p.useClass,
70
+ useValue: p.useValue,
71
+ inject: p.inject,
72
+ });
73
+ return;
74
+ }
75
+ const cls = provider;
76
+ logger_1.default.debug(`Registering provider: ${cls?.name}`);
39
77
  // Check if provider is request-scoped
40
- const scope = Reflect.getMetadata('hazel:scope', provider);
78
+ const scope = Reflect.getMetadata('hazel:scope', cls);
41
79
  if (scope === 'request') {
42
80
  // Don't eagerly resolve request-scoped providers
43
- // They will be resolved per-request by the container
44
- logger_1.default.debug(`Skipping eager resolution for request-scoped provider: ${provider.name}`);
45
- // Just register the class itself, not an instance
46
81
  this.container.registerProvider({
47
- token: provider,
48
- useClass: provider,
82
+ token: cls,
83
+ useClass: cls,
49
84
  scope: container_1.Scope.REQUEST,
50
85
  });
51
86
  }
52
87
  else {
53
88
  // Eagerly resolve singleton and transient providers
54
- this.container.register(provider, this.container.resolve(provider));
89
+ this.container.register(cls, this.container.resolve(cls));
55
90
  }
56
91
  });
57
92
  }
58
93
  // Register controllers
59
94
  if (metadata.controllers) {
60
- logger_1.default.debug('Registering controllers:', metadata.controllers.map((c) => c.name));
95
+ logger_1.default.debug('Registering controllers:', metadata.controllers.map((c) => c?.name));
61
96
  metadata.controllers.forEach((controller) => {
62
97
  logger_1.default.debug(`Registering controller: ${controller.name}`);
63
98
  // Check if controller has request-scoped dependencies
@@ -94,13 +129,6 @@ class HazelModuleInstance {
94
129
  });
95
130
  });
96
131
  }
97
- // Initialize imported modules
98
- if (metadata.imports) {
99
- logger_1.default.debug('Initializing imported modules:', metadata.imports.map((m) => m.name));
100
- metadata.imports.forEach((moduleType) => {
101
- new HazelModuleInstance(moduleType);
102
- });
103
- }
104
132
  }
105
133
  getContainer() {
106
134
  return this.container;
@@ -5,6 +5,9 @@ export interface HazelResponse {
5
5
  end(): void;
6
6
  status(code: number): HazelResponse;
7
7
  json(data: unknown): void;
8
+ redirect(url: string, statusCode?: number): void;
9
+ /** Send a Buffer as binary (e.g. audio, PDF). Sets Content-Type if provided. */
10
+ sendBuffer?(buffer: Buffer, contentType?: string): void;
8
11
  }
9
12
  export declare class HazelExpressResponse implements HazelResponse {
10
13
  private res;
@@ -15,6 +18,8 @@ export declare class HazelExpressResponse implements HazelResponse {
15
18
  write(chunk: string): void;
16
19
  end(): void;
17
20
  status(code: number): HazelResponse;
21
+ redirect(url: string, statusCode?: number): void;
22
+ sendBuffer(buffer: Buffer, contentType?: string): void;
18
23
  json(data: unknown): void;
19
24
  }
20
25
  //# sourceMappingURL=hazel-response.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hazel-response.d.ts","sourceRoot":"","sources":["../src/hazel-response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,IAAI,IAAI,CAAC;IACZ,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IACpC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED,qBAAa,oBAAqB,YAAW,aAAa;IAI5C,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,WAAW,CAAkB;gBAEjB,GAAG,EAAE,QAAQ;IAEjC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAY1B,GAAG,IAAI,IAAI;IAMX,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAOnC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CA+B1B"}
1
+ {"version":3,"file":"hazel-response.d.ts","sourceRoot":"","sources":["../src/hazel-response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,IAAI,IAAI,CAAC;IACZ,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;IACpC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjD,gFAAgF;IAChF,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzD;AAED,qBAAa,oBAAqB,YAAW,aAAa;IAI5C,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,WAAW,CAAkB;gBAEjB,GAAG,EAAE,QAAQ;IAEjC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAY1B,GAAG,IAAI,IAAI;IAMX,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAOnC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,GAAG,IAAI;IAWrD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAWtD,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CA+B1B"}
@@ -35,6 +35,27 @@ class HazelExpressResponse {
35
35
  }
36
36
  return this;
37
37
  }
38
+ redirect(url, statusCode = 302) {
39
+ if (this.headersSent)
40
+ return;
41
+ if (typeof this.res.redirect === 'function') {
42
+ this.res.redirect(url, statusCode);
43
+ return;
44
+ }
45
+ this.headersSent = true;
46
+ this.res.writeHead(statusCode, { Location: url });
47
+ this.res.end();
48
+ }
49
+ sendBuffer(buffer, contentType) {
50
+ if (this.isStreaming || this.headersSent) {
51
+ return;
52
+ }
53
+ if (contentType) {
54
+ this.res.setHeader('Content-Type', contentType);
55
+ }
56
+ this.res.send(buffer);
57
+ this.headersSent = true;
58
+ }
38
59
  json(data) {
39
60
  if (this.isStreaming || this.headersSent) {
40
61
  return; // Don't try to send JSON if we're already streaming or headers are sent
package/dist/health.js CHANGED
@@ -19,7 +19,7 @@ class HealthCheckManager {
19
19
  */
20
20
  registerCheck(check) {
21
21
  this.checks.set(check.name, check);
22
- logger_1.default.info(`Registered health check: ${check.name}`);
22
+ logger_1.default.debug(`Registered health check: ${check.name}`);
23
23
  }
24
24
  /**
25
25
  * Run all health checks
package/dist/index.d.ts CHANGED
@@ -3,22 +3,22 @@
3
3
  * A modern, modular Node.js framework with TypeScript support
4
4
  */
5
5
  import 'reflect-metadata';
6
- export { HazelApp } from './hazel-app';
6
+ export { HazelApp, type EarlyHttpHandler, type ProxyHandler } from './hazel-app';
7
7
  export { HazelModule, Module, HazelModuleInstance, getModuleMetadata } from './hazel-module';
8
- export type { ModuleOptions } from './hazel-module';
8
+ export type { ModuleOptions, DynamicModule } from './hazel-module';
9
9
  export { ShutdownManager } from './shutdown';
10
10
  export type { ShutdownHandler } from './shutdown';
11
11
  export { HealthCheckManager, BuiltInHealthChecks } from './health';
12
12
  export type { HealthCheck, HealthCheckResult, HealthStatus } from './health';
13
13
  export { TimeoutMiddleware } from './middleware/timeout.middleware';
14
14
  export type { TimeoutOptions } from './middleware/timeout.middleware';
15
- export { Controller, Injectable, Service, Get, Post, Put, Delete, Patch, Body, Param, Query, Req, Res, Headers, HttpCode, Header, Redirect, Inject, UsePipes, UseInterceptors, UseGuards, type ControllerMetadata, type RouteMetadata, type ControllerOptions, type RouteOptions, type ServiceOptions, type InjectableOptions, type RepositoryOptions, type OnModuleInit, type OnModuleDestroy, type ExecutionContext, type CanActivate, } from './decorators';
15
+ export { Controller, Injectable, Service, Get, Post, Put, Delete, Patch, Body, Param, Query, Req, Res, Ip, Host, Headers, HttpCode, Header, Redirect, Inject, UsePipes, UseInterceptors, UseGuards, Public, SkipAuth, AITask, Timeout, Optional, Session, Retry, ApiTags, ApiOperation, SetMetadata, getMetadata, createParamDecorator, CUSTOM_METADATA_PREFIX, type ControllerMetadata, type RouteMetadata, type ControllerOptions, type RouteOptions, type ServiceOptions, type InjectableOptions, type RepositoryOptions, type OnModuleInit, type OnModuleDestroy, type ExecutionContext, type CanActivate, type RetryDecoratorOptions, type ApiOperationOptions, type ParamDecoratorContext, } from './decorators';
16
16
  export { Container, Scope, type InjectionToken, type Provider } from './container';
17
17
  export type { Type, Request, Response, RequestContext, ValidationSchema } from './types';
18
- export { HttpError, BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, ConflictError, InternalServerError, HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException, ConflictException, InternalServerErrorException, } from './errors/http.error';
18
+ export { HttpError, BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, ConflictError, InternalServerError, HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException, ConflictException, InternalServerErrorException, RequestTimeoutError, } from './errors/http.error';
19
19
  export { PipeTransform, ValidationError, ParseIntPipe, type PipeMetadata } from './pipes/pipe';
20
20
  export { ValidationPipe } from './pipes/validation.pipe';
21
- export { Interceptor, type InterceptorMetadata } from './interceptors/interceptor';
21
+ export { Interceptor, RetryInterceptor, type InterceptorMetadata, type RetryOptions, } from './interceptors/interceptor';
22
22
  export { type ExceptionFilter, type ArgumentsHost, ArgumentsHostImpl, Catch, getFilterExceptions, } from './filters/exception-filter';
23
23
  export { HttpExceptionFilter } from './filters/http-exception.filter';
24
24
  export { Test, TestingModule, TestingModuleBuilder, type TestingModuleMetadata, } from './testing/testing.module';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,8 +7,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
8
8
  };
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.ArgumentsHostImpl = exports.ValidationPipe = exports.ParseIntPipe = exports.ValidationError = exports.InternalServerErrorException = exports.ConflictException = exports.NotFoundException = exports.ForbiddenException = exports.UnauthorizedException = exports.BadRequestException = exports.HttpException = exports.InternalServerError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BadRequestError = exports.HttpError = exports.Scope = exports.Container = exports.UseGuards = exports.UseInterceptors = exports.UsePipes = exports.Inject = exports.Redirect = exports.Header = exports.HttpCode = exports.Headers = exports.Res = exports.Req = exports.Query = exports.Param = exports.Body = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.Service = exports.Injectable = exports.Controller = exports.TimeoutMiddleware = exports.BuiltInHealthChecks = exports.HealthCheckManager = exports.ShutdownManager = exports.getModuleMetadata = exports.HazelModuleInstance = exports.Module = exports.HazelModule = exports.HazelApp = void 0;
11
- exports.escapeHtml = exports.sanitizeObject = exports.sanitizeSql = exports.sanitizeEmail = exports.sanitizeUrl = exports.sanitizeString = exports.sanitizeHtml = exports.RequestParser = exports.Router = exports.Validator = exports.default = exports.logger = exports.UploadedFiles = exports.UploadedFile = exports.FileUploadInterceptor = exports.CsrfMiddleware = exports.RateLimitMiddleware = exports.SecurityHeadersMiddleware = exports.LoggerMiddleware = exports.CorsMiddleware = exports.GlobalMiddlewareManager = exports.extractVersion = exports.matchVersion = exports.getVersionMetadata = exports.VersioningType = exports.Version = exports.RouteMatcher = exports.TestingModuleBuilder = exports.TestingModule = exports.Test = exports.HttpExceptionFilter = exports.getFilterExceptions = exports.Catch = void 0;
10
+ exports.UnauthorizedError = exports.BadRequestError = exports.HttpError = exports.Scope = exports.Container = exports.CUSTOM_METADATA_PREFIX = exports.createParamDecorator = exports.getMetadata = exports.SetMetadata = exports.ApiOperation = exports.ApiTags = exports.Retry = exports.Session = exports.Optional = exports.Timeout = exports.AITask = exports.SkipAuth = exports.Public = exports.UseGuards = exports.UseInterceptors = exports.UsePipes = exports.Inject = exports.Redirect = exports.Header = exports.HttpCode = exports.Headers = exports.Host = exports.Ip = exports.Res = exports.Req = exports.Query = exports.Param = exports.Body = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.Service = exports.Injectable = exports.Controller = exports.TimeoutMiddleware = exports.BuiltInHealthChecks = exports.HealthCheckManager = exports.ShutdownManager = exports.getModuleMetadata = exports.HazelModuleInstance = exports.Module = exports.HazelModule = exports.HazelApp = void 0;
11
+ exports.escapeHtml = exports.sanitizeObject = exports.sanitizeSql = exports.sanitizeEmail = exports.sanitizeUrl = exports.sanitizeString = exports.sanitizeHtml = exports.RequestParser = exports.Router = exports.Validator = exports.default = exports.logger = exports.UploadedFiles = exports.UploadedFile = exports.FileUploadInterceptor = exports.CsrfMiddleware = exports.RateLimitMiddleware = exports.SecurityHeadersMiddleware = exports.LoggerMiddleware = exports.CorsMiddleware = exports.GlobalMiddlewareManager = exports.extractVersion = exports.matchVersion = exports.getVersionMetadata = exports.VersioningType = exports.Version = exports.RouteMatcher = exports.TestingModuleBuilder = exports.TestingModule = exports.Test = exports.HttpExceptionFilter = exports.getFilterExceptions = exports.Catch = exports.ArgumentsHostImpl = exports.RetryInterceptor = exports.ValidationPipe = exports.ParseIntPipe = exports.ValidationError = exports.RequestTimeoutError = exports.InternalServerErrorException = exports.ConflictException = exports.NotFoundException = exports.ForbiddenException = exports.UnauthorizedException = exports.BadRequestException = exports.HttpException = exports.InternalServerError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = void 0;
12
12
  // Import reflect-metadata to enable decorator metadata
13
13
  // Users don't need to import this manually
14
14
  require("reflect-metadata");
@@ -44,6 +44,8 @@ Object.defineProperty(exports, "Param", { enumerable: true, get: function () { r
44
44
  Object.defineProperty(exports, "Query", { enumerable: true, get: function () { return decorators_1.Query; } });
45
45
  Object.defineProperty(exports, "Req", { enumerable: true, get: function () { return decorators_1.Req; } });
46
46
  Object.defineProperty(exports, "Res", { enumerable: true, get: function () { return decorators_1.Res; } });
47
+ Object.defineProperty(exports, "Ip", { enumerable: true, get: function () { return decorators_1.Ip; } });
48
+ Object.defineProperty(exports, "Host", { enumerable: true, get: function () { return decorators_1.Host; } });
47
49
  Object.defineProperty(exports, "Headers", { enumerable: true, get: function () { return decorators_1.Headers; } });
48
50
  Object.defineProperty(exports, "HttpCode", { enumerable: true, get: function () { return decorators_1.HttpCode; } });
49
51
  Object.defineProperty(exports, "Header", { enumerable: true, get: function () { return decorators_1.Header; } });
@@ -52,6 +54,19 @@ Object.defineProperty(exports, "Inject", { enumerable: true, get: function () {
52
54
  Object.defineProperty(exports, "UsePipes", { enumerable: true, get: function () { return decorators_1.UsePipes; } });
53
55
  Object.defineProperty(exports, "UseInterceptors", { enumerable: true, get: function () { return decorators_1.UseInterceptors; } });
54
56
  Object.defineProperty(exports, "UseGuards", { enumerable: true, get: function () { return decorators_1.UseGuards; } });
57
+ Object.defineProperty(exports, "Public", { enumerable: true, get: function () { return decorators_1.Public; } });
58
+ Object.defineProperty(exports, "SkipAuth", { enumerable: true, get: function () { return decorators_1.SkipAuth; } });
59
+ Object.defineProperty(exports, "AITask", { enumerable: true, get: function () { return decorators_1.AITask; } });
60
+ Object.defineProperty(exports, "Timeout", { enumerable: true, get: function () { return decorators_1.Timeout; } });
61
+ Object.defineProperty(exports, "Optional", { enumerable: true, get: function () { return decorators_1.Optional; } });
62
+ Object.defineProperty(exports, "Session", { enumerable: true, get: function () { return decorators_1.Session; } });
63
+ Object.defineProperty(exports, "Retry", { enumerable: true, get: function () { return decorators_1.Retry; } });
64
+ Object.defineProperty(exports, "ApiTags", { enumerable: true, get: function () { return decorators_1.ApiTags; } });
65
+ Object.defineProperty(exports, "ApiOperation", { enumerable: true, get: function () { return decorators_1.ApiOperation; } });
66
+ Object.defineProperty(exports, "SetMetadata", { enumerable: true, get: function () { return decorators_1.SetMetadata; } });
67
+ Object.defineProperty(exports, "getMetadata", { enumerable: true, get: function () { return decorators_1.getMetadata; } });
68
+ Object.defineProperty(exports, "createParamDecorator", { enumerable: true, get: function () { return decorators_1.createParamDecorator; } });
69
+ Object.defineProperty(exports, "CUSTOM_METADATA_PREFIX", { enumerable: true, get: function () { return decorators_1.CUSTOM_METADATA_PREFIX; } });
55
70
  // Container & DI
56
71
  var container_1 = require("./container");
57
72
  Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return container_1.Container; } });
@@ -72,12 +87,16 @@ Object.defineProperty(exports, "ForbiddenException", { enumerable: true, get: fu
72
87
  Object.defineProperty(exports, "NotFoundException", { enumerable: true, get: function () { return http_error_1.NotFoundException; } });
73
88
  Object.defineProperty(exports, "ConflictException", { enumerable: true, get: function () { return http_error_1.ConflictException; } });
74
89
  Object.defineProperty(exports, "InternalServerErrorException", { enumerable: true, get: function () { return http_error_1.InternalServerErrorException; } });
90
+ Object.defineProperty(exports, "RequestTimeoutError", { enumerable: true, get: function () { return http_error_1.RequestTimeoutError; } });
75
91
  // Pipes
76
92
  var pipe_1 = require("./pipes/pipe");
77
93
  Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return pipe_1.ValidationError; } });
78
94
  Object.defineProperty(exports, "ParseIntPipe", { enumerable: true, get: function () { return pipe_1.ParseIntPipe; } });
79
95
  var validation_pipe_1 = require("./pipes/validation.pipe");
80
96
  Object.defineProperty(exports, "ValidationPipe", { enumerable: true, get: function () { return validation_pipe_1.ValidationPipe; } });
97
+ // Interceptors
98
+ var interceptor_1 = require("./interceptors/interceptor");
99
+ Object.defineProperty(exports, "RetryInterceptor", { enumerable: true, get: function () { return interceptor_1.RetryInterceptor; } });
81
100
  // Filters
82
101
  var exception_filter_1 = require("./filters/exception-filter");
83
102
  Object.defineProperty(exports, "ArgumentsHostImpl", { enumerable: true, get: function () { return exception_filter_1.ArgumentsHostImpl; } });
@@ -18,5 +18,13 @@ export declare class CacheInterceptor implements Interceptor {
18
18
  constructor(options?: CacheOptions);
19
19
  intercept(context: RequestContext, next: () => Promise<unknown>): Promise<unknown>;
20
20
  }
21
+ export interface RetryOptions {
22
+ count: number;
23
+ delay?: number;
24
+ retryIf?: (err: Error) => boolean;
25
+ }
26
+ export declare class RetryInterceptor implements Interceptor {
27
+ intercept(context: RequestContext, next: () => Promise<unknown>): Promise<unknown>;
28
+ }
21
29
  export type Type<T = unknown> = new (...args: unknown[]) => T;
22
30
  //# sourceMappingURL=interceptor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../src/interceptors/interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,kBAAmB,YAAW,WAAW;IAC9C,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;CAgBzF;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAA2D;IAC/E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAEjB,OAAO,CAAC,EAAE,YAAY;IAI5B,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;CAgBzF;AAED,MAAM,MAAM,IAAI,CAAC,CAAC,GAAG,OAAO,IAAI,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../src/interceptors/interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,kBAAmB,YAAW,WAAW;IAC9C,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;CAgBzF;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAA2D;IAC/E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAEjB,OAAO,CAAC,EAAE,YAAY;IAI5B,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;CAgBzF;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,OAAO,CAAC;CACnC;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAC5C,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;CAqBzF;AAED,MAAM,MAAM,IAAI,CAAC,CAAC,GAAG,OAAO,IAAI,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC"}
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CacheInterceptor = exports.LoggingInterceptor = void 0;
6
+ exports.RetryInterceptor = exports.CacheInterceptor = exports.LoggingInterceptor = void 0;
7
7
  const logger_1 = __importDefault(require("../logger"));
8
8
  class LoggingInterceptor {
9
9
  async intercept(context, next) {
@@ -44,3 +44,28 @@ class CacheInterceptor {
44
44
  }
45
45
  exports.CacheInterceptor = CacheInterceptor;
46
46
  CacheInterceptor.cache = new Map();
47
+ class RetryInterceptor {
48
+ async intercept(context, next) {
49
+ const opts = context.retryOptions;
50
+ if (!opts || opts.count < 1) {
51
+ return next();
52
+ }
53
+ const delayMs = opts.delay ?? 100;
54
+ const shouldRetry = opts.retryIf ?? (() => true);
55
+ let lastError;
56
+ for (let attempt = 0; attempt <= opts.count; attempt++) {
57
+ try {
58
+ return await next();
59
+ }
60
+ catch (err) {
61
+ lastError = err instanceof Error ? err : new Error(String(err));
62
+ if (attempt === opts.count || !shouldRetry(lastError)) {
63
+ throw lastError;
64
+ }
65
+ await new Promise((r) => setTimeout(r, delayMs));
66
+ }
67
+ }
68
+ throw lastError;
69
+ }
70
+ }
71
+ exports.RetryInterceptor = RetryInterceptor;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAuOvD,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,MAAM,IAAI,KACf,IAuBF,CAAC;AAQF,QAAA,MAAM,cAAc;0BALO,OAAO;CAOhC,CAAC;AAGH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAK9B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAwQvD,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,MAAM,IAAI,KACf,IAyBF,CAAC;AAQF,QAAA,MAAM,cAAc;0BALO,OAAO;CAOhC,CAAC;AAGH,eAAe,cAAc,CAAC"}
package/dist/logger.js CHANGED
@@ -13,8 +13,10 @@ const chalk_1 = __importDefault(require("chalk"));
13
13
  dotenv_1.default.config();
14
14
  const logLevel = process.env.LOG_LEVEL || 'info';
15
15
  const logDir = process.env.LOG_DIR || 'logs';
16
+ const logEnabled = process.env.LOG_ENABLED !== 'false'; // default: true
17
+ const logPackage = process.env.LOG_PACKAGE || ''; // e.g. "http" = only HTTP request logs
16
18
  // Ensure log directory exists
17
- if (!fs_1.default.existsSync(logDir)) {
19
+ if (logDir && !fs_1.default.existsSync(logDir)) {
18
20
  fs_1.default.mkdirSync(logDir, { recursive: true });
19
21
  }
20
22
  // Professional color scheme for different log levels
@@ -67,15 +69,16 @@ const getCategoryColor = (message) => {
67
69
  return chalk_1.default.white;
68
70
  };
69
71
  // Custom format for better readability with enhanced colors
70
- const customFormat = winston_1.default.format.printf(({ level, message, timestamp, ...metadata }) => {
72
+ const customFormat = winston_1.default.format.printf((info) => {
73
+ const { level, message, timestamp, ...metadata } = info;
71
74
  // Get the appropriate color for the log level
72
75
  const levelColor = colors[level] || chalk_1.default.white;
73
76
  // Format the timestamp with subtle color
74
- const time = chalk_1.default.gray.dim(timestamp);
77
+ const time = chalk_1.default.gray.dim(String(timestamp ?? ''));
75
78
  // Format the level with color and padding (no icons for professional look)
76
- const levelStr = levelColor.bold(`[${level.toUpperCase()}]`.padEnd(9));
79
+ const levelStr = levelColor.bold(`[${String(level).toUpperCase()}]`.padEnd(9));
77
80
  // Convert message to string
78
- const messageStr = String(message);
81
+ const messageStr = String(message ?? '');
79
82
  // Detect category and apply appropriate color to message
80
83
  const categoryColor = getCategoryColor(messageStr);
81
84
  let msg = categoryColor(messageStr);
@@ -151,20 +154,29 @@ const customFormat = winston_1.default.format.printf(({ level, message, timestam
151
154
  }
152
155
  return `${time} ${levelStr} ${msg}${metaStr}`;
153
156
  });
154
- // Create logger instance
155
- const logger = winston_1.default.createLogger({
156
- level: logLevel,
157
- format: winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), customFormat),
158
- transports: [
159
- // Console transport with colors
160
- new winston_1.default.transports.Console({
157
+ // When LOG_PACKAGE=http, only allow logs that look like HTTP requests
158
+ const isHttpLog = (info) => {
159
+ const msg = String(info.message ?? '');
160
+ return /^(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\s+/i.test(msg) || msg.includes(' ') || msg.includes(' ');
161
+ };
162
+ const transports = [];
163
+ if (logEnabled) {
164
+ if (logPackage === 'http') {
165
+ transports.push(new winston_1.default.transports.Console({
166
+ format: winston_1.default.format.combine(winston_1.default.format((info) => (isHttpLog(info) ? info : false))(), customFormat),
167
+ }));
168
+ }
169
+ else {
170
+ transports.push(new winston_1.default.transports.Console({
161
171
  format: winston_1.default.format.combine(customFormat),
162
- }),
163
- // File transport for all logs (without colors)
164
- new winston_1.default.transports.File({
172
+ }));
173
+ }
174
+ if (logDir) {
175
+ transports.push(new winston_1.default.transports.File({
165
176
  filename: path_1.default.join(logDir, 'combined.log'),
166
- format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.printf(({ level, message, timestamp, ...metadata }) => {
167
- let msg = `${timestamp} [${level.toUpperCase()}] ${message}`;
177
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.printf((info) => {
178
+ const { level, message, timestamp, ...metadata } = info;
179
+ let msg = `${timestamp} [${String(level).toUpperCase()}] ${message}`;
168
180
  if (Object.keys(metadata).length > 0) {
169
181
  msg += ` | ${JSON.stringify(metadata, (key, val) => {
170
182
  if (key === 'socket' || key === 'parser' || key === 'res' || key === 'req') {
@@ -175,13 +187,12 @@ const logger = winston_1.default.createLogger({
175
187
  }
176
188
  return msg;
177
189
  })),
178
- }),
179
- // File transport for errors only (without colors)
180
- new winston_1.default.transports.File({
190
+ }), new winston_1.default.transports.File({
181
191
  filename: path_1.default.join(logDir, 'error.log'),
182
192
  level: 'error',
183
- format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.printf(({ level, message, timestamp, ...metadata }) => {
184
- let msg = `${timestamp} [${level.toUpperCase()}] ${message}`;
193
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.printf((info) => {
194
+ const { level, message, timestamp, ...metadata } = info;
195
+ let msg = `${timestamp} [${String(level).toUpperCase()}] ${message}`;
185
196
  if (Object.keys(metadata).length > 0) {
186
197
  msg += ` | ${JSON.stringify(metadata, (key, val) => {
187
198
  if (key === 'socket' || key === 'parser' || key === 'res' || key === 'req') {
@@ -192,8 +203,17 @@ const logger = winston_1.default.createLogger({
192
203
  }
193
204
  return msg;
194
205
  })),
195
- }),
196
- ],
206
+ }));
207
+ }
208
+ }
209
+ else {
210
+ transports.push(new winston_1.default.transports.Console({ silent: true }));
211
+ }
212
+ // Create logger instance
213
+ const logger = winston_1.default.createLogger({
214
+ level: logLevel,
215
+ format: winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), customFormat),
216
+ transports,
197
217
  });
198
218
  // Log application info when starting
199
219
  const appInfo = {
@@ -206,6 +226,9 @@ logger.info(chalk_1.default.cyan.bold('Application started'), appInfo);
206
226
  const requestLogger = (req, res, next) => {
207
227
  const start = Date.now();
208
228
  res.on('finish', () => {
229
+ const pathname = (req.url ?? '').split('?')[0];
230
+ if (pathname === '/favicon.ico')
231
+ return;
209
232
  const duration = Date.now() - start;
210
233
  const statusColor = res.statusCode >= 500
211
234
  ? chalk_1.default.red
@@ -216,11 +239,11 @@ const requestLogger = (req, res, next) => {
216
239
  : res.statusCode >= 200
217
240
  ? chalk_1.default.green
218
241
  : chalk_1.default.white;
219
- logger.info(`${chalk_1.default.bold(req.method)} ${req.url}`, {
220
- status: statusColor(res.statusCode),
242
+ logger.info(`${chalk_1.default.bold(req.method ?? '')} ${req.url ?? ''}`, {
243
+ status: statusColor(String(res.statusCode)),
221
244
  duration: chalk_1.default.yellow(`${duration}ms`),
222
- userAgent: chalk_1.default.gray(req.headers['user-agent']),
223
- ip: chalk_1.default.gray(req.socket.remoteAddress),
245
+ userAgent: chalk_1.default.gray(String(req.headers['user-agent'] ?? '')),
246
+ ip: chalk_1.default.gray(String(req.socket.remoteAddress ?? '')),
224
247
  });
225
248
  });
226
249
  next();
@@ -13,5 +13,10 @@ export interface RequestContext {
13
13
  role: string;
14
14
  [key: string]: unknown;
15
15
  };
16
+ retryOptions?: {
17
+ count: number;
18
+ delay?: number;
19
+ retryIf?: (err: Error) => boolean;
20
+ };
16
21
  }
17
22
  //# sourceMappingURL=request-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../src/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../src/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,OAAO,CAAA;KAAE,CAAC;CACrF"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMxC,OAAO,kBAAkB,CAAC;AAY1B,UAAU,UAAU;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,KAAK,YAAY,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;AAEpF,qBAAa,MAAM;IAKL,OAAO,CAAC,SAAS;IAJ7B,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,cAAc,CAAuD;IAC7E,OAAO,CAAC,iBAAiB,CAAoB;gBAEzB,SAAS,EAAE,SAAS;IAUxC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI;YA4DrC,UAAU;YAsBV,iBAAiB;IAe/B,OAAO,CAAC,kBAAkB;IAqQ1B,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,aAAa;IAOf,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0C7F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIjD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIlD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIjD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIpD,OAAO,CAAC,QAAQ;IAKV,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAkChE"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMxC,OAAO,kBAAkB,CAAC;AAc1B,UAAU,UAAU;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,KAAK,YAAY,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;AAEpF,qBAAa,MAAM;IAKL,OAAO,CAAC,SAAS;IAJ7B,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,cAAc,CAAuD;IAC7E,OAAO,CAAC,iBAAiB,CAAoB;gBAEzB,SAAS,EAAE,SAAS;IAUxC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI;YA4DrC,UAAU;YAsBV,iBAAiB;IAe/B,OAAO,CAAC,kBAAkB;IAgT1B,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,aAAa;IAOf,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0C7F,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIjD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIlD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIjD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI;IAIpD,OAAO,CAAC,QAAQ;IAKV,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAkChE"}