@hazeljs/discovery 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +192 -0
- package/README.md +450 -0
- package/dist/__tests__/consul-backend.test.d.ts +6 -0
- package/dist/__tests__/consul-backend.test.d.ts.map +1 -0
- package/dist/__tests__/consul-backend.test.js +300 -0
- package/dist/__tests__/decorators.test.d.ts +5 -0
- package/dist/__tests__/decorators.test.d.ts.map +1 -0
- package/dist/__tests__/decorators.test.js +72 -0
- package/dist/__tests__/discovery-client.test.d.ts +5 -0
- package/dist/__tests__/discovery-client.test.d.ts.map +1 -0
- package/dist/__tests__/discovery-client.test.js +142 -0
- package/dist/__tests__/kubernetes-backend.test.d.ts +6 -0
- package/dist/__tests__/kubernetes-backend.test.d.ts.map +1 -0
- package/dist/__tests__/kubernetes-backend.test.js +261 -0
- package/dist/__tests__/load-balancer-strategies.test.d.ts +5 -0
- package/dist/__tests__/load-balancer-strategies.test.d.ts.map +1 -0
- package/dist/__tests__/load-balancer-strategies.test.js +234 -0
- package/dist/__tests__/memory-backend.test.d.ts +5 -0
- package/dist/__tests__/memory-backend.test.d.ts.map +1 -0
- package/dist/__tests__/memory-backend.test.js +246 -0
- package/dist/__tests__/redis-backend.test.d.ts +6 -0
- package/dist/__tests__/redis-backend.test.d.ts.map +1 -0
- package/dist/__tests__/redis-backend.test.js +280 -0
- package/dist/__tests__/service-client.test.d.ts +5 -0
- package/dist/__tests__/service-client.test.d.ts.map +1 -0
- package/dist/__tests__/service-client.test.js +216 -0
- package/dist/__tests__/service-registry.test.d.ts +5 -0
- package/dist/__tests__/service-registry.test.d.ts.map +1 -0
- package/dist/__tests__/service-registry.test.js +65 -0
- package/dist/backends/consul-backend.d.ts +115 -0
- package/dist/backends/consul-backend.d.ts.map +1 -0
- package/dist/backends/consul-backend.js +259 -0
- package/dist/backends/kubernetes-backend.d.ts +103 -0
- package/dist/backends/kubernetes-backend.d.ts.map +1 -0
- package/dist/backends/kubernetes-backend.js +153 -0
- package/dist/backends/memory-backend.d.ts +21 -0
- package/dist/backends/memory-backend.d.ts.map +1 -0
- package/dist/backends/memory-backend.js +86 -0
- package/dist/backends/redis-backend.d.ts +76 -0
- package/dist/backends/redis-backend.d.ts.map +1 -0
- package/dist/backends/redis-backend.js +220 -0
- package/dist/backends/registry-backend.d.ts +39 -0
- package/dist/backends/registry-backend.d.ts.map +1 -0
- package/dist/backends/registry-backend.js +5 -0
- package/dist/client/discovery-client.d.ts +49 -0
- package/dist/client/discovery-client.d.ts.map +1 -0
- package/dist/client/discovery-client.js +123 -0
- package/dist/client/service-client.d.ts +48 -0
- package/dist/client/service-client.d.ts.map +1 -0
- package/dist/client/service-client.js +155 -0
- package/dist/decorators/inject-service-client.decorator.d.ts +16 -0
- package/dist/decorators/inject-service-client.decorator.d.ts.map +1 -0
- package/dist/decorators/inject-service-client.decorator.js +24 -0
- package/dist/decorators/service-registry.decorator.d.ts +11 -0
- package/dist/decorators/service-registry.decorator.d.ts.map +1 -0
- package/dist/decorators/service-registry.decorator.js +20 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/load-balancer/strategies.d.ts +82 -0
- package/dist/load-balancer/strategies.d.ts.map +1 -0
- package/dist/load-balancer/strategies.js +209 -0
- package/dist/registry/service-registry.d.ts +51 -0
- package/dist/registry/service-registry.d.ts.map +1 -0
- package/dist/registry/service-registry.js +159 -0
- package/dist/types/index.d.ts +61 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -0
- package/dist/utils/filter.d.ts +10 -0
- package/dist/utils/filter.d.ts.map +1 -0
- package/dist/utils/filter.js +39 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +34 -0
- package/dist/utils/validation.d.ts +36 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +109 -0
- package/package.json +81 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pluggable logger for @hazeljs/discovery
|
|
4
|
+
*
|
|
5
|
+
* Consumers can supply their own logger via DiscoveryLogger.setLogger().
|
|
6
|
+
* The default logger writes to the console.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DiscoveryLogger = void 0;
|
|
10
|
+
const defaultLogger = {
|
|
11
|
+
// eslint-disable-next-line no-console
|
|
12
|
+
debug: (msg, ...args) => console.debug(`[discovery] ${msg}`, ...args),
|
|
13
|
+
// eslint-disable-next-line no-console
|
|
14
|
+
info: (msg, ...args) => console.info(`[discovery] ${msg}`, ...args),
|
|
15
|
+
// eslint-disable-next-line no-console
|
|
16
|
+
warn: (msg, ...args) => console.warn(`[discovery] ${msg}`, ...args),
|
|
17
|
+
// eslint-disable-next-line no-console
|
|
18
|
+
error: (msg, ...args) => console.error(`[discovery] ${msg}`, ...args),
|
|
19
|
+
};
|
|
20
|
+
let currentLogger = defaultLogger;
|
|
21
|
+
exports.DiscoveryLogger = {
|
|
22
|
+
/** Replace the default console logger with a custom implementation */
|
|
23
|
+
setLogger(logger) {
|
|
24
|
+
currentLogger = logger;
|
|
25
|
+
},
|
|
26
|
+
/** Reset to the default console logger */
|
|
27
|
+
resetLogger() {
|
|
28
|
+
currentLogger = defaultLogger;
|
|
29
|
+
},
|
|
30
|
+
/** Get the current logger instance */
|
|
31
|
+
getLogger() {
|
|
32
|
+
return currentLogger;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation utilities for discovery configuration objects
|
|
3
|
+
*/
|
|
4
|
+
import { ServiceRegistryConfig, DiscoveryClientConfig } from '../types';
|
|
5
|
+
import { RedisBackendConfig } from '../backends/redis-backend';
|
|
6
|
+
import { ConsulBackendConfig } from '../backends/consul-backend';
|
|
7
|
+
import { KubernetesBackendConfig } from '../backends/kubernetes-backend';
|
|
8
|
+
import { ServiceClientConfig } from '../client/service-client';
|
|
9
|
+
export declare class ConfigValidationError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validate ServiceRegistryConfig at runtime
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateServiceRegistryConfig(config: ServiceRegistryConfig): void;
|
|
16
|
+
/**
|
|
17
|
+
* Validate DiscoveryClientConfig at runtime
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateDiscoveryClientConfig(config: DiscoveryClientConfig): void;
|
|
20
|
+
/**
|
|
21
|
+
* Validate ServiceClientConfig at runtime
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateServiceClientConfig(config: ServiceClientConfig): void;
|
|
24
|
+
/**
|
|
25
|
+
* Validate RedisBackendConfig at runtime
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateRedisBackendConfig(config: RedisBackendConfig): void;
|
|
28
|
+
/**
|
|
29
|
+
* Validate ConsulBackendConfig at runtime
|
|
30
|
+
*/
|
|
31
|
+
export declare function validateConsulBackendConfig(config: ConsulBackendConfig): void;
|
|
32
|
+
/**
|
|
33
|
+
* Validate KubernetesBackendConfig at runtime
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateKubernetesBackendConfig(config: KubernetesBackendConfig): void;
|
|
36
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAgCjF;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAejF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAkC7E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAe3E;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAkB7E;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CASrF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Runtime validation utilities for discovery configuration objects
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConfigValidationError = void 0;
|
|
7
|
+
exports.validateServiceRegistryConfig = validateServiceRegistryConfig;
|
|
8
|
+
exports.validateDiscoveryClientConfig = validateDiscoveryClientConfig;
|
|
9
|
+
exports.validateServiceClientConfig = validateServiceClientConfig;
|
|
10
|
+
exports.validateRedisBackendConfig = validateRedisBackendConfig;
|
|
11
|
+
exports.validateConsulBackendConfig = validateConsulBackendConfig;
|
|
12
|
+
exports.validateKubernetesBackendConfig = validateKubernetesBackendConfig;
|
|
13
|
+
class ConfigValidationError extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'ConfigValidationError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.ConfigValidationError = ConfigValidationError;
|
|
20
|
+
/**
|
|
21
|
+
* Validate ServiceRegistryConfig at runtime
|
|
22
|
+
*/
|
|
23
|
+
function validateServiceRegistryConfig(config) {
|
|
24
|
+
if (!config.name || typeof config.name !== 'string' || config.name.trim().length === 0) {
|
|
25
|
+
throw new ConfigValidationError('ServiceRegistryConfig: "name" is required and must be a non-empty string');
|
|
26
|
+
}
|
|
27
|
+
if (config.port == null ||
|
|
28
|
+
typeof config.port !== 'number' ||
|
|
29
|
+
config.port < 0 ||
|
|
30
|
+
config.port > 65535) {
|
|
31
|
+
throw new ConfigValidationError('ServiceRegistryConfig: "port" is required and must be a number between 0 and 65535');
|
|
32
|
+
}
|
|
33
|
+
if (config.healthCheckInterval != null &&
|
|
34
|
+
(typeof config.healthCheckInterval !== 'number' || config.healthCheckInterval <= 0)) {
|
|
35
|
+
throw new ConfigValidationError('ServiceRegistryConfig: "healthCheckInterval" must be a positive number (ms)');
|
|
36
|
+
}
|
|
37
|
+
if (config.protocol && !['http', 'https', 'grpc'].includes(config.protocol)) {
|
|
38
|
+
throw new ConfigValidationError('ServiceRegistryConfig: "protocol" must be one of "http", "https", "grpc"');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate DiscoveryClientConfig at runtime
|
|
43
|
+
*/
|
|
44
|
+
function validateDiscoveryClientConfig(config) {
|
|
45
|
+
if (config.cacheTTL != null && (typeof config.cacheTTL !== 'number' || config.cacheTTL <= 0)) {
|
|
46
|
+
throw new ConfigValidationError('DiscoveryClientConfig: "cacheTTL" must be a positive number (ms)');
|
|
47
|
+
}
|
|
48
|
+
if (config.refreshInterval != null &&
|
|
49
|
+
(typeof config.refreshInterval !== 'number' || config.refreshInterval <= 0)) {
|
|
50
|
+
throw new ConfigValidationError('DiscoveryClientConfig: "refreshInterval" must be a positive number (ms)');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Validate ServiceClientConfig at runtime
|
|
55
|
+
*/
|
|
56
|
+
function validateServiceClientConfig(config) {
|
|
57
|
+
if (!config.serviceName ||
|
|
58
|
+
typeof config.serviceName !== 'string' ||
|
|
59
|
+
config.serviceName.trim().length === 0) {
|
|
60
|
+
throw new ConfigValidationError('ServiceClientConfig: "serviceName" is required and must be a non-empty string');
|
|
61
|
+
}
|
|
62
|
+
if (config.timeout != null && (typeof config.timeout !== 'number' || config.timeout <= 0)) {
|
|
63
|
+
throw new ConfigValidationError('ServiceClientConfig: "timeout" must be a positive number (ms)');
|
|
64
|
+
}
|
|
65
|
+
if (config.retries != null &&
|
|
66
|
+
(typeof config.retries !== 'number' || config.retries < 0 || !Number.isInteger(config.retries))) {
|
|
67
|
+
throw new ConfigValidationError('ServiceClientConfig: "retries" must be a non-negative integer');
|
|
68
|
+
}
|
|
69
|
+
if (config.retryDelay != null &&
|
|
70
|
+
(typeof config.retryDelay !== 'number' || config.retryDelay < 0)) {
|
|
71
|
+
throw new ConfigValidationError('ServiceClientConfig: "retryDelay" must be a non-negative number (ms)');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Validate RedisBackendConfig at runtime
|
|
76
|
+
*/
|
|
77
|
+
function validateRedisBackendConfig(config) {
|
|
78
|
+
if (config.ttl != null && (typeof config.ttl !== 'number' || config.ttl <= 0)) {
|
|
79
|
+
throw new ConfigValidationError('RedisBackendConfig: "ttl" must be a positive number (seconds)');
|
|
80
|
+
}
|
|
81
|
+
if (config.port != null &&
|
|
82
|
+
(typeof config.port !== 'number' || config.port < 0 || config.port > 65535)) {
|
|
83
|
+
throw new ConfigValidationError('RedisBackendConfig: "port" must be a number between 0 and 65535');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Validate ConsulBackendConfig at runtime
|
|
88
|
+
*/
|
|
89
|
+
function validateConsulBackendConfig(config) {
|
|
90
|
+
if (config.ttl != null && typeof config.ttl === 'string') {
|
|
91
|
+
const match = config.ttl.match(/^(\d+)([smh])$/);
|
|
92
|
+
if (!match) {
|
|
93
|
+
throw new ConfigValidationError('ConsulBackendConfig: "ttl" must match format like "30s", "5m", or "1h"');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (config.port != null &&
|
|
97
|
+
(typeof config.port !== 'number' || config.port < 0 || config.port > 65535)) {
|
|
98
|
+
throw new ConfigValidationError('ConsulBackendConfig: "port" must be a number between 0 and 65535');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Validate KubernetesBackendConfig at runtime
|
|
103
|
+
*/
|
|
104
|
+
function validateKubernetesBackendConfig(config) {
|
|
105
|
+
if (config.namespace != null &&
|
|
106
|
+
(typeof config.namespace !== 'string' || config.namespace.trim().length === 0)) {
|
|
107
|
+
throw new ConfigValidationError('KubernetesBackendConfig: "namespace" must be a non-empty string');
|
|
108
|
+
}
|
|
109
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hazeljs/discovery",
|
|
3
|
+
"version": "0.2.0-alpha.1",
|
|
4
|
+
"description": "Service discovery and registry for HazelJS microservices - Eureka-inspired with multiple backend support",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "jest --coverage --passWithNoTests",
|
|
13
|
+
"test:ci": "jest --coverage --coverageReporters=text --coverageReporters=lcov --coverageReporters=clover --no-coverage-threshold",
|
|
14
|
+
"test:watch": "jest --watch",
|
|
15
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
16
|
+
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
17
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
18
|
+
"clean": "rm -rf dist"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@hazeljs/core": "^0.2.0-alpha.1",
|
|
22
|
+
"@hazeljs/resilience": "^0.2.0-alpha.1",
|
|
23
|
+
"axios": "^1.6.0",
|
|
24
|
+
"reflect-metadata": "^0.2.2"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/jest": "^29.5.14",
|
|
28
|
+
"@types/node": "^20.17.50",
|
|
29
|
+
"@typescript-eslint/eslint-plugin": "^8.18.2",
|
|
30
|
+
"@typescript-eslint/parser": "^8.18.2",
|
|
31
|
+
"eslint": "^8.56.0",
|
|
32
|
+
"eslint-config-prettier": "^9.1.0",
|
|
33
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
34
|
+
"jest": "^29.7.0",
|
|
35
|
+
"prettier": "^3.2.5",
|
|
36
|
+
"ts-jest": "^29.1.2",
|
|
37
|
+
"typescript": "^5.3.3"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@hazeljs/core": ">=0.2.0-beta.0",
|
|
41
|
+
"@kubernetes/client-node": "^0.20.0",
|
|
42
|
+
"consul": "^1.2.0",
|
|
43
|
+
"ioredis": "^5.3.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependenciesMeta": {
|
|
46
|
+
"ioredis": {
|
|
47
|
+
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"consul": {
|
|
50
|
+
"optional": true
|
|
51
|
+
},
|
|
52
|
+
"@kubernetes/client-node": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "git+https://github.com/hazel-js/hazeljs.git",
|
|
62
|
+
"directory": "packages/discovery"
|
|
63
|
+
},
|
|
64
|
+
"keywords": [
|
|
65
|
+
"hazeljs",
|
|
66
|
+
"microservices",
|
|
67
|
+
"service-discovery",
|
|
68
|
+
"service-registry",
|
|
69
|
+
"load-balancing",
|
|
70
|
+
"eureka",
|
|
71
|
+
"consul",
|
|
72
|
+
"kubernetes"
|
|
73
|
+
],
|
|
74
|
+
"author": "Muhammad Arslan <muhammad.arslan@hazeljs.com>",
|
|
75
|
+
"license": "Apache-2.0",
|
|
76
|
+
"bugs": {
|
|
77
|
+
"url": "https://github.com/hazeljs/hazel-js/issues"
|
|
78
|
+
},
|
|
79
|
+
"homepage": "https://hazeljs.com",
|
|
80
|
+
"gitHead": "cbc5ee2c12ced28fd0576faf13c5f078c1e8421e"
|
|
81
|
+
}
|