@luckystack/core 0.2.7 → 0.3.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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a6 as ErrorParam, a7 as ErrorResponseInput, a8 as NormalizedErrorResponse, a9 as HealthHashConfig, aa as DeepPartial, B as BaseSessionLayout, b as AuthProps } from './pageRouteValidation-B2YF7g3A.js';
2
- export { ab as ApiConfig, A as ApiMethodMap, a as AppConfig, ac as AuthConfig, ad as AuthRateLimitConfig, ae as CorsConfig, D as DEFAULT_PAGE_ROUTE_RULES, af as DEFAULT_PROJECT_CONFIG, ag as DevConfig, ah as HttpConfig, H as HttpMethodLiteral, ai as HttpStreamConfig, aj as INVALID_ERROR_RESPONSE_CODE, L as Logger, c as LoggerContext, d as LoggingConfig, N as Notifier, e as NotifyInput, f as NotifyParam, ak as OfflineQueueConfig, P as PagePathValidationResult, g as PageRouteRules, al as PasswordPolicyConfig, am as PathsConfig, h as ProjectConfig, an as ProjectConfigInput, ao as QueueDropReason, ap as RateLimitIdentity, aq as RateLimitIdentityParams, R as RateLimitingConfig, S as SOCKETSTATUS, ar as SecurityHeadersConfig, as as ServiceRouteParseError, at as ServiceRouteParseResult, au as ServiceRouteParseSuccess, i as SessionConfig, j as SessionLocation, av as SocketConfig, aw as SyncConfig, ax as SyncFlushPressureConfig, ay as SyncStreamThrottleConfig, az as TransportRouteParseError, aA as TransportRouteParseResult, aB as TransportRouteParseSuccess, aC as ValidationConfig, k as buildApiResponseEventName, l as buildApiStreamEventName, m as buildGetJoinedRoomsResponseEventName, n as buildJoinRoomResponseEventName, o as buildLeaveRoomResponseEventName, p as buildSyncProgressEventName, q as buildSyncResponseEventName, r as clearCsrfToken, aD as createDevLogger, aE as deepMerge, aF as defaultHttpStatusForResponse, s as enqueueApiRequest, t as enqueueSyncRequest, u as flushApiQueue, v as flushSyncQueue, w as getApiQueueSize, x as getCsrfToken, y as getLogger, z as getNotifier, C as getProjectConfig, aG as getProjectName, E as getRegisteredApiMethod, F as getSyncQueueSize, G as httpFetch, I as incrementResponseIndex, J as isApiMethodMapRegistered, aH as isErrorParamArray, aI as isLoggerRegistered, K as isOnline, aJ as isPlainObject, M as isProjectConfigRegistered, O as normalizeErrorResponseCore, Q as notify, T as parseServiceRouteName, aK as parseTransportRouteName, U as registerApiMethodMap, V as registerLogger, W as registerNotifier, X as registerProjectConfig, Y as removeApiQueueItem, Z as removeApiQueueItemsByKey, _ as removeSyncQueueItem, aL as resetLoggerForTests, $ as setSocket, a0 as sleep, a1 as socket, a2 as socketEventNames, a3 as statusContent, a4 as validatePagePath, a5 as waitForSocket } from './pageRouteValidation-B2YF7g3A.js';
1
+ import { a6 as ErrorParam, a7 as ErrorResponseInput, a8 as NormalizedErrorResponse, a9 as HealthHashConfig, aa as DeepPartial, B as BaseSessionLayout, b as AuthProps } from './pageRouteValidation-BwSFuQL9.js';
2
+ export { ab as ApiConfig, A as ApiMethodMap, a as AppConfig, ac as AuthConfig, ad as AuthRateLimitConfig, ae as CorsConfig, D as DEFAULT_PAGE_ROUTE_RULES, af as DEFAULT_PROJECT_CONFIG, ag as DevConfig, ah as HttpConfig, H as HttpMethodLiteral, ai as HttpStreamConfig, aj as INVALID_ERROR_RESPONSE_CODE, L as Logger, c as LoggerContext, d as LoggingConfig, N as Notifier, e as NotifyInput, f as NotifyParam, ak as OfflineQueueConfig, P as PagePathValidationResult, g as PageRouteRules, al as PasswordPolicyConfig, am as PathsConfig, h as ProjectConfig, an as ProjectConfigInput, ao as QueueDropReason, ap as RateLimitIdentity, aq as RateLimitIdentityParams, R as RateLimitingConfig, S as SOCKETSTATUS, ar as SecurityHeadersConfig, as as ServiceRouteParseError, at as ServiceRouteParseResult, au as ServiceRouteParseSuccess, i as SessionConfig, j as SessionLocation, av as SocketConfig, aw as SyncConfig, ax as SyncFlushPressureConfig, ay as SyncStreamThrottleConfig, az as TransportRouteParseError, aA as TransportRouteParseResult, aB as TransportRouteParseSuccess, aC as ValidationConfig, k as buildApiResponseEventName, l as buildApiStreamEventName, m as buildGetJoinedRoomsResponseEventName, n as buildJoinRoomResponseEventName, o as buildLeaveRoomResponseEventName, p as buildSyncProgressEventName, q as buildSyncResponseEventName, r as clearCsrfToken, aD as createDevLogger, aE as deepMerge, aF as defaultHttpStatusForResponse, s as enqueueApiRequest, t as enqueueSyncRequest, u as flushApiQueue, v as flushSyncQueue, w as getApiQueueSize, x as getCsrfToken, y as getLogger, z as getNotifier, C as getProjectConfig, aG as getProjectName, E as getRegisteredApiMethod, F as getSyncQueueSize, G as httpFetch, I as incrementResponseIndex, J as isApiMethodMapRegistered, aH as isErrorParamArray, aI as isLoggerRegistered, K as isOnline, aJ as isPlainObject, M as isProjectConfigRegistered, O as normalizeErrorResponseCore, Q as notify, T as parseServiceRouteName, aK as parseTransportRouteName, U as registerApiMethodMap, V as registerLogger, W as registerNotifier, X as registerProjectConfig, Y as removeApiQueueItem, Z as removeApiQueueItemsByKey, _ as removeSyncQueueItem, aL as resetLoggerForTests, $ as setSocket, a0 as sleep, a1 as socket, a2 as socketEventNames, a3 as statusContent, a4 as validatePagePath, a5 as waitForSocket } from './pageRouteValidation-BwSFuQL9.js';
3
3
  export { ApiTypeMap, StreamPayload, SyncTypeMap } from './apiTypeStubs.js';
4
4
  import { Server, Socket } from 'socket.io';
5
5
  import { z } from 'zod';
@@ -379,6 +379,15 @@ interface DeployRoutingShape {
379
379
  missingServiceErrorCode?: string;
380
380
  enableUnhealthyFallback?: boolean;
381
381
  strictBootHandshake?: boolean;
382
+ /**
383
+ * Opt INTO the boot-handshake's synchronized-env (cookie/session secret) drift
384
+ * check. DEFAULT false — the router stays a dumb proxy that holds NO backend
385
+ * secrets. Comparing synchronized-env hashes requires the router process to
386
+ * carry the same SESSION_SECRET etc. as the backends, which most deployments
387
+ * deliberately avoid; the always-on shared-Redis handshake is unaffected. Set
388
+ * true only when you intentionally give the router the synchronized secrets.
389
+ */
390
+ verifySynchronizedEnv?: boolean;
382
391
  /** Default port the router listens on when ROUTER_PORT env var is unset (default 4000). */
383
392
  defaultRouterPort?: number;
384
393
  /** Default ms between health polls when not specified per-call (default 5000). */
@@ -412,6 +421,30 @@ interface DeployRoutingShape {
412
421
  * rejecting with 413. DEFAULT undefined → router uses its built-in default.
413
422
  */
414
423
  maxRequestBodyBytes?: number;
424
+ /**
425
+ * Max size (bytes) of the upgrade `head` buffer the WS proxy forwards to the
426
+ * upstream during a WebSocket handshake. An over-cap head is rejected (the
427
+ * client socket is destroyed) BEFORE the upstream leg opens, so a client
428
+ * cannot push an unbounded pre-upgrade buffer through the router. DEFAULT
429
+ * undefined → router uses its built-in default (64 KiB).
430
+ */
431
+ wsMaxHeadBytes?: number;
432
+ /**
433
+ * Idle-timeout (ms) for an UPGRADED WebSocket pipe: when no bytes flow in
434
+ * either direction for this long, the router tears the proxied pair down.
435
+ * Bounds an otherwise-unbounded pre/post-auth pipe a client could hold open
436
+ * against the router. The timer resets on any activity. DEFAULT undefined →
437
+ * router uses its built-in default (120000 ms = 2 min). Set `0` to disable.
438
+ */
439
+ wsIdleTimeoutMs?: number;
440
+ /**
441
+ * Per-connection byte budget for an UPGRADED WebSocket pipe: when the total
442
+ * bytes piped across both legs exceed this cap, the router tears the proxied
443
+ * pair down. Bounds how much a single connection can stream through the
444
+ * router. DEFAULT undefined → router uses its built-in default (100 MiB). Set
445
+ * `false` to disable the cap (unbounded).
446
+ */
447
+ wsMaxBytesPerConnection?: number | false;
415
448
  }
416
449
  interface DeployDevelopmentShape {
417
450
  enableFallbackRouting?: boolean;
@@ -497,6 +530,18 @@ interface ErrorTracker {
497
530
  setUser: (user: ErrorTrackerUser | null) => void;
498
531
  setContext?: (key: string, context: ErrorTrackerContext | null) => void;
499
532
  startSpan?: <T>(name: string, op: string, fn: () => T) => T;
533
+ /**
534
+ * Optional handle-style span (#62): open a span NOW and close it later via the
535
+ * returned handle's `finish()`. Unlike {@link startSpan} (which wraps a single
536
+ * synchronous `fn`), this fits an open-at-preExecute / close-at-postExecute
537
+ * request lifecycle that spans awaits. When present, the registry-level
538
+ * {@link startSpanHandle} delegates to the FIRST registered adapter that
539
+ * implements it so the request span reaches an adapter-only backend
540
+ * (Datadog/PostHog/custom), not just the legacy Sentry SDK path.
541
+ */
542
+ startSpanHandle?: (name: string, op: string) => {
543
+ finish: () => void;
544
+ };
500
545
  recordMetric?: (name: string, value: number, tags?: Record<string, string>) => void;
501
546
  beforeSend?: (event: ErrorTrackerEvent) => ErrorTrackerEvent | null;
502
547
  /**
@@ -567,7 +612,7 @@ interface SpanHandle {
567
612
  /** Milliseconds elapsed at the moment `finish()` first ran (0 before). */
568
613
  readonly durationMs: number;
569
614
  }
570
- declare const startSpanHandle: (_name: string, _op: string) => SpanHandle;
615
+ declare const startSpanHandle: (name: string, op: string) => SpanHandle;
571
616
 
572
617
  declare const EnvSchema: z.ZodObject<{
573
618
  NODE_ENV: z.ZodDefault<z.ZodEnum<{
package/dist/index.js CHANGED
@@ -49,7 +49,7 @@ import {
49
49
  tryCatchSync,
50
50
  validatePagePath,
51
51
  waitForSocket
52
- } from "./chunk-6YKLU3ZR.js";
52
+ } from "./chunk-H64EC7Q6.js";
53
53
  import {
54
54
  DEFAULT_PROJECT_CONFIG,
55
55
  deepMerge,
@@ -58,7 +58,7 @@ import {
58
58
  isPlainObject,
59
59
  isProjectConfigRegistered,
60
60
  registerProjectConfig
61
- } from "./chunk-7FGFIIBD.js";
61
+ } from "./chunk-6BBJ2Q6I.js";
62
62
  import {
63
63
  DEFAULT_REDACTED_LOG_KEYS,
64
64
  DEPTH_TRUNCATED_PLACEHOLDER,
@@ -96,7 +96,7 @@ import {
96
96
  startSpan,
97
97
  startSpanAcrossTrackers,
98
98
  startSpanHandle
99
- } from "./chunk-OHGJSQZE.js";
99
+ } from "./chunk-TGYBUT4N.js";
100
100
  import {
101
101
  createRegistry
102
102
  } from "./chunk-USQA6QTX.js";
@@ -1520,7 +1520,7 @@ var getRateLimitStatus = async (key, limit) => {
1520
1520
  };
1521
1521
  var clearRateLimit = async (key) => strategyRegistry.get().clear(key);
1522
1522
  var clearAllRateLimits = async () => {
1523
- if (process.env.NODE_ENV === "production") {
1523
+ if (resolveEnvKey() === "production") {
1524
1524
  throw new Error("[RateLimiter] clearAllRateLimits() is not allowed in production. Use clearRateLimit(key) for scoped resets.");
1525
1525
  }
1526
1526
  return strategyRegistry.get().clearAll();
@@ -1885,8 +1885,8 @@ var validateInputByType = async ({
1885
1885
  if (!typeText || typeText.trim() === "" || typeText.trim() === "any") {
1886
1886
  return { status: "success" };
1887
1887
  }
1888
- if (process.env.NODE_ENV === "production") {
1889
- const { getProjectConfig: getProjectConfig2 } = await import("./projectConfig-BVO7PJRO.js");
1888
+ if (resolveEnvKey() === "production") {
1889
+ const { getProjectConfig: getProjectConfig2 } = await import("./projectConfig-FITPOAMC.js");
1890
1890
  if (getProjectConfig2().validation.runtimeMode === "off") {
1891
1891
  return { status: "success" };
1892
1892
  }