@luckystack/core
v0.2.5
Published
LuckyStack core: socket-first transport contracts, Redis adapter, project-config registry, hooks registry, response normalization, rate limiting, and shared session types. Foundation for every other @luckystack/* package.
Downloads
3,454
Maintainers
Readme
@luckystack/core
Foundation package for LuckyStack. Socket-first transport contracts, Redis adapter, project-config registry, hooks registry, response normalization, rate limiting, and shared session types.
Every other @luckystack/* package depends on this one.
Install
npm install @luckystack/corePeer dependencies you must install separately:
npm install @prisma/client ioredis socket.io socket.io-client zodQuickstart
The core package is mostly consumed transitively through @luckystack/server, @luckystack/api, etc. You typically only touch it directly to register your project config and to call low-level utilities.
import { registerProjectConfig, getProjectConfig, notify, redis, prisma } from '@luckystack/core';
registerProjectConfig({
defaultLanguage: 'en',
session: { expiryDays: 30, basedToken: false, perUser: 'multiple' },
auth: {
emailMaxLength: 254,
passwordMinLength: 8,
passwordMaxLength: 128,
nameMaxLength: 64,
oauthStateTtlSeconds: 600,
},
// ...see ProjectConfig type for the full surface
});
const config = getProjectConfig();Subpath: @luckystack/core/client
Browser-safe surface for the React/Vite bundle. Re-exports the pieces consumed by @luckystack/sync's client transport (projectConfig, notifier, socketState, offlineQueue, responseNormalizer, serviceRoute, socketEvents, socketStatusTypes, apiTypeStubs, sessionTypes).
import { socket, isOnline, enqueueApiRequest } from '@luckystack/core/client';Public API (server entry)
| Group | Exports |
| --- | --- |
| Project config | registerProjectConfig, getProjectConfig, getProjectName, isProjectConfigRegistered, DEFAULT_PROJECT_CONFIG. Types: ProjectConfig, ProjectConfigInput, LoggingConfig, RateLimitingConfig, SessionConfig, SentryConfig, SentrySampleRates, HttpConfig, HttpStreamConfig, SecurityHeadersConfig, CorsConfig, AuthConfig, SocketConfig, SyncConfig, SyncStreamThrottleConfig, OfflineQueueConfig, DevConfig, PathsConfig, EmailConfig, EmailLoggingConfig, EmailEnvVarsConfig, EmailDefaultsConfig. getProjectName() is the canonical way to read the project's Redis-prefix string — it resolves at call time in this order: (1) projectConfig.session.projectName if a consumer set it, (2) process.env.PROJECT_NAME (read after dotenv has loaded), (3) literal 'luckystack' as the absolute fallback. Reach for it from any framework or project code that needs the prefix instead of duplicating the env-read pattern. |
| Deploy + services config | registerDeployConfig, getDeployConfig, isDeployConfigRegistered, registerServicesConfig, getServicesConfig, isServicesConfigRegistered. Types: DeployConfigShape, DeployResourceShape, DeployEnvironmentShape, DeployRoutingShape, DeployDevelopmentShape, ServicesConfigShape, ServiceDefinition, PresetDefinition |
| Runtime maps | registerRuntimeMapsProvider, getRuntimeApiMaps, getRuntimeSyncMaps. Types: RuntimeMapsProvider, RuntimeApiMapsResult, RuntimeSyncMapsResult |
| DI clients | registerPrismaClient, registerRedisClient, getPrismaClient, getRedisClient, isPrismaClientRegistered, isRedisClientRegistered |
| Notifier | registerNotifier, getNotifier, notify. Types: Notifier, NotifyInput, NotifyParam |
| Email registry | registerEmailSender, getEmailSender, isEmailSenderRegistered. Types: EmailSender, EmailMessage, EmailResult (re-exported from @luckystack/email for convenience) |
| Logger | registerLogger, getLogger, isLoggerRegistered, resetLoggerForTests, createDevLogger. Types: Logger, LoggerContext. Default logger is a thin wrapper over console.{debug,info,warn,error} with no color codes — safe in production. Call registerLogger(createDevLogger()) from a dev-only entry to opt into the colored terminal output (which still depends on initConsolelog() to render the trailing color string). Plug in Pino / Winston / Datadog by registering an object that satisfies Logger. |
| Redacted log keys | registerRedactedLogKeys, getRedactedLogKeys, isRedactedLogKey, resetRedactedLogKeysForTests |
| Avatar / uploads | registerAvatarConfig, getAvatarConfig, DEFAULT_AVATAR_CONFIG, serveAvatar, processUpload. Types: AvatarConfig, AvatarConfigInput, ProcessUploadInput, ProcessUploadResult. Path-traversal guard: serveAvatar rejects any fileId that does not match /^[A-Za-z0-9_-]{1,128}$/ with a 400 before touching the filesystem — .., slashes, and other path-separator characters cannot escape the configured upload directory. processUpload wraps the project-supplied encode/save callback with the framework's onUploadStart (stoppable) and onUploadComplete hook contract so consumer upload routes don't need to plumb the hooks themselves. Returns { status: 'success', sizeBytes }, { status: 'rejected', errorCode } (when onUploadStart returned a stop signal), or { status: 'error', reason, cause? }. See src/settings/_api/updateUser_v1.ts for the canonical avatar usage. |
| Bind address | registerBindAddress({ ip, port }), getBindAddress() → { ip, port: string }. createLuckyStackServer registers the resolved listen address at boot so framework code (e.g. checkOrigin building the same-origin entry) reads it from the registry instead of SERVER_IP / SERVER_PORT env vars — no more drift when consumers configure programmatically via createLuckyStackServer({ ip, port }). Resolution at call time: (1) registerBindAddress(...) value, (2) process.env.SERVER_IP / SERVER_PORT (legacy), (3) '127.0.0.1' / '' fallback. |
| Locale reloader | registerLocaleReloader, getLocaleReloader. Type: LocaleReloader |
| Hooks (async) | registerHook, dispatchHook, clearAllHooks. Types: HookName, HookHandler, HookResult, HookStopSignal, HookPayloads, DispatchResult, HookSessionShape. Canonical payload types: PreApiValidatePayload, PostApiValidatePayload, PreApiExecutePayload, PostApiExecutePayload, PreApiRespondPayload, PostApiRespondPayload, ApiResponseEnvelope, PreSyncFanoutPayload, PostSyncFanoutPayload, ApiErrorPayload, SyncErrorPayload, RateLimitExceededPayload, CorsRejectedPayload, CsrfMismatchPayload, PreSessionRefreshPayload, PostSessionRefreshPayload, OnUploadStartPayload, OnUploadCompletePayload. Feature-package payloads (Pre/PostLogin, Pre/PostRegister, Pre/PostLogout, Pre/PostSessionCreate, Pre/PostSessionDelete, Pre/PostEmailSend, Pre/PostPresenceUpdate, socket lifecycle, etc.) augment HookPayloads from their owning packages — see those packages' READMEs. |
| Hooks (sync, mutators) | registerSyncHook, dispatchSyncHook. Types: SyncHookName, SyncHookHandler, SyncHookPayloads, PreErrorNormalizePayload, PostErrorNormalizePayload. Sync hook handlers must be synchronous (no async), mutate the payload object in place, and cannot stop the flow. Use them only for hot-path mutators like error-code remapping. |
| Session types | BaseSessionLayout, SessionLocation, AuthProps |
| Socket | setIoInstance, getIoInstance, attachSocketRedisAdapter, socket, setSocket, incrementResponseIndex, waitForSocket. Types: SOCKETSTATUS, statusContent, apiMessage, syncMessage |
| Auth helpers | extractTokenFromSocket, extractTokenFromRequest, validateRequest, isFalsy, allowedOrigin. Types: ValidationResult |
| Rate limiting | checkRateLimit, getRateLimitStatus, clearRateLimit, clearAllRateLimits |
| Validation | validateInputByType (resolves to @luckystack/devkit lazily in dev) |
| Persistence + env | redis, prisma, db exports, env exports |
| Boot | writeBootUuid, readBootUuid, resolveEnvKey, collectSynchronizedEnvKeys, computeSynchronizedEnvHashes, hashSynchronizedValue, initConsolelog |
| Offline queue | isOnline, enqueueApiRequest, enqueueSyncRequest, removeApiQueueItem, removeSyncQueueItem, removeApiQueueItemsByKey, flushApiQueue, flushSyncQueue, getApiQueueSize, getSyncQueueSize |
| CSRF | getCsrfToken, clearCsrfToken, httpFetch |
| Cookies + paths | All exports of ./cookies, ./httpApiUtils, and ./paths (getGeneratedApiDocsPath, getApiMethodMapPath, etc.) |
| Misc | tryCatch, sleep, getParams, response normalizers (normalizeErrorResponse, extractLanguageFromHeader, …), service-route helpers, socket-event constants |
Note:
apiRequestis exported from@luckystack/core/client, not from the server entry. The server barrel does not pull React-coupled code.
Dependencies
- Runtime:
@socket.io/redis-adapter,dotenv - Peer (canonical ranges, standardized 2026-05-07):
@prisma/client@^6.19.0ioredis@^5.10.0socket.io@^4.8.0socket.io-client@^4.8.0zod@^3.25.0
License
MIT — see LICENSE.
