@luckystack/core 0.6.3 → 0.6.5
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/CHANGELOG.md +17 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.js +34 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -18,19 +18,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
18
|
- **Decoupled secrets-resolved hook** (ADR 0026): `notifySecretsResolved(changedKeys?)`
|
|
19
19
|
+ `registerSecretsResolvedListener(fn)`. A secret resolver (e.g.
|
|
20
20
|
`@luckystack/secret-manager` via `onApplied: notifySecretsResolved`) fires it after
|
|
21
|
-
overwriting `process.env`; `redis.ts` self-registers a listener that
|
|
22
|
-
default client when a `REDIS_` credential changed, so Redis auth via a
|
|
23
|
-
POINTER survives boot AND rotation with no hand-wiring. Generic — Prisma
|
|
24
|
-
clients can subscribe too. Also adds
|
|
25
|
-
`ProjectConfig` (`SecretManagerConfigRef`)
|
|
21
|
+
overwriting `process.env`; `redis.ts` self-registers a listener that EAGERLY REBUILDS +
|
|
22
|
+
registers the default client when a `REDIS_` credential changed, so Redis auth via a
|
|
23
|
+
secret-manager POINTER survives boot AND rotation with no hand-wiring. Generic — Prisma
|
|
24
|
+
pools / SDK clients can subscribe too. Also adds `rebuildDefaultRedisClient()` and an
|
|
25
|
+
optional structural `secretManager?` field on `ProjectConfig` (`SecretManagerConfigRef`)
|
|
26
|
+
so the server boot can detect a resolver.
|
|
26
27
|
|
|
27
28
|
### Fixed
|
|
28
29
|
|
|
29
30
|
- **Redis secret-manager pointer boot** (ADR 0026): the default Redis client no longer
|
|
30
31
|
fails auth with a baked-in `REDIS_PASSWORD_V<n>` pointer when it was built (during an
|
|
31
|
-
early import) before secrets resolved
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
early import) before secrets resolved. The framework EAGERLY REBUILDS + registers a
|
|
33
|
+
fresh client from the resolved env (`rebuildDefaultRedisClient()`), so the boot-UUID
|
|
34
|
+
write authenticates with the real password — no consumer code. **Correction over
|
|
35
|
+
0.6.3/0.6.4:** the rebuild logic was right but never TRIGGERED for a normal project (the
|
|
36
|
+
server-boot gate `getProjectConfig().secretManager?.url` is falsy — the scaffold doesn't
|
|
37
|
+
register `secretManager` into `projectConfig` — and bare `initSecretManager` wires no
|
|
38
|
+
`onApplied`). Core now publishes `notifySecretsResolved` onto a decoupled global-symbol
|
|
39
|
+
ARRAY (`Symbol.for('luckystack.secretsResolved.listeners')`) at module load, which
|
|
40
|
+
`@luckystack/secret-manager` fires automatically after every resolve — so the rebuild
|
|
41
|
+
happens at resolve time with zero consumer code, in prod and dev, and even survives a
|
|
42
|
+
dual `@luckystack/core` instance.
|
|
34
43
|
- **CORE-2** — `tryCatchSync<T, P = void>` now mirrors `tryCatch`'s `P` default,
|
|
35
44
|
so a params-less call can pass only the result type (`tryCatchSync<URL>(() =>
|
|
36
45
|
new URL(raw))`) instead of failing with TS2558.
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { z } from 'zod';
|
|
|
6
6
|
import * as _prisma_client_runtime_library from '@prisma/client/runtime/library';
|
|
7
7
|
import * as _prisma_client from '@prisma/client';
|
|
8
8
|
import { PrismaClient } from '@prisma/client';
|
|
9
|
-
import Redis, { Redis
|
|
9
|
+
import Redis$1, { Redis } from 'ioredis';
|
|
10
10
|
import { RedisAdapterOptions } from '@socket.io/redis-adapter';
|
|
11
11
|
import { ServerResponse, IncomingMessage, IncomingHttpHeaders } from 'node:http';
|
|
12
12
|
import 'socket.io-client';
|
|
@@ -679,6 +679,7 @@ declare const isDbHealthCheckRegistered: () => boolean;
|
|
|
679
679
|
declare const resetDbHealthCheckForTests: () => void;
|
|
680
680
|
|
|
681
681
|
declare const resetDefaultRedisClient: () => void;
|
|
682
|
+
declare const rebuildDefaultRedisClient: () => Redis;
|
|
682
683
|
interface RedisConnectionOptions {
|
|
683
684
|
host: string;
|
|
684
685
|
port: number;
|
|
@@ -687,7 +688,7 @@ interface RedisConnectionOptions {
|
|
|
687
688
|
}
|
|
688
689
|
declare const getRedisConnectionOptions: () => RedisConnectionOptions;
|
|
689
690
|
declare const registerStrayPrefixCommand: (...commands: string[]) => void;
|
|
690
|
-
declare const redis: Redis;
|
|
691
|
+
declare const redis: Redis$1;
|
|
691
692
|
|
|
692
693
|
type SecretsResolvedListener = (changedKeys: readonly string[] | undefined) => void;
|
|
693
694
|
declare const registerSecretsResolvedListener: (listener: SecretsResolvedListener) => (() => void);
|
|
@@ -722,15 +723,15 @@ declare const releaseLease: (name: string, token: string) => Promise<boolean>;
|
|
|
722
723
|
|
|
723
724
|
declare const DEFAULT_CLIENT_KEY = "default";
|
|
724
725
|
declare const registerPrismaClient: (client: PrismaClient, key?: string) => PrismaClient;
|
|
725
|
-
declare const registerRedisClient: (client: Redis
|
|
726
|
+
declare const registerRedisClient: (client: Redis, key?: string) => Redis;
|
|
726
727
|
declare const isPrismaClientRegistered: () => boolean;
|
|
727
728
|
declare const isRedisClientRegistered: () => boolean;
|
|
728
729
|
declare const getPrismaClientKeys: () => string[];
|
|
729
730
|
declare const getRedisClientKeys: () => string[];
|
|
730
731
|
declare const getPrismaClientFor: (key?: string) => PrismaClient;
|
|
731
|
-
declare const getRedisClientFor: (key?: string) => Redis
|
|
732
|
+
declare const getRedisClientFor: (key?: string) => Redis;
|
|
732
733
|
declare const getPrismaClient: () => PrismaClient;
|
|
733
|
-
declare const getRedisClient: () => Redis
|
|
734
|
+
declare const getRedisClient: () => Redis;
|
|
734
735
|
declare const resetClientsForTests: () => void;
|
|
735
736
|
|
|
736
737
|
interface AttachSocketRedisAdapterOptions {
|
|
@@ -744,9 +745,9 @@ interface AttachSocketRedisAdapterOptions {
|
|
|
744
745
|
* a dedicated adapter connection, custom auth, or a sentinel/cluster handle.
|
|
745
746
|
* When omitted the framework duplicates the default `redis` handle.
|
|
746
747
|
*/
|
|
747
|
-
pubClient?: Redis
|
|
748
|
+
pubClient?: Redis;
|
|
748
749
|
/** Pre-built sub client (see `pubClient`). */
|
|
749
|
-
subClient?: Redis
|
|
750
|
+
subClient?: Redis;
|
|
750
751
|
}
|
|
751
752
|
declare const attachSocketRedisAdapter: (io: Server, options?: AttachSocketRedisAdapterOptions) => void;
|
|
752
753
|
|
|
@@ -1894,4 +1895,4 @@ declare const clearAllHooks: () => void;
|
|
|
1894
1895
|
declare const registerSyncHook: <TName extends SyncHookName>(name: TName, handler: SyncHookHandler<SyncHookPayloads[TName]>) => (() => void);
|
|
1895
1896
|
declare const dispatchSyncHook: <TName extends SyncHookName>(name: TName, payload: SyncHookPayloads[TName]) => void;
|
|
1896
1897
|
|
|
1897
|
-
export { type ApiAuthRejectedPayload, type ApiErrorPayload, type ApiResponseEnvelope, AuthProps, type AvatarConfig, type AvatarConfigInput, BOOT_KEY_PREFIX, BaseSessionLayout, type CheckRateLimitParams, type CookiePrefixConstraints, type CorsRejectedPayload, type CreateLocalizedNormalizerInput, type CsrfConfig, type CsrfCookieOptions, type CsrfMismatchPayload, DEFAULT_AVATAR_CONFIG, DEFAULT_CLIENT_KEY, DEFAULT_CSRF_CONFIG, DEFAULT_ENV_FILES, DEFAULT_REDACTED_LOG_KEYS, DEPTH_TRUNCATED_PLACEHOLDER, type DbHealthCheck, type DbHealthResult, DeepPartial, type DeployConfigShape, type DeployDevelopmentShape, type DeployEnvironmentShape, type DeployResourceShape, type DeployRoutingShape, type DispatchResult, type EmailAttachment, type EmailMessage, type EmailResult, type EmailSender, type EmailSenderRegistry, type ErrorFormatter, type ErrorFormatterContext, ErrorParam, ErrorResponseInput, type ErrorTracker, type ErrorTrackerContext, type ErrorTrackerEvent, type ErrorTrackerUser, type FormatterEnvelope, GENERATED_API_DOCS_PATH, GENERATED_API_SCHEMAS_PATH, GENERATED_SOCKET_TYPES_PATH, HealthHashConfig, type HealthHashDescriptor, type HookHandler, type HookName, type HookPayloads, type HookResult, type HookSessionShape, type HookStopSignal, type HttpMethod, type LanguageCode, type LocaleReloader, type LocalizedNormalizer, type NormalizeErrorResponseInput, NormalizedErrorResponse, type OnUploadCompletePayload, type OnUploadStartPayload, type OneTimeTokenHandle, PUBLIC_DIR, type PeerRequire, type PostApiExecutePayload, type PostApiRespondPayload, type PostApiValidatePayload, type PostAvatarServePayload, type PostErrorNormalizePayload, type PostHttpRequestPayload, type PostSessionRefreshPayload, type PostSyncAuthorizePayload, type PostSyncExecutePayload, type PostSyncFanoutPayload, type PostSyncValidatePayload, type PreApiExecutePayload, type PreApiRespondPayload, type PreApiValidatePayload, type PreAvatarServePayload, type PreCaptureFilter, type PreErrorNormalizePayload, type PreHttpRequestPayload, type PreServerStopPayload, type PreSessionRefreshPayload, type PreSocketMessagePayload, type PreSyncAuthorizePayload, type PreSyncExecutePayload, type PreSyncFanoutPayload, type PreSyncRecipientPayload, type PreSyncValidatePayload, type PresetDefinition, type ProcessUploadInput, type ProcessUploadResult, REDACTED_PLACEHOLDER, ROOT_DIR, type RateLimitExceededPayload, type RateLimitResult, type RateLimitStrategy, type RedisConnectionOptions, type RedisKeyFormatter, type Registry, type RegistryOptions, type ResolveClientIpParams, type RoomNameFormatter, type RoomNameFormatterContext, type RuntimeApiMapsResult, type RuntimeEnv, type RuntimeMapsProvider, type RuntimeSyncMapsResult, SERVER_DIR, SERVER_FUNCTIONS_DIR, SHARED_DIR, SRC_DIR, type SecretsResolvedListener, type ServiceDefinition, type ServicesConfigShape, type SessionCreatedPayload, type SessionLogoutInput, type SessionProvider, type SessionRevokedPayload, type SessionSaveResult, type SocketMiddleware, type SpanHandle, type SpanResult, type SyncErrorPayload, type SyncHookHandler, type SyncHookName, type SyncHookPayloads, TSCONFIG_ALIAS_FILES, type TranslateFunction, type TranslateInput, UNKNOWN_CLIENT_IP, UPLOADS_DIR, type ValidationResult$1 as ValidationResult, abortAllForSocket, abortApiByResponseIndex, abortSyncByCb, acquireLease, allowedOrigin, type apiMessage, appendErrorTracker, applyCookiePrefixConstraints, applyErrorFormatter, applySocketMiddlewares, applyStrayKeyPrefix, attachSocketRedisAdapter, bootstrapEnv, captureException, captureExceptionAcrossTrackers, captureMessage, captureMessageAcrossTrackers, checkRateLimit, clearAllHooks, clearAllRateLimits, clearRateLimit, clearSocketMiddlewares, collectSynchronizedEnvKeys, computeSynchronizedEnvHashes, consumeOneTimeToken, consumeOneTimeTokenJson, createLocalizedNormalizer, createRegistry, defaultRateLimitStrategy, defaultRedisKeyFormatter, defaultRoomNameFormatter, deriveTokenBucketId, describeHealthHashConfig, dispatchHook, dispatchSyncHook, ensurePeerDepInstalled, env, escapeHtml, extractLanguageFromHeader, extractTokenFromRequest, extractTokenFromSocket, flushErrorTrackers, formatKey, formatRoomName, getActiveErrorTrackers, getAvatarConfig, getBindAddress, getCookieValue, getCsrfConfig, getCurrentErrorTrackerIdentity, getDbHealthCheck, getDeployConfig, getEffectiveHttpMethod, getEmailSender, getEmailSenderByName, getEnv, getEnvFiles, getErrorFormatter, getGeneratedApiDocsPath, getGeneratedApiSchemasPath, getGeneratedSocketTypesPath, getIoInstance, getLocaleReloader, getLocalizedNormalizer, getParams, getPrismaClient, getPrismaClientFor, getPrismaClientKeys, getPublicDir, getRateLimitStatus, getRateLimitStrategy, getRedactedLogKeys, getRedisClient, getRedisClientFor, getRedisClientKeys, getRedisConnectionOptions, getRedisKeyFormatter, getRegisteredSessionProvider, getRoomNameFormatter, getRuntimeApiMaps, getRuntimeSyncMaps, getServerDir, getServerFunctionDirs, getServerFunctionsDir, getServicesConfig, getSharedDir, getSocketMiddlewares, getSrcDir, getUploadsDir, hasCookie, hashSynchronizedValue, hashSynchronizedValueWith, inferHttpMethod, initConsolelog, initSharedSentry, isDbHealthCheckRegistered, isDeployConfigRegistered, isEmailSenderRegistered, isFalsy, isGetMethodName, isLocalizedNormalizerRegistered, isLoopbackIp, isMethodAllowed, isPrismaClientRegistered, isPrismaClientResolvable, isProduction, isRedactedLogKey, isRedisClientRegistered, isRuntimeMapsProviderRegistered, isServicesConfigRegistered, isSessionProviderRegistered, issueOneTimeToken, listEmailSenderNames, loadEnvFiles, loadPeer, normalizeErrorResponse, normalizeOrigin, notifySecretsResolved, oneTimeTokenKey, performLogout, prisma, processUpload, readBootUuid, readSession, recordMetricAcrossTrackers, redis, registerApiAbortController, registerAvatarConfig, registerBindAddress, registerCsrfConfig, registerDbHealthCheck, registerDeployConfig, registerEmailSender, registerEmailSenders, registerErrorFormatter, registerErrorTracker, registerErrorTrackers, registerHook, registerLocaleReloader, registerLocalizedNormalizer, registerPreCaptureFilter, registerPrismaClient, registerRateLimitStrategy, registerRedactedLogKeys, registerRedisClient, registerRedisKeyFormatter, registerRoomNameFormatter, registerRuntimeMapsProvider, registerSecretsResolvedListener, registerServicesConfig, registerSessionProvider, registerSocketMiddleware, registerStrayPrefixCommand, registerSyncAbortController, registerSyncHook, releaseLease, removeSession, renewLease, resetClientsForTests, resetCsrfConfigForTests, resetDbHealthCheckForTests, resetDefaultRedisClient, resetRedactedLogKeysForTests, resetRedisKeyFormatterForTests, resetSessionProviderForTests, resolveClientIp, resolveEnvKey, resolveErrorMessage, resolveFromRoot, resolveHealthHashConfig, resolveHealthHashConfigFromDescriptor, runWithErrorTrackerIdentity, runWithErrorTrackerIdentityScope, sanitizeErrorString, sanitizeErrorStrings, sanitizeForLog, serveAvatar, setCurrentErrorTrackerIdentity, setErrorTrackerUser, setIoInstance, setSentryUser, startSpan, startSpanAcrossTrackers, startSpanHandle, type syncMessage, tryCatch, tryCatchSync, unregisterApiAbortController, unregisterSyncAbortController, validateInputByType, validateRequest, writeBootUuid, writeSession };
|
|
1898
|
+
export { type ApiAuthRejectedPayload, type ApiErrorPayload, type ApiResponseEnvelope, AuthProps, type AvatarConfig, type AvatarConfigInput, BOOT_KEY_PREFIX, BaseSessionLayout, type CheckRateLimitParams, type CookiePrefixConstraints, type CorsRejectedPayload, type CreateLocalizedNormalizerInput, type CsrfConfig, type CsrfCookieOptions, type CsrfMismatchPayload, DEFAULT_AVATAR_CONFIG, DEFAULT_CLIENT_KEY, DEFAULT_CSRF_CONFIG, DEFAULT_ENV_FILES, DEFAULT_REDACTED_LOG_KEYS, DEPTH_TRUNCATED_PLACEHOLDER, type DbHealthCheck, type DbHealthResult, DeepPartial, type DeployConfigShape, type DeployDevelopmentShape, type DeployEnvironmentShape, type DeployResourceShape, type DeployRoutingShape, type DispatchResult, type EmailAttachment, type EmailMessage, type EmailResult, type EmailSender, type EmailSenderRegistry, type ErrorFormatter, type ErrorFormatterContext, ErrorParam, ErrorResponseInput, type ErrorTracker, type ErrorTrackerContext, type ErrorTrackerEvent, type ErrorTrackerUser, type FormatterEnvelope, GENERATED_API_DOCS_PATH, GENERATED_API_SCHEMAS_PATH, GENERATED_SOCKET_TYPES_PATH, HealthHashConfig, type HealthHashDescriptor, type HookHandler, type HookName, type HookPayloads, type HookResult, type HookSessionShape, type HookStopSignal, type HttpMethod, type LanguageCode, type LocaleReloader, type LocalizedNormalizer, type NormalizeErrorResponseInput, NormalizedErrorResponse, type OnUploadCompletePayload, type OnUploadStartPayload, type OneTimeTokenHandle, PUBLIC_DIR, type PeerRequire, type PostApiExecutePayload, type PostApiRespondPayload, type PostApiValidatePayload, type PostAvatarServePayload, type PostErrorNormalizePayload, type PostHttpRequestPayload, type PostSessionRefreshPayload, type PostSyncAuthorizePayload, type PostSyncExecutePayload, type PostSyncFanoutPayload, type PostSyncValidatePayload, type PreApiExecutePayload, type PreApiRespondPayload, type PreApiValidatePayload, type PreAvatarServePayload, type PreCaptureFilter, type PreErrorNormalizePayload, type PreHttpRequestPayload, type PreServerStopPayload, type PreSessionRefreshPayload, type PreSocketMessagePayload, type PreSyncAuthorizePayload, type PreSyncExecutePayload, type PreSyncFanoutPayload, type PreSyncRecipientPayload, type PreSyncValidatePayload, type PresetDefinition, type ProcessUploadInput, type ProcessUploadResult, REDACTED_PLACEHOLDER, ROOT_DIR, type RateLimitExceededPayload, type RateLimitResult, type RateLimitStrategy, type RedisConnectionOptions, type RedisKeyFormatter, type Registry, type RegistryOptions, type ResolveClientIpParams, type RoomNameFormatter, type RoomNameFormatterContext, type RuntimeApiMapsResult, type RuntimeEnv, type RuntimeMapsProvider, type RuntimeSyncMapsResult, SERVER_DIR, SERVER_FUNCTIONS_DIR, SHARED_DIR, SRC_DIR, type SecretsResolvedListener, type ServiceDefinition, type ServicesConfigShape, type SessionCreatedPayload, type SessionLogoutInput, type SessionProvider, type SessionRevokedPayload, type SessionSaveResult, type SocketMiddleware, type SpanHandle, type SpanResult, type SyncErrorPayload, type SyncHookHandler, type SyncHookName, type SyncHookPayloads, TSCONFIG_ALIAS_FILES, type TranslateFunction, type TranslateInput, UNKNOWN_CLIENT_IP, UPLOADS_DIR, type ValidationResult$1 as ValidationResult, abortAllForSocket, abortApiByResponseIndex, abortSyncByCb, acquireLease, allowedOrigin, type apiMessage, appendErrorTracker, applyCookiePrefixConstraints, applyErrorFormatter, applySocketMiddlewares, applyStrayKeyPrefix, attachSocketRedisAdapter, bootstrapEnv, captureException, captureExceptionAcrossTrackers, captureMessage, captureMessageAcrossTrackers, checkRateLimit, clearAllHooks, clearAllRateLimits, clearRateLimit, clearSocketMiddlewares, collectSynchronizedEnvKeys, computeSynchronizedEnvHashes, consumeOneTimeToken, consumeOneTimeTokenJson, createLocalizedNormalizer, createRegistry, defaultRateLimitStrategy, defaultRedisKeyFormatter, defaultRoomNameFormatter, deriveTokenBucketId, describeHealthHashConfig, dispatchHook, dispatchSyncHook, ensurePeerDepInstalled, env, escapeHtml, extractLanguageFromHeader, extractTokenFromRequest, extractTokenFromSocket, flushErrorTrackers, formatKey, formatRoomName, getActiveErrorTrackers, getAvatarConfig, getBindAddress, getCookieValue, getCsrfConfig, getCurrentErrorTrackerIdentity, getDbHealthCheck, getDeployConfig, getEffectiveHttpMethod, getEmailSender, getEmailSenderByName, getEnv, getEnvFiles, getErrorFormatter, getGeneratedApiDocsPath, getGeneratedApiSchemasPath, getGeneratedSocketTypesPath, getIoInstance, getLocaleReloader, getLocalizedNormalizer, getParams, getPrismaClient, getPrismaClientFor, getPrismaClientKeys, getPublicDir, getRateLimitStatus, getRateLimitStrategy, getRedactedLogKeys, getRedisClient, getRedisClientFor, getRedisClientKeys, getRedisConnectionOptions, getRedisKeyFormatter, getRegisteredSessionProvider, getRoomNameFormatter, getRuntimeApiMaps, getRuntimeSyncMaps, getServerDir, getServerFunctionDirs, getServerFunctionsDir, getServicesConfig, getSharedDir, getSocketMiddlewares, getSrcDir, getUploadsDir, hasCookie, hashSynchronizedValue, hashSynchronizedValueWith, inferHttpMethod, initConsolelog, initSharedSentry, isDbHealthCheckRegistered, isDeployConfigRegistered, isEmailSenderRegistered, isFalsy, isGetMethodName, isLocalizedNormalizerRegistered, isLoopbackIp, isMethodAllowed, isPrismaClientRegistered, isPrismaClientResolvable, isProduction, isRedactedLogKey, isRedisClientRegistered, isRuntimeMapsProviderRegistered, isServicesConfigRegistered, isSessionProviderRegistered, issueOneTimeToken, listEmailSenderNames, loadEnvFiles, loadPeer, normalizeErrorResponse, normalizeOrigin, notifySecretsResolved, oneTimeTokenKey, performLogout, prisma, processUpload, readBootUuid, readSession, rebuildDefaultRedisClient, recordMetricAcrossTrackers, redis, registerApiAbortController, registerAvatarConfig, registerBindAddress, registerCsrfConfig, registerDbHealthCheck, registerDeployConfig, registerEmailSender, registerEmailSenders, registerErrorFormatter, registerErrorTracker, registerErrorTrackers, registerHook, registerLocaleReloader, registerLocalizedNormalizer, registerPreCaptureFilter, registerPrismaClient, registerRateLimitStrategy, registerRedactedLogKeys, registerRedisClient, registerRedisKeyFormatter, registerRoomNameFormatter, registerRuntimeMapsProvider, registerSecretsResolvedListener, registerServicesConfig, registerSessionProvider, registerSocketMiddleware, registerStrayPrefixCommand, registerSyncAbortController, registerSyncHook, releaseLease, removeSession, renewLease, resetClientsForTests, resetCsrfConfigForTests, resetDbHealthCheckForTests, resetDefaultRedisClient, resetRedactedLogKeysForTests, resetRedisKeyFormatterForTests, resetSessionProviderForTests, resolveClientIp, resolveEnvKey, resolveErrorMessage, resolveFromRoot, resolveHealthHashConfig, resolveHealthHashConfigFromDescriptor, runWithErrorTrackerIdentity, runWithErrorTrackerIdentityScope, sanitizeErrorString, sanitizeErrorStrings, sanitizeForLog, serveAvatar, setCurrentErrorTrackerIdentity, setErrorTrackerUser, setIoInstance, setSentryUser, startSpan, startSpanAcrossTrackers, startSpanHandle, type syncMessage, tryCatch, tryCatchSync, unregisterApiAbortController, unregisterSyncAbortController, validateInputByType, validateRequest, writeBootUuid, writeSession };
|
package/dist/index.js
CHANGED
|
@@ -613,6 +613,15 @@ var notifySecretsResolved = (changedKeys) => {
|
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
};
|
|
616
|
+
var GLOBAL_LISTENERS_SYMBOL = /* @__PURE__ */ Symbol.for("luckystack.secretsResolved.listeners");
|
|
617
|
+
var getGlobalSecretsResolvedListeners = () => {
|
|
618
|
+
const existing = Reflect.get(globalThis, GLOBAL_LISTENERS_SYMBOL);
|
|
619
|
+
if (Array.isArray(existing)) return existing;
|
|
620
|
+
const created = [];
|
|
621
|
+
Reflect.set(globalThis, GLOBAL_LISTENERS_SYMBOL, created);
|
|
622
|
+
return created;
|
|
623
|
+
};
|
|
624
|
+
getGlobalSecretsResolvedListeners().push(notifySecretsResolved);
|
|
616
625
|
|
|
617
626
|
// src/redis.ts
|
|
618
627
|
var cachedDefault = null;
|
|
@@ -624,11 +633,10 @@ var readPositiveIntEnv = (name, fallback) => {
|
|
|
624
633
|
const parsed = Number.parseInt(raw, 10);
|
|
625
634
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
626
635
|
};
|
|
627
|
-
var
|
|
628
|
-
if (cachedDefault) return cachedDefault;
|
|
636
|
+
var constructRedisClient = () => {
|
|
629
637
|
const maxReconnectAttempts = readPositiveIntEnv("LUCKYSTACK_REDIS_MAX_RECONNECTS", DEFAULT_MAX_REDIS_RECONNECT_ATTEMPTS);
|
|
630
638
|
const maxBackoffMs = readPositiveIntEnv("LUCKYSTACK_REDIS_MAX_BACKOFF_MS", DEFAULT_MAX_REDIS_BACKOFF_MS);
|
|
631
|
-
|
|
639
|
+
const client = new Redis({
|
|
632
640
|
host: env.REDIS_HOST,
|
|
633
641
|
port: Number.parseInt(env.REDIS_PORT, 10),
|
|
634
642
|
...process.env.REDIS_USER && { username: process.env.REDIS_USER },
|
|
@@ -643,21 +651,26 @@ var buildDefaultRedisClient = () => {
|
|
|
643
651
|
return Math.min(times * 50, maxBackoffMs);
|
|
644
652
|
}
|
|
645
653
|
});
|
|
646
|
-
|
|
654
|
+
client.on("ready", async () => {
|
|
647
655
|
getLogger().info("Connected to Redis");
|
|
648
656
|
});
|
|
649
|
-
|
|
657
|
+
client.on("error", (err) => {
|
|
650
658
|
const message = String(err?.message ?? err);
|
|
651
659
|
const password = process.env.REDIS_PASSWORD ?? "";
|
|
652
660
|
if (/WRONGPASS|NOAUTH|invalid username-password/i.test(message) && /_V\d+$/i.test(password)) {
|
|
653
661
|
getLogger().error(
|
|
654
|
-
`Redis auth failed and REDIS_PASSWORD ("${password}") looks like an UNRESOLVED secret-manager pointer. The default Redis client was likely built before secret-manager init ran. The framework now
|
|
662
|
+
`Redis auth failed and REDIS_PASSWORD ("${password}") looks like an UNRESOLVED secret-manager pointer. The default Redis client was likely built before secret-manager init ran. The framework now EAGERLY REBUILDS + registers a fresh client automatically when \`config.secretManager.url\` is set (server boot) and when \`initSecretManager\` is wired with \`onApplied: notifySecretsResolved\`; if you resolve secrets by other means, call \`rebuildDefaultRedisClient()\` (or \`registerRedisClient(new Redis(getRedisConnectionOptions()))\`) after resolution. Also confirm \`REDIS_PASSWORD\` is listed in the secret-manager \`envNames\` allowlist (unset resolves nothing). See docs/luckystack/ARCHITECTURE_SECRET_MANAGER.md.`,
|
|
655
663
|
err
|
|
656
664
|
);
|
|
657
665
|
return;
|
|
658
666
|
}
|
|
659
667
|
getLogger().error("Error connecting to Redis", err);
|
|
660
668
|
});
|
|
669
|
+
return client;
|
|
670
|
+
};
|
|
671
|
+
var buildDefaultRedisClient = () => {
|
|
672
|
+
if (cachedDefault) return cachedDefault;
|
|
673
|
+
cachedDefault = constructRedisClient();
|
|
661
674
|
return cachedDefault;
|
|
662
675
|
};
|
|
663
676
|
var resetDefaultRedisClient = () => {
|
|
@@ -669,10 +682,23 @@ var resetDefaultRedisClient = () => {
|
|
|
669
682
|
} catch {
|
|
670
683
|
}
|
|
671
684
|
};
|
|
685
|
+
var rebuildDefaultRedisClient = () => {
|
|
686
|
+
const previousRegistered = isRedisClientRegistered() ? getRedisClient() : null;
|
|
687
|
+
resetDefaultRedisClient();
|
|
688
|
+
const client = constructRedisClient();
|
|
689
|
+
registerRedisClient(client);
|
|
690
|
+
if (previousRegistered && previousRegistered !== client) {
|
|
691
|
+
try {
|
|
692
|
+
previousRegistered.disconnect();
|
|
693
|
+
} catch {
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return client;
|
|
697
|
+
};
|
|
672
698
|
setDefaultRedisResolver(buildDefaultRedisClient);
|
|
673
699
|
registerSecretsResolvedListener((changedKeys) => {
|
|
674
700
|
if (changedKeys === void 0 || changedKeys.some((key) => /^REDIS_/i.test(key))) {
|
|
675
|
-
|
|
701
|
+
rebuildDefaultRedisClient();
|
|
676
702
|
}
|
|
677
703
|
});
|
|
678
704
|
var getRedisConnectionOptions = () => ({
|
|
@@ -2295,6 +2321,7 @@ export {
|
|
|
2295
2321
|
processUpload,
|
|
2296
2322
|
readBootUuid,
|
|
2297
2323
|
readSession,
|
|
2324
|
+
rebuildDefaultRedisClient,
|
|
2298
2325
|
recordMetricAcrossTrackers,
|
|
2299
2326
|
redis,
|
|
2300
2327
|
registerApiAbortController,
|