@zerooneit/expressive-tea 1.3.0-beta.5 → 2.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 (77) hide show
  1. package/.gitattributes +4 -0
  2. package/.swcrc +61 -0
  3. package/README.md +564 -174
  4. package/classes/Boot.d.ts +94 -3
  5. package/classes/Boot.js +171 -51
  6. package/classes/Engine.d.ts +59 -10
  7. package/classes/Engine.js +72 -11
  8. package/classes/EngineRegistry.d.ts +154 -0
  9. package/classes/EngineRegistry.js +247 -0
  10. package/classes/LoadBalancer.js +2 -5
  11. package/classes/ProxyRoute.d.ts +3 -3
  12. package/classes/ProxyRoute.js +5 -5
  13. package/classes/Settings.d.ts +31 -2
  14. package/classes/Settings.js +64 -11
  15. package/decorators/annotations.d.ts +1 -1
  16. package/decorators/annotations.js +17 -17
  17. package/decorators/env.d.ts +145 -0
  18. package/decorators/env.js +177 -0
  19. package/decorators/health.d.ts +115 -0
  20. package/decorators/health.js +124 -0
  21. package/decorators/module.d.ts +15 -15
  22. package/decorators/module.js +14 -23
  23. package/decorators/proxy.d.ts +26 -11
  24. package/decorators/proxy.js +35 -45
  25. package/decorators/router.d.ts +17 -16
  26. package/decorators/router.js +32 -52
  27. package/decorators/server.d.ts +8 -8
  28. package/decorators/server.js +48 -50
  29. package/engines/health/index.d.ts +120 -0
  30. package/engines/health/index.js +179 -0
  31. package/engines/http/index.d.ts +6 -7
  32. package/engines/http/index.js +22 -17
  33. package/engines/index.d.ts +32 -0
  34. package/engines/index.js +112 -0
  35. package/engines/socketio/index.d.ts +2 -1
  36. package/engines/socketio/index.js +16 -6
  37. package/engines/teacup/index.d.ts +13 -0
  38. package/engines/teacup/index.js +61 -11
  39. package/engines/teapot/index.d.ts +15 -2
  40. package/engines/teapot/index.js +61 -13
  41. package/engines/websocket/index.d.ts +4 -1
  42. package/engines/websocket/index.js +10 -2
  43. package/eslint.config.mjs +138 -0
  44. package/exceptions/RequestExceptions.d.ts +3 -3
  45. package/helpers/boot-helper.d.ts +6 -6
  46. package/helpers/boot-helper.js +30 -24
  47. package/helpers/decorators.js +7 -6
  48. package/helpers/promise-helper.d.ts +1 -1
  49. package/helpers/promise-helper.js +1 -2
  50. package/helpers/server.d.ts +32 -6
  51. package/helpers/server.js +101 -61
  52. package/helpers/teapot-helper.d.ts +5 -8
  53. package/helpers/teapot-helper.js +39 -11
  54. package/helpers/websocket-helper.d.ts +3 -5
  55. package/helpers/websocket-helper.js +3 -3
  56. package/interfaces/index.d.ts +1 -1
  57. package/inversify.config.d.ts +4 -4
  58. package/inversify.config.js +1 -1
  59. package/libs/utilities.d.ts +21910 -0
  60. package/libs/utilities.js +420 -0
  61. package/mixins/module.d.ts +45 -0
  62. package/mixins/module.js +71 -0
  63. package/mixins/proxy.d.ts +46 -0
  64. package/mixins/proxy.js +86 -0
  65. package/mixins/route.d.ts +48 -0
  66. package/mixins/route.js +96 -0
  67. package/package.json +91 -69
  68. package/services/DependencyInjection.d.ts +95 -7
  69. package/services/DependencyInjection.js +123 -5
  70. package/services/WebsocketService.d.ts +4 -6
  71. package/services/WebsocketService.js +5 -3
  72. package/types/core.d.ts +14 -0
  73. package/types/core.js +2 -0
  74. package/types/injection-types.d.ts +6 -0
  75. package/types/injection-types.js +10 -0
  76. package/types/inversify.d.ts +5 -0
  77. package/types/inversify.js +3 -0
@@ -1,20 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.param = exports.body = exports.query = exports.next = exports.response = exports.request = void 0;
4
- const Metadata_1 = require("@expressive-tea/commons/classes/Metadata");
5
- const constants_1 = require("@expressive-tea/commons/constants");
3
+ exports.request = request;
4
+ exports.response = response;
5
+ exports.next = next;
6
+ exports.query = query;
7
+ exports.body = body;
8
+ exports.param = param;
9
+ const commons_1 = require("@expressive-tea/commons");
10
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
11
+ const commons_2 = require("@expressive-tea/commons");
6
12
  /**
7
13
  * @module Decorators/Annotations
8
14
  */
9
15
  function addToArguments(target, propertyKey, parameterIndex, type, args) {
10
- const decoratedParameters = Metadata_1.default.get(constants_1.ARGUMENTS_KEY, target, propertyKey) || [];
16
+ const decoratedParameters = commons_1.Metadata.get(commons_2.ARGUMENTS_KEY, target, propertyKey) || [];
11
17
  decoratedParameters.unshift({
12
18
  arguments: args,
13
19
  index: parameterIndex,
14
20
  key: propertyKey,
15
21
  type
16
22
  });
17
- Metadata_1.default.set(constants_1.ARGUMENTS_KEY, decoratedParameters, target, propertyKey);
23
+ commons_1.Metadata.set(commons_2.ARGUMENTS_KEY, decoratedParameters, target, propertyKey);
18
24
  }
19
25
  /**
20
26
  * Is passing directly to the decorated argument described <a href="http://expressjs.com/en/4x/api.html#req">here</a>.
@@ -28,9 +34,8 @@ function addToArguments(target, propertyKey, parameterIndex, type, args) {
28
34
  *
29
35
  */
30
36
  function request(target, propertyKey, parameterIndex) {
31
- addToArguments(target, propertyKey, parameterIndex, constants_1.ARGUMENT_TYPES.REQUEST);
37
+ addToArguments(target, propertyKey, parameterIndex, commons_2.ARGUMENT_TYPES.REQUEST);
32
38
  }
33
- exports.request = request;
34
39
  /**
35
40
  * Is passing directly to the decorated argument described <a href="http://expressjs.com/en/4x/api.html#res">here</a>.
36
41
  * @decorator {ParameterDecorator} response - Assign express Response instance to parameter.
@@ -43,9 +48,8 @@ exports.request = request;
43
48
  *
44
49
  */
45
50
  function response(target, propertyKey, parameterIndex) {
46
- addToArguments(target, propertyKey, parameterIndex, constants_1.ARGUMENT_TYPES.RESPONSE);
51
+ addToArguments(target, propertyKey, parameterIndex, commons_2.ARGUMENT_TYPES.RESPONSE);
47
52
  }
48
- exports.response = response;
49
53
  /**
50
54
  * Is passing directly to the decorated argument and you can check how is working following the next guide
51
55
  * <a href="http://expressjs.com/en/guide/using-middleware.html">here</a>.
@@ -59,9 +63,8 @@ exports.response = response;
59
63
  *
60
64
  */
61
65
  function next(target, propertyKey, parameterIndex) {
62
- addToArguments(target, propertyKey, parameterIndex, constants_1.ARGUMENT_TYPES.NEXT);
66
+ addToArguments(target, propertyKey, parameterIndex, commons_2.ARGUMENT_TYPES.NEXT);
63
67
  }
64
- exports.next = next;
65
68
  /**
66
69
  * It will pass a get query parameters which it must be defined on the query parameters string unless it will get a
67
70
  * undefined result. This decorator provides the way to return query parameters in one of the next ways: <br>
@@ -82,10 +85,9 @@ exports.next = next;
82
85
  */
83
86
  function query(parameter) {
84
87
  return (target, propertyKey, parameterIndex) => {
85
- addToArguments(target, propertyKey, parameterIndex, constants_1.ARGUMENT_TYPES.QUERY, parameter);
88
+ addToArguments(target, propertyKey, parameterIndex, commons_2.ARGUMENT_TYPES.QUERY, parameter);
86
89
  };
87
90
  }
88
- exports.query = query;
89
91
  /**
90
92
  * It will pass a get body parameters which it must be defined on the request body, unless it will get a
91
93
  * undefined result. This decorator provides the way to return body parameters in one of the next ways: <br>
@@ -106,10 +108,9 @@ exports.query = query;
106
108
  */
107
109
  function body(bodyParam) {
108
110
  return (target, propertyKey, parameterIndex) => {
109
- addToArguments(target, propertyKey, parameterIndex, constants_1.ARGUMENT_TYPES.BODY, bodyParam);
111
+ addToArguments(target, propertyKey, parameterIndex, commons_2.ARGUMENT_TYPES.BODY, bodyParam);
110
112
  };
111
113
  }
112
- exports.body = body;
113
114
  /**
114
115
  * It will return the value defined on the url path for the current method or a global middleware, this only works
115
116
  * for single parameter, and also might be side affected if there is an any <b>param</b> decorator is declared for the
@@ -126,7 +127,6 @@ exports.body = body;
126
127
  */
127
128
  function param(parameter) {
128
129
  return (target, propertyKey, parameterIndex) => {
129
- addToArguments(target, propertyKey, parameterIndex, constants_1.ARGUMENT_TYPES.GET_PARAM, parameter);
130
+ addToArguments(target, propertyKey, parameterIndex, commons_2.ARGUMENT_TYPES.GET_PARAM, parameter);
130
131
  };
131
132
  }
132
- exports.param = param;
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Environment variable loading options with optional transformation
3
+ * @interface EnvOptions
4
+ * @template T - Type of transformed environment variables
5
+ * @since 2.0.0
6
+ */
7
+ export interface EnvOptions<T = Record<string, string>> {
8
+ /**
9
+ * Path to the .env file (relative to project root)
10
+ * @default '.env'
11
+ */
12
+ path?: string;
13
+ /**
14
+ * Whether to override existing environment variables
15
+ * @default false
16
+ */
17
+ override?: boolean;
18
+ /**
19
+ * List of required environment variables (will throw if missing)
20
+ */
21
+ required?: string[];
22
+ /**
23
+ * Whether to ignore missing .env file
24
+ * @default false
25
+ */
26
+ silent?: boolean;
27
+ /**
28
+ * Optional transformation function for type-safe environment variables.
29
+ * Receives parsed env vars and returns transformed result.
30
+ * Use with validation libraries like Zod for runtime type safety.
31
+ *
32
+ * @param env - Parsed environment variables
33
+ * @returns Transformed and validated environment variables
34
+ * @since 2.0.1
35
+ *
36
+ * @example
37
+ * import { z } from 'zod';
38
+ * const EnvSchema = z.object({
39
+ * PORT: z.string().transform(Number),
40
+ * DATABASE_URL: z.string().url()
41
+ * });
42
+ *
43
+ * @Env({
44
+ * transform: (env) => EnvSchema.parse(env),
45
+ * onTransformError: 'throw'
46
+ * })
47
+ */
48
+ transform?: (env: Record<string, string>) => T;
49
+ /**
50
+ * Behavior when transform function throws an error
51
+ * - 'throw': Re-throw error immediately (fail-fast, recommended for production)
52
+ * - 'warn': Log warning and continue with unvalidated env
53
+ * - 'ignore': Silent failure, continue without transform
54
+ *
55
+ * @default 'throw'
56
+ * @since 2.0.1
57
+ */
58
+ onTransformError?: 'throw' | 'warn' | 'ignore';
59
+ }
60
+ /**
61
+ * Retrieve transformed environment variables from global storage.
62
+ * Returns null if no transform was applied.
63
+ *
64
+ * @template T - Type of transformed environment variables
65
+ * @returns Transformed environment variables or null
66
+ * @since 2.0.1
67
+ *
68
+ * @example
69
+ * const env = getTransformedEnv<MyEnvType>();
70
+ * if (env) {
71
+ * console.log(env.PORT); // Type-safe access
72
+ * }
73
+ */
74
+ export declare function getTransformedEnv<T>(): T | null;
75
+ /**
76
+ * Class decorator to load environment variables from .env files before application initialization.
77
+ *
78
+ * This decorator can be stacked to load multiple .env files in order, allowing for
79
+ * environment-specific overrides (e.g., .env → .env.local → .env.production).
80
+ *
81
+ * Environment variables are loaded BEFORE the Settings singleton is initialized,
82
+ * ensuring they're available during the entire application lifecycle.
83
+ *
84
+ * **New in v2.0.1:** Optional type-safe transformation with validation libraries like Zod.
85
+ *
86
+ * @decorator {ClassDecorator} Env - Load environment variables from .env file
87
+ * @template T - Type of transformed environment variables
88
+ * @param options - Environment loading options
89
+ * @returns Class decorator function
90
+ * @since 2.0.0
91
+ * @summary Load environment variables from .env files with optional type-safe transformation
92
+ *
93
+ * @example
94
+ * // Basic usage - load from .env
95
+ * @Env()
96
+ * class MyApp extends Boot {}
97
+ *
98
+ * @example
99
+ * // Load from custom path with required variables
100
+ * @Env({
101
+ * path: '.env.production',
102
+ * required: ['DATABASE_URL', 'API_KEY']
103
+ * })
104
+ * class MyApp extends Boot {}
105
+ *
106
+ * @example
107
+ * // Stack multiple .env files (loaded in order)
108
+ * @Env({ path: '.env' })
109
+ * @Env({ path: '.env.local', override: true, silent: true })
110
+ * class MyApp extends Boot {}
111
+ *
112
+ * @example
113
+ * // Type-safe transformation with Zod
114
+ * import { z } from 'zod';
115
+ *
116
+ * const EnvSchema = z.object({
117
+ * PORT: z.string().transform(Number),
118
+ * DATABASE_URL: z.string().url(),
119
+ * API_KEY: z.string().min(32)
120
+ * });
121
+ *
122
+ * type Env = z.infer<typeof EnvSchema>;
123
+ *
124
+ * @Env<Env>({
125
+ * path: '.env',
126
+ * required: ['DATABASE_URL', 'API_KEY'],
127
+ * transform: (env) => EnvSchema.parse(env),
128
+ * onTransformError: 'throw' // Fail fast on invalid env
129
+ * })
130
+ * class MyApp extends Boot {
131
+ * constructor() {
132
+ * super();
133
+ * // Access type-safe env
134
+ * const env = Settings.getInstance().getEnv<Env>();
135
+ * console.log(env.PORT); // Type: number
136
+ * }
137
+ * }
138
+ *
139
+ * @example
140
+ * // In your .env file:
141
+ * // DATABASE_URL=postgres://localhost:5432/mydb
142
+ * // API_KEY="secret-key-with-special-chars"
143
+ * // PORT=3000
144
+ */
145
+ export declare function Env<T = Record<string, string>>(options?: EnvOptions<T>): ClassDecorator;
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTransformedEnv = getTransformedEnv;
4
+ exports.Env = Env;
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const dotenv = require("dotenv");
8
+ /**
9
+ * Global storage for transformed environment variables.
10
+ * Set by @Env decorator when transform option is provided.
11
+ * @private
12
+ */
13
+ let transformedEnv = null;
14
+ /**
15
+ * Store transformed environment variables in global storage.
16
+ * Used internally by @Env decorator.
17
+ *
18
+ * @template T - Type of transformed environment variables
19
+ * @param env - Transformed environment variables
20
+ * @private
21
+ * @since 2.0.1
22
+ */
23
+ function storeTransformedEnv(env) {
24
+ transformedEnv = env;
25
+ }
26
+ /**
27
+ * Retrieve transformed environment variables from global storage.
28
+ * Returns null if no transform was applied.
29
+ *
30
+ * @template T - Type of transformed environment variables
31
+ * @returns Transformed environment variables or null
32
+ * @since 2.0.1
33
+ *
34
+ * @example
35
+ * const env = getTransformedEnv<MyEnvType>();
36
+ * if (env) {
37
+ * console.log(env.PORT); // Type-safe access
38
+ * }
39
+ */
40
+ function getTransformedEnv() {
41
+ return transformedEnv;
42
+ }
43
+ /**
44
+ * Load environment variables from a .env file using dotenv.
45
+ * Supports transformation and validation via optional transform function.
46
+ *
47
+ * @template T - Type of transformed environment variables
48
+ * @param options - Environment loading options
49
+ * @throws {Error} If required variables are missing, file is not found (when not silent), or transform fails (when onTransformError='throw')
50
+ * @since 2.0.0
51
+ * @private
52
+ */
53
+ function loadEnvFile(options) {
54
+ const { path: envPath = '.env', override = false, required = [], silent = false, transform, onTransformError = 'throw' } = options;
55
+ const fullPath = (0, path_1.resolve)(process.cwd(), envPath);
56
+ // Check if file exists
57
+ if (!(0, fs_1.existsSync)(fullPath)) {
58
+ if (!silent) {
59
+ throw new Error(`Environment file not found: ${fullPath}`);
60
+ }
61
+ return undefined;
62
+ }
63
+ // Load with dotenv
64
+ const result = dotenv.config({
65
+ path: fullPath,
66
+ override
67
+ });
68
+ if (result.error && !silent) {
69
+ throw new Error(`Failed to load ${fullPath}: ${result.error.message}`);
70
+ }
71
+ // Validate required variables
72
+ const missing = required.filter((key) => process.env[key] === undefined);
73
+ if (missing.length > 0) {
74
+ throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
75
+ }
76
+ // Apply transform if provided
77
+ if (transform) {
78
+ try {
79
+ const envVars = result.parsed || {};
80
+ const transformed = transform(envVars);
81
+ // Store transformed result globally
82
+ storeTransformedEnv(transformed);
83
+ return transformed;
84
+ }
85
+ catch (error) {
86
+ const errorMsg = `Environment transformation failed: ${error.message}`;
87
+ if (onTransformError === 'throw') {
88
+ throw new Error(errorMsg);
89
+ }
90
+ else if (onTransformError === 'warn') {
91
+ console.warn(`[Expressive Tea] ${errorMsg}`);
92
+ if (error.stack) {
93
+ console.warn(error.stack);
94
+ }
95
+ }
96
+ // 'ignore' - do nothing, return undefined
97
+ }
98
+ }
99
+ return undefined;
100
+ }
101
+ /**
102
+ * Class decorator to load environment variables from .env files before application initialization.
103
+ *
104
+ * This decorator can be stacked to load multiple .env files in order, allowing for
105
+ * environment-specific overrides (e.g., .env → .env.local → .env.production).
106
+ *
107
+ * Environment variables are loaded BEFORE the Settings singleton is initialized,
108
+ * ensuring they're available during the entire application lifecycle.
109
+ *
110
+ * **New in v2.0.1:** Optional type-safe transformation with validation libraries like Zod.
111
+ *
112
+ * @decorator {ClassDecorator} Env - Load environment variables from .env file
113
+ * @template T - Type of transformed environment variables
114
+ * @param options - Environment loading options
115
+ * @returns Class decorator function
116
+ * @since 2.0.0
117
+ * @summary Load environment variables from .env files with optional type-safe transformation
118
+ *
119
+ * @example
120
+ * // Basic usage - load from .env
121
+ * @Env()
122
+ * class MyApp extends Boot {}
123
+ *
124
+ * @example
125
+ * // Load from custom path with required variables
126
+ * @Env({
127
+ * path: '.env.production',
128
+ * required: ['DATABASE_URL', 'API_KEY']
129
+ * })
130
+ * class MyApp extends Boot {}
131
+ *
132
+ * @example
133
+ * // Stack multiple .env files (loaded in order)
134
+ * @Env({ path: '.env' })
135
+ * @Env({ path: '.env.local', override: true, silent: true })
136
+ * class MyApp extends Boot {}
137
+ *
138
+ * @example
139
+ * // Type-safe transformation with Zod
140
+ * import { z } from 'zod';
141
+ *
142
+ * const EnvSchema = z.object({
143
+ * PORT: z.string().transform(Number),
144
+ * DATABASE_URL: z.string().url(),
145
+ * API_KEY: z.string().min(32)
146
+ * });
147
+ *
148
+ * type Env = z.infer<typeof EnvSchema>;
149
+ *
150
+ * @Env<Env>({
151
+ * path: '.env',
152
+ * required: ['DATABASE_URL', 'API_KEY'],
153
+ * transform: (env) => EnvSchema.parse(env),
154
+ * onTransformError: 'throw' // Fail fast on invalid env
155
+ * })
156
+ * class MyApp extends Boot {
157
+ * constructor() {
158
+ * super();
159
+ * // Access type-safe env
160
+ * const env = Settings.getInstance().getEnv<Env>();
161
+ * console.log(env.PORT); // Type: number
162
+ * }
163
+ * }
164
+ *
165
+ * @example
166
+ * // In your .env file:
167
+ * // DATABASE_URL=postgres://localhost:5432/mydb
168
+ * // API_KEY="secret-key-with-special-chars"
169
+ * // PORT=3000
170
+ */
171
+ function Env(options = {}) {
172
+ return (target) => {
173
+ // Load env file immediately when decorator is applied
174
+ loadEnvFile(options);
175
+ return target;
176
+ };
177
+ }
@@ -0,0 +1,115 @@
1
+ import type { HealthCheck as HealthCheckConfig } from '../engines/health';
2
+ /**
3
+ * Health check decorator options
4
+ * @since 2.0.0
5
+ */
6
+ export interface HealthCheckOptions {
7
+ /** Array of health checks to register */
8
+ checks: HealthCheckConfig[];
9
+ }
10
+ /**
11
+ * Class decorator to register health checks for monitoring and orchestration.
12
+ *
13
+ * Adds standardized health check endpoints:
14
+ * - `/health` - Detailed health status with all checks
15
+ * - `/health/live` - Liveness probe (Kubernetes compatible)
16
+ * - `/health/ready` - Readiness probe (only passes if all critical checks pass)
17
+ *
18
+ * Health checks are executed asynchronously and can be marked as critical for readiness.
19
+ * Non-critical checks only affect the detailed `/health` endpoint.
20
+ *
21
+ * @decorator {ClassDecorator} HealthCheck - Register health checks
22
+ * @param options - Health check configuration
23
+ * @returns Class decorator function
24
+ * @since 2.0.0
25
+ * @summary Register application health checks for monitoring
26
+ *
27
+ * @example
28
+ * // Basic health check
29
+ * @HealthCheck({
30
+ * checks: [
31
+ * {
32
+ * name: 'database',
33
+ * check: async () => {
34
+ * const isConnected = await db.ping();
35
+ * return { status: isConnected ? 'pass' : 'fail' };
36
+ * },
37
+ * critical: true,
38
+ * timeout: 5000
39
+ * }
40
+ * ]
41
+ * })
42
+ * class MyApp extends Boot {}
43
+ *
44
+ * @example
45
+ * // Multiple health checks with different priorities
46
+ * @HealthCheck({
47
+ * checks: [
48
+ * {
49
+ * name: 'database',
50
+ * check: async () => {
51
+ * const connected = await db.ping();
52
+ * return {
53
+ * status: connected ? 'pass' : 'fail',
54
+ * details: { connections: db.poolSize }
55
+ * };
56
+ * },
57
+ * critical: true // Required for readiness
58
+ * },
59
+ * {
60
+ * name: 'cache',
61
+ * check: async () => {
62
+ * const ready = await redis.ping();
63
+ * return {
64
+ * status: ready ? 'pass' : 'warn', // Warn but don't fail
65
+ * details: { cached_items: await redis.dbsize() }
66
+ * };
67
+ * },
68
+ * critical: false // Optional, won't block readiness
69
+ * },
70
+ * {
71
+ * name: 'external_api',
72
+ * check: async () => {
73
+ * try {
74
+ * const response = await fetch('https://api.example.com/status');
75
+ * return { status: response.ok ? 'pass' : 'warn' };
76
+ * } catch (error) {
77
+ * return {
78
+ * status: 'warn',
79
+ * error: error.message
80
+ * };
81
+ * }
82
+ * },
83
+ * timeout: 3000
84
+ * }
85
+ * ]
86
+ * })
87
+ * class MyApp extends Boot {}
88
+ *
89
+ * @example
90
+ * // Kubernetes deployment.yaml example
91
+ * // spec:
92
+ * // containers:
93
+ * // - name: my-app
94
+ * // livenessProbe:
95
+ * // httpGet:
96
+ * // path: /health/live
97
+ * // port: 3000
98
+ * // initialDelaySeconds: 30
99
+ * // periodSeconds: 10
100
+ * // readinessProbe:
101
+ * // httpGet:
102
+ * // path: /health/ready
103
+ * // port: 3000
104
+ * // initialDelaySeconds: 5
105
+ * // periodSeconds: 5
106
+ */
107
+ export declare function HealthCheck(options: HealthCheckOptions): ClassDecorator;
108
+ /**
109
+ * Get health checks from a class
110
+ * @param target - Target class
111
+ * @returns Array of health checks
112
+ * @since 2.0.0
113
+ * @internal
114
+ */
115
+ export declare function getHealthChecks(target: any): HealthCheckConfig[];
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HealthCheck = HealthCheck;
4
+ exports.getHealthChecks = getHealthChecks;
5
+ const commons_1 = require("@expressive-tea/commons");
6
+ /**
7
+ * Health check decorator metadata key
8
+ * @private
9
+ */
10
+ const HEALTH_CHECKS_KEY = 'expressive-tea:health-checks';
11
+ /**
12
+ * Class decorator to register health checks for monitoring and orchestration.
13
+ *
14
+ * Adds standardized health check endpoints:
15
+ * - `/health` - Detailed health status with all checks
16
+ * - `/health/live` - Liveness probe (Kubernetes compatible)
17
+ * - `/health/ready` - Readiness probe (only passes if all critical checks pass)
18
+ *
19
+ * Health checks are executed asynchronously and can be marked as critical for readiness.
20
+ * Non-critical checks only affect the detailed `/health` endpoint.
21
+ *
22
+ * @decorator {ClassDecorator} HealthCheck - Register health checks
23
+ * @param options - Health check configuration
24
+ * @returns Class decorator function
25
+ * @since 2.0.0
26
+ * @summary Register application health checks for monitoring
27
+ *
28
+ * @example
29
+ * // Basic health check
30
+ * @HealthCheck({
31
+ * checks: [
32
+ * {
33
+ * name: 'database',
34
+ * check: async () => {
35
+ * const isConnected = await db.ping();
36
+ * return { status: isConnected ? 'pass' : 'fail' };
37
+ * },
38
+ * critical: true,
39
+ * timeout: 5000
40
+ * }
41
+ * ]
42
+ * })
43
+ * class MyApp extends Boot {}
44
+ *
45
+ * @example
46
+ * // Multiple health checks with different priorities
47
+ * @HealthCheck({
48
+ * checks: [
49
+ * {
50
+ * name: 'database',
51
+ * check: async () => {
52
+ * const connected = await db.ping();
53
+ * return {
54
+ * status: connected ? 'pass' : 'fail',
55
+ * details: { connections: db.poolSize }
56
+ * };
57
+ * },
58
+ * critical: true // Required for readiness
59
+ * },
60
+ * {
61
+ * name: 'cache',
62
+ * check: async () => {
63
+ * const ready = await redis.ping();
64
+ * return {
65
+ * status: ready ? 'pass' : 'warn', // Warn but don't fail
66
+ * details: { cached_items: await redis.dbsize() }
67
+ * };
68
+ * },
69
+ * critical: false // Optional, won't block readiness
70
+ * },
71
+ * {
72
+ * name: 'external_api',
73
+ * check: async () => {
74
+ * try {
75
+ * const response = await fetch('https://api.example.com/status');
76
+ * return { status: response.ok ? 'pass' : 'warn' };
77
+ * } catch (error) {
78
+ * return {
79
+ * status: 'warn',
80
+ * error: error.message
81
+ * };
82
+ * }
83
+ * },
84
+ * timeout: 3000
85
+ * }
86
+ * ]
87
+ * })
88
+ * class MyApp extends Boot {}
89
+ *
90
+ * @example
91
+ * // Kubernetes deployment.yaml example
92
+ * // spec:
93
+ * // containers:
94
+ * // - name: my-app
95
+ * // livenessProbe:
96
+ * // httpGet:
97
+ * // path: /health/live
98
+ * // port: 3000
99
+ * // initialDelaySeconds: 30
100
+ * // periodSeconds: 10
101
+ * // readinessProbe:
102
+ * // httpGet:
103
+ * // path: /health/ready
104
+ * // port: 3000
105
+ * // initialDelaySeconds: 5
106
+ * // periodSeconds: 5
107
+ */
108
+ function HealthCheck(options) {
109
+ return (target) => {
110
+ // Store health checks in metadata
111
+ commons_1.Metadata.set(HEALTH_CHECKS_KEY, options.checks, target);
112
+ return target;
113
+ };
114
+ }
115
+ /**
116
+ * Get health checks from a class
117
+ * @param target - Target class
118
+ * @returns Array of health checks
119
+ * @since 2.0.0
120
+ * @internal
121
+ */
122
+ function getHealthChecks(target) {
123
+ return commons_1.Metadata.get(HEALTH_CHECKS_KEY, target) || [];
124
+ }