@zorionapp/gg-core 5.0.37 → 5.0.38
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/package.json +1 -1
- package/src/gg-auth/services/gg-bearer-auth.service.d.ts +1 -0
- package/src/gg-auth/services/gg-bearer-auth.service.js +32 -21
- package/src/gg-auth/services/gg-bearer-auth.service.js.map +1 -1
- package/src/gg-logger/gg-logger.module.js +6 -0
- package/src/gg-logger/gg-logger.module.js.map +1 -1
- package/src/gg-resilience/index.d.ts +2 -0
- package/src/gg-resilience/index.js +6 -0
- package/src/gg-resilience/index.js.map +1 -0
- package/src/gg-resilience/is-transient-error.d.ts +25 -0
- package/src/gg-resilience/is-transient-error.js +117 -0
- package/src/gg-resilience/is-transient-error.js.map +1 -0
- package/src/gg-resilience/with-retry.d.ts +17 -0
- package/src/gg-resilience/with-retry.js +53 -0
- package/src/gg-resilience/with-retry.js.map +1 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ const luxon_1 = require("luxon");
|
|
|
12
12
|
const nestjs_cls_1 = require("nestjs-cls");
|
|
13
13
|
const rxjs_1 = require("rxjs");
|
|
14
14
|
const gg_cache_1 = require("../../gg-cache");
|
|
15
|
+
const gg_resilience_1 = require("../../gg-resilience");
|
|
15
16
|
const gg_auth_module_options_1 = require("../gg-auth.module-options");
|
|
16
17
|
let GgBearerAuthService = GgBearerAuthService_1 = class GgBearerAuthService {
|
|
17
18
|
constructor(options, request, http, ggCache) {
|
|
@@ -54,30 +55,40 @@ let GgBearerAuthService = GgBearerAuthService_1 = class GgBearerAuthService {
|
|
|
54
55
|
* @param cacheKey
|
|
55
56
|
* @protected
|
|
56
57
|
*/
|
|
57
|
-
fetchAndCacheUserDto(accessToken, cacheKey) {
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
-
|
|
58
|
+
async fetchAndCacheUserDto(accessToken, cacheKey) {
|
|
59
|
+
try {
|
|
60
|
+
const response = await (0, gg_resilience_1.withRetry)(() => (0, rxjs_1.firstValueFrom)(this.http.post(`${this.baseUrl}/jwt/check`, { accessToken }, { timeout: this.jwtCheckTimeoutMs })), {
|
|
61
|
+
attempts: 2,
|
|
62
|
+
shouldRetry: gg_resilience_1.isTransientHttpError,
|
|
63
|
+
onRetry: (err, attempt, delayMs) => this.logger.warn({ msg: 'Retrying JWT check after a transient error', attempt, delayMs, err: err }),
|
|
64
|
+
});
|
|
65
|
+
this.logger.log({ msg: 'User queried successfully', userId: response?.data?.user?.ggId });
|
|
66
|
+
await this.ggCache.set(cacheKey, response.data.user, {
|
|
67
|
+
namespaced: false,
|
|
68
|
+
ttl: luxon_1.Duration.fromObject({ seconds: this.authCacheTtlSeconds }),
|
|
69
|
+
});
|
|
70
|
+
return (0, class_transformer_1.plainToInstance)(dto_1.UserDto, response.data.user);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
await this.handleJwtCheckError(error, cacheKey);
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async handleJwtCheckError(error, cacheKey) {
|
|
78
|
+
// Invalid/expired JWT — cache a negative result and decline at warn, matching the prior policy.
|
|
79
|
+
if (error.code === 'ERR_BAD_REQUEST') {
|
|
80
|
+
this.logger.warn({ msg: `User authentication declined with given JWT`, err: error });
|
|
81
|
+
await this.ggCache.set(cacheKey, new dto_1.UserDto(), {
|
|
61
82
|
namespaced: false,
|
|
62
83
|
ttl: luxon_1.Duration.fromObject({ seconds: this.authCacheTtlSeconds }),
|
|
63
84
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.logger.warn({ msg: `User authentication declined with given JWT`, err: error });
|
|
72
|
-
await this.ggCache.set(cacheKey, new dto_1.UserDto(), {
|
|
73
|
-
namespaced: false,
|
|
74
|
-
ttl: luxon_1.Duration.fromObject({ seconds: this.authCacheTtlSeconds }),
|
|
75
|
-
});
|
|
76
|
-
return error;
|
|
77
|
-
}
|
|
78
|
-
this.logger.error({ msg: `Internal server error`, err: error });
|
|
79
|
-
};
|
|
80
|
-
return (0, rxjs_1.firstValueFrom)(this.http.post(`${this.baseUrl}/jwt/check`, { accessToken }, { timeout: this.jwtCheckTimeoutMs }).pipe((0, rxjs_1.tap)({ next: onSuccess, error: onError }), (0, rxjs_1.map)((res) => (0, class_transformer_1.plainToInstance)(dto_1.UserDto, res.data.user))));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (error.code === 'ECONNREFUSED') {
|
|
88
|
+
this.logger.error({ msg: 'User service unreachable; check network connection or port mapping', err: error });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.logger.error({ msg: `Internal server error`, err: error });
|
|
81
92
|
}
|
|
82
93
|
getPositiveNumberOrFallback(value, fallback) {
|
|
83
94
|
if (Number.isFinite(value) && value > 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gg-bearer-auth.service.js","sourceRoot":"","sources":["../../../../../../libs/gg-core/src/gg-auth/services/gg-bearer-auth.service.ts"],"names":[],"mappings":";;;;;AAAA,mDAAoD;AACpD,yCAA4C;AAC5C,2CAA4D;AAE5D,yDAAoD;AACpD,qDAAwC;AAGxC,iCAAiC;AACjC,2CAAqC;AACrC,+
|
|
1
|
+
{"version":3,"file":"gg-bearer-auth.service.js","sourceRoot":"","sources":["../../../../../../libs/gg-core/src/gg-auth/services/gg-bearer-auth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ const tslib_1 = require("tslib");
|
|
|
6
6
|
const common_1 = require("@nestjs/common");
|
|
7
7
|
const nestjs_pino_1 = require("nestjs-pino");
|
|
8
8
|
const gg_config_1 = require("../gg-config");
|
|
9
|
+
const gg_resilience_1 = require("../gg-resilience");
|
|
9
10
|
const PINO_LEVEL_TO_GCP_SEVERITY = {
|
|
10
11
|
trace: 'DEBUG',
|
|
11
12
|
debug: 'DEBUG',
|
|
@@ -50,6 +51,11 @@ function buildErrorReportingMixin(service, version) {
|
|
|
50
51
|
if (!(err instanceof Error) || !err.stack) {
|
|
51
52
|
return {};
|
|
52
53
|
}
|
|
54
|
+
// ClientRMQ logs broker force-closes / heartbeat timeouts at error, but the client auto-reconnects:
|
|
55
|
+
// keep the log line, keep the self-healing noise out of Error Reporting.
|
|
56
|
+
if ((0, gg_resilience_1.isTransientRmqConnectionError)(err)) {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
53
59
|
return {
|
|
54
60
|
stack_trace: err.stack,
|
|
55
61
|
serviceContext: { service, version },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gg-logger.module.js","sourceRoot":"","sources":["../../../../../libs/gg-core/src/gg-logger/gg-logger.module.ts"],"names":[],"mappings":";;;;;AAAA,2CAAuD;AAEvD,6CAAmD;AACnD,4CAAyC;
|
|
1
|
+
{"version":3,"file":"gg-logger.module.js","sourceRoot":"","sources":["../../../../../libs/gg-core/src/gg-logger/gg-logger.module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./is-transient-error"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./with-retry"), exports);
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/gg-core/src/gg-resilience/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,uDAA6B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A failed outbound HTTP call worth retrying: a network/timeout error (no response) or an upstream
|
|
3
|
+
* 5xx. A 4xx (including 429) is the peer's deliberate rejection and is never treated as transient —
|
|
4
|
+
* retrying it just adds load.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isTransientHttpError(error: unknown): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A database driver error caused by the connection dropping rather than the query itself — safe to
|
|
9
|
+
* retry a read. Never matches constraint/validation/not-found errors.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isTransientDbError(error: unknown): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* A Redis command that timed out or was interrupted by a reconnect — safe to retry for idempotent ops.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isTransientRedisError(error: unknown): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* A RabbitMQ connection lifecycle error the client recovers from on its own (broker force-close,
|
|
18
|
+
* heartbeat timeout). Used to keep this self-healing noise out of Error Reporting — it is NOT a
|
|
19
|
+
* retry signal, since reconnection is handled by the connection manager, not by the caller.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isTransientRmqConnectionError(error: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Explicit-only union of the transient HTTP, database, and Redis classifiers
|
|
24
|
+
*/
|
|
25
|
+
export declare function isTransientError(error: unknown): boolean;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTransientError = exports.isTransientRmqConnectionError = exports.isTransientRedisError = exports.isTransientDbError = exports.isTransientHttpError = void 0;
|
|
4
|
+
// Network-layer error codes that mean "the connection failed", not "the peer rejected the request".
|
|
5
|
+
// Shared by the HTTP and DB/Redis classifiers since node surfaces the same codes across drivers.
|
|
6
|
+
const TRANSIENT_NETWORK_CODES = new Set([
|
|
7
|
+
'ECONNRESET',
|
|
8
|
+
'ECONNREFUSED',
|
|
9
|
+
'ECONNABORTED',
|
|
10
|
+
'ETIMEDOUT',
|
|
11
|
+
'EAI_AGAIN',
|
|
12
|
+
'ENOTFOUND',
|
|
13
|
+
'EHOSTUNREACH',
|
|
14
|
+
'ENETUNREACH',
|
|
15
|
+
'EPIPE',
|
|
16
|
+
]);
|
|
17
|
+
// Postgres/MikroORM: an idle connection dropped by the server or a proxy, a failover, or the pool
|
|
18
|
+
// giving up. These wrap a plain SELECT/UPDATE that would otherwise succeed on a retry.
|
|
19
|
+
const TRANSIENT_DB_ERROR_PATTERNS = [
|
|
20
|
+
'Connection terminated unexpectedly',
|
|
21
|
+
'Connection terminated due to connection timeout',
|
|
22
|
+
'connection is closed',
|
|
23
|
+
'Client has encountered a connection error',
|
|
24
|
+
'server closed the connection unexpectedly',
|
|
25
|
+
'terminating connection due to administrator command',
|
|
26
|
+
'the database system is shutting down',
|
|
27
|
+
'the database system is starting up',
|
|
28
|
+
'timeout exceeded when trying to connect',
|
|
29
|
+
'read ECONNRESET',
|
|
30
|
+
];
|
|
31
|
+
// Postgres SQLSTATE codes in the connection-exception (08xxx) and operator-intervention (57xxx) classes.
|
|
32
|
+
const TRANSIENT_DB_SQL_STATES = new Set(['08000', '08003', '08006', '08001', '08004', '57P01', '57P02', '57P03', '53300']);
|
|
33
|
+
// ioredis: a command that timed out or was cut off mid-flight while the client reconnected.
|
|
34
|
+
const TRANSIENT_REDIS_ERROR_PATTERNS = [
|
|
35
|
+
'Command timed out',
|
|
36
|
+
"Stream isn't writeable",
|
|
37
|
+
'Connection is closed',
|
|
38
|
+
'Connection is fully closed',
|
|
39
|
+
'max retries per request',
|
|
40
|
+
];
|
|
41
|
+
// amqplib: the broker forcibly closed the connection (redeploy, management action) or a heartbeat
|
|
42
|
+
// lapsed. The connection manager reconnects transparently, so these are noise, never a lost message.
|
|
43
|
+
const TRANSIENT_RMQ_ERROR_PATTERNS = ['CONNECTION-FORCED', 'Connection closed: 320', 'Heartbeat timeout'];
|
|
44
|
+
// amqplib reply code for CONNECTION-FORCED (see amqplib/lib/connection.js).
|
|
45
|
+
const AMQP_CONNECTION_FORCED_CODE = 320;
|
|
46
|
+
function messageIncludes(error, patterns) {
|
|
47
|
+
const message = error instanceof Error ? error.message : typeof error === 'string' ? error : '';
|
|
48
|
+
return patterns.some((pattern) => message.includes(pattern));
|
|
49
|
+
}
|
|
50
|
+
function errorCode(error) {
|
|
51
|
+
return error?.code;
|
|
52
|
+
}
|
|
53
|
+
function isAxiosError(error) {
|
|
54
|
+
return Boolean(error?.isAxiosError);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A failed outbound HTTP call worth retrying: a network/timeout error (no response) or an upstream
|
|
58
|
+
* 5xx. A 4xx (including 429) is the peer's deliberate rejection and is never treated as transient —
|
|
59
|
+
* retrying it just adds load.
|
|
60
|
+
*/
|
|
61
|
+
function isTransientHttpError(error) {
|
|
62
|
+
if (isAxiosError(error)) {
|
|
63
|
+
if (error.response) {
|
|
64
|
+
return error.response.status >= 500;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
const code = errorCode(error);
|
|
69
|
+
return typeof code === 'string' && TRANSIENT_NETWORK_CODES.has(code);
|
|
70
|
+
}
|
|
71
|
+
exports.isTransientHttpError = isTransientHttpError;
|
|
72
|
+
/**
|
|
73
|
+
* A database driver error caused by the connection dropping rather than the query itself — safe to
|
|
74
|
+
* retry a read. Never matches constraint/validation/not-found errors.
|
|
75
|
+
*/
|
|
76
|
+
function isTransientDbError(error) {
|
|
77
|
+
const code = errorCode(error);
|
|
78
|
+
if (typeof code === 'string' && (TRANSIENT_NETWORK_CODES.has(code) || TRANSIENT_DB_SQL_STATES.has(code))) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return messageIncludes(error, TRANSIENT_DB_ERROR_PATTERNS);
|
|
82
|
+
}
|
|
83
|
+
exports.isTransientDbError = isTransientDbError;
|
|
84
|
+
/**
|
|
85
|
+
* A Redis command that timed out or was interrupted by a reconnect — safe to retry for idempotent ops.
|
|
86
|
+
*/
|
|
87
|
+
function isTransientRedisError(error) {
|
|
88
|
+
if (error?.name === 'MaxRetriesPerRequestError') {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
const code = errorCode(error);
|
|
92
|
+
if (typeof code === 'string' && TRANSIENT_NETWORK_CODES.has(code)) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return messageIncludes(error, TRANSIENT_REDIS_ERROR_PATTERNS);
|
|
96
|
+
}
|
|
97
|
+
exports.isTransientRedisError = isTransientRedisError;
|
|
98
|
+
/**
|
|
99
|
+
* A RabbitMQ connection lifecycle error the client recovers from on its own (broker force-close,
|
|
100
|
+
* heartbeat timeout). Used to keep this self-healing noise out of Error Reporting — it is NOT a
|
|
101
|
+
* retry signal, since reconnection is handled by the connection manager, not by the caller.
|
|
102
|
+
*/
|
|
103
|
+
function isTransientRmqConnectionError(error) {
|
|
104
|
+
if (errorCode(error) === AMQP_CONNECTION_FORCED_CODE) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
return messageIncludes(error, TRANSIENT_RMQ_ERROR_PATTERNS);
|
|
108
|
+
}
|
|
109
|
+
exports.isTransientRmqConnectionError = isTransientRmqConnectionError;
|
|
110
|
+
/**
|
|
111
|
+
* Explicit-only union of the transient HTTP, database, and Redis classifiers
|
|
112
|
+
*/
|
|
113
|
+
function isTransientError(error) {
|
|
114
|
+
return isTransientHttpError(error) || isTransientDbError(error) || isTransientRedisError(error);
|
|
115
|
+
}
|
|
116
|
+
exports.isTransientError = isTransientError;
|
|
117
|
+
//# sourceMappingURL=is-transient-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-transient-error.js","sourceRoot":"","sources":["../../../../../libs/gg-core/src/gg-resilience/is-transient-error.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface RetryOptions {
|
|
2
|
+
attempts?: number;
|
|
3
|
+
baseDelayMs?: number;
|
|
4
|
+
maxDelayMs?: number;
|
|
5
|
+
jitter?: boolean;
|
|
6
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
7
|
+
onRetry?: (error: unknown, attempt: number, delayMs: number) => void;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Runs `operation`, retrying it on transient failures with exponential backoff. Retries are logged
|
|
12
|
+
* via `onRetry` (typically at `warn`); the original error is rethrown unchanged once attempts are
|
|
13
|
+
* exhausted or the error is not retryable, so the caller — or the global exception filter — logs the
|
|
14
|
+
* genuine failure at `error`. This keeps self-healing blips out of Error Reporting while preserving
|
|
15
|
+
* real faults.
|
|
16
|
+
*/
|
|
17
|
+
export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withRetry = void 0;
|
|
4
|
+
const is_transient_error_1 = require("./is-transient-error");
|
|
5
|
+
const DEFAULT_ATTEMPTS = 3;
|
|
6
|
+
const DEFAULT_BASE_DELAY_MS = 100;
|
|
7
|
+
const DEFAULT_MAX_DELAY_MS = 2000;
|
|
8
|
+
function backoffDelay(attempt, baseDelayMs, maxDelayMs, jitter) {
|
|
9
|
+
const capped = Math.min(maxDelayMs, baseDelayMs * 2 ** (attempt - 1));
|
|
10
|
+
// Equal jitter: half fixed, half random — spreads retries without collapsing the delay to ~0.
|
|
11
|
+
return jitter ? capped / 2 + Math.random() * (capped / 2) : capped;
|
|
12
|
+
}
|
|
13
|
+
function sleep(ms, signal) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
if (signal?.aborted) {
|
|
16
|
+
return reject(signal.reason ?? new Error('Aborted'));
|
|
17
|
+
}
|
|
18
|
+
const onAbort = () => {
|
|
19
|
+
clearTimeout(timer);
|
|
20
|
+
reject(signal?.reason ?? new Error('Aborted'));
|
|
21
|
+
};
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
signal?.removeEventListener('abort', onAbort);
|
|
24
|
+
resolve();
|
|
25
|
+
}, ms);
|
|
26
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Runs `operation`, retrying it on transient failures with exponential backoff. Retries are logged
|
|
31
|
+
* via `onRetry` (typically at `warn`); the original error is rethrown unchanged once attempts are
|
|
32
|
+
* exhausted or the error is not retryable, so the caller — or the global exception filter — logs the
|
|
33
|
+
* genuine failure at `error`. This keeps self-healing blips out of Error Reporting while preserving
|
|
34
|
+
* real faults.
|
|
35
|
+
*/
|
|
36
|
+
async function withRetry(operation, options = {}) {
|
|
37
|
+
const { attempts = DEFAULT_ATTEMPTS, baseDelayMs = DEFAULT_BASE_DELAY_MS, maxDelayMs = DEFAULT_MAX_DELAY_MS, jitter = true, shouldRetry = is_transient_error_1.isTransientHttpError, onRetry, signal, } = options;
|
|
38
|
+
for (let attempt = 1;; attempt++) {
|
|
39
|
+
try {
|
|
40
|
+
return await operation();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (attempt >= attempts || !shouldRetry(error)) {
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
const delayMs = backoffDelay(attempt, baseDelayMs, maxDelayMs, jitter);
|
|
47
|
+
onRetry?.(error, attempt, delayMs);
|
|
48
|
+
await sleep(delayMs, signal);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.withRetry = withRetry;
|
|
53
|
+
//# sourceMappingURL=with-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-retry.js","sourceRoot":"","sources":["../../../../../libs/gg-core/src/gg-resilience/with-retry.ts"],"names":[],"mappings":";;;AAAA,6DAA4D;AAgB5D,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC,SAAS,YAAY,CAAC,OAAe,EAAE,WAAmB,EAAE,UAAkB,EAAE,MAAe;IAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAEtE,8FAA8F;IAC9F,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACrE,CAAC;AAED,SAAS,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC7C,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,SAAS,CAAI,SAA2B,EAAE,UAAwB,EAAE;IACxF,MAAM,EACJ,QAAQ,GAAG,gBAAgB,EAC3B,WAAW,GAAG,qBAAqB,EACnC,UAAU,GAAG,oBAAoB,EACjC,MAAM,GAAG,IAAI,EACb,WAAW,GAAG,yCAAoB,EAClC,OAAO,EACP,MAAM,GACP,GAAG,OAAO,CAAC;IAEZ,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/C,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;YACvE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACnC,MAAM,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;AACH,CAAC;AAxBD,8BAwBC"}
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -13,4 +13,5 @@ tslib_1.__exportStar(require("./gg-metrics"), exports);
|
|
|
13
13
|
tslib_1.__exportStar(require("./gg-micro"), exports);
|
|
14
14
|
tslib_1.__exportStar(require("./gg-redis"), exports);
|
|
15
15
|
tslib_1.__exportStar(require("./gg-redlock"), exports);
|
|
16
|
+
tslib_1.__exportStar(require("./gg-resilience"), exports);
|
|
16
17
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/gg-core/src/index.ts"],"names":[],"mappings":";;;AAAA,oDAA0B;AAC1B,qDAA2B;AAC3B,sDAA4B;AAC5B,oDAA0B;AAC1B,wDAA8B;AAC9B,qDAA2B;AAC3B,sDAA4B;AAC5B,sDAA4B;AAC5B,uDAA6B;AAC7B,qDAA2B;AAC3B,qDAA2B;AAC3B,uDAA6B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/gg-core/src/index.ts"],"names":[],"mappings":";;;AAAA,oDAA0B;AAC1B,qDAA2B;AAC3B,sDAA4B;AAC5B,oDAA0B;AAC1B,wDAA8B;AAC9B,qDAA2B;AAC3B,sDAA4B;AAC5B,sDAA4B;AAC5B,uDAA6B;AAC7B,qDAA2B;AAC3B,qDAA2B;AAC3B,uDAA6B;AAC7B,0DAAgC"}
|