@luckystack/core 0.14.0 → 0.15.0

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/bootUuid.d.ts +16 -0
  3. package/dist/{chunk-PN2FPJXI.js → chunk-55YXIACQ.js} +1 -1
  4. package/dist/chunk-55YXIACQ.js.map +1 -0
  5. package/dist/{chunk-RC7ZQBO6.js → chunk-EZIBIQXO.js} +3 -3
  6. package/dist/{chunk-C4AK6P5D.js → chunk-NJULJZ3N.js} +29 -17
  7. package/dist/chunk-NJULJZ3N.js.map +1 -0
  8. package/dist/{chunk-6UPWMV6L.js → chunk-YKVBUWB6.js} +2 -2
  9. package/dist/chunk-YKVBUWB6.js.map +1 -0
  10. package/dist/client.d.ts +1 -1
  11. package/dist/client.js +74 -12
  12. package/dist/client.js.map +1 -1
  13. package/dist/config.js +2 -2
  14. package/dist/deployConfigRegistry.d.ts +3 -1
  15. package/dist/emailRegistry.d.ts +2 -1
  16. package/dist/errorTrackerIdentity.d.ts +2 -0
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +134 -31
  19. package/dist/index.js.map +1 -1
  20. package/dist/localSocketEnumerationGuard.d.ts +2 -1
  21. package/dist/middlewareRegistry.d.ts +13 -1
  22. package/dist/{projectConfig-EOJRMH36.js → projectConfig-6QNMG5GZ.js} +2 -2
  23. package/dist/projectConfig.d.ts +13 -9
  24. package/dist/react/languageOverride.d.ts +8 -0
  25. package/dist/redactedLogKeys.d.ts +2 -0
  26. package/dist/roomNameFormatterRegistry.d.ts +7 -5
  27. package/dist/{sentrySetup-T7535RYZ.js → sentrySetup-MZTUOMHL.js} +3 -3
  28. package/dist/sessionProviderRegistry.d.ts +14 -6
  29. package/package.json +1 -1
  30. package/dist/chunk-6UPWMV6L.js.map +0 -1
  31. package/dist/chunk-C4AK6P5D.js.map +0 -1
  32. package/dist/chunk-PN2FPJXI.js.map +0 -1
  33. /package/dist/{chunk-RC7ZQBO6.js.map → chunk-EZIBIQXO.js.map} +0 -0
  34. /package/dist/{projectConfig-EOJRMH36.js.map → projectConfig-6QNMG5GZ.js.map} +0 -0
  35. /package/dist/{sentrySetup-T7535RYZ.js.map → sentrySetup-MZTUOMHL.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -49,7 +49,7 @@ export type { BaseSessionLayout, SessionLocation, AuthProps, Jsonify } from './s
49
49
  export * from './sentrySetup.js';
50
50
  export { registerErrorTracker, registerErrorTrackers, appendErrorTracker, getActiveErrorTrackers, captureExceptionAcrossTrackers, captureMessageAcrossTrackers, setErrorTrackerUser, recordMetricAcrossTrackers, startSpanAcrossTrackers, startSpanHandle, registerPreCaptureFilter, flushErrorTrackers, sanitizeErrorString, sanitizeErrorStrings, } from './errorTrackerRegistry.js';
51
51
  export type { ErrorTracker, ErrorTrackerContext, ErrorTrackerUser, ErrorTrackerEvent, SpanResult, SpanHandle, PreCaptureFilter, } from './errorTrackerRegistry.js';
52
- export { runWithErrorTrackerIdentity, runWithErrorTrackerIdentityScope, setCurrentErrorTrackerIdentity, getCurrentErrorTrackerIdentity, } from './errorTrackerIdentity.js';
52
+ export { runWithErrorTrackerIdentity, runWithErrorTrackerIdentityScope, setCurrentErrorTrackerIdentity, getCurrentErrorTrackerIdentity, hasErrorTrackerIdentityScope, } from './errorTrackerIdentity.js';
53
53
  export * from './env.js';
54
54
  export * from './db.js';
55
55
  export { registerDbHealthCheck, getDbHealthCheck, isDbHealthCheckRegistered, resetDbHealthCheckForTests, } from './dbHealthCheck.js';
@@ -63,7 +63,7 @@ export type { RedisKeyFormatter } from './redisKeyFormatter.js';
63
63
  export { acquireLease, renewLease, releaseLease } from './lease.js';
64
64
  export { DEFAULT_CLIENT_KEY, registerPrismaClient, registerRedisClient, getPrismaClient, getRedisClient, getPrismaClientFor, getRedisClientFor, getPrismaClientKeys, getRedisClientKeys, isPrismaClientRegistered, isRedisClientRegistered, resetClientsForTests, } from './clients.js';
65
65
  export { attachSocketRedisAdapter, resolveSocketAdapterKey } from './socketRedisAdapter.js';
66
- export { writeBootUuid, readBootUuid, refreshBootUuid, startBootUuidHeartbeat, resolveEnvKey, BOOT_KEY_PREFIX, type BootUuidHeartbeat, } from './bootUuid.js';
66
+ export { writeBootUuid, readBootUuid, refreshBootUuid, startBootUuidHeartbeat, resolveEnvKey, BOOT_KEY_PREFIX, bootUuidKey, type BootUuidHeartbeat, } from './bootUuid.js';
67
67
  export { collectSynchronizedEnvKeys, computeSynchronizedEnvHashes, hashSynchronizedValue, hashSynchronizedValueWith, resolveHealthHashConfig, describeHealthHashConfig, resolveHealthHashConfigFromDescriptor, } from './synchronizedEnvHashes.js';
68
68
  export type { HealthHashDescriptor } from './synchronizedEnvHashes.js';
69
69
  export { initConsolelog } from './consoleLog.js';
@@ -89,7 +89,7 @@ export { extractTokenFromRequest } from './extractTokenFromRequest.js';
89
89
  export { resolveClientIp, isLoopbackIp, UNKNOWN_CLIENT_IP, deriveTokenBucketId } from './resolveClientIp.js';
90
90
  export type { ResolveClientIpParams } from './resolveClientIp.js';
91
91
  export { registerSessionProvider, getRegisteredSessionProvider, isSessionProviderRegistered, resetSessionProviderForTests, readSession, writeSession, removeSession, performLogout, } from './sessionProviderRegistry.js';
92
- export type { SessionProvider, SessionSaveResult, SessionLogoutInput } from './sessionProviderRegistry.js';
92
+ export type { SessionProvider, SessionSaveResult, SessionSaveOptions, SessionLogoutInput } from './sessionProviderRegistry.js';
93
93
  export { validateRequest, isFalsy } from './validateRequest.js';
94
94
  export type { ValidationResult } from './validateRequest.js';
95
95
  export { checkRateLimit, getRateLimitStatus, clearRateLimit, clearAllRateLimits, registerRateLimitStrategy, getRateLimitStrategy, defaultRateLimitStrategy, } from './rateLimiter.js';
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ import {
51
51
  tryCatchSync,
52
52
  validatePagePath,
53
53
  waitForSocket
54
- } from "./chunk-RC7ZQBO6.js";
54
+ } from "./chunk-EZIBIQXO.js";
55
55
  import {
56
56
  getDeployConfig,
57
57
  getPortOverride,
@@ -64,7 +64,7 @@ import {
64
64
  registerSecretsResolvedListener,
65
65
  registerServicesConfig,
66
66
  resetPortOverrideForTests
67
- } from "./chunk-6UPWMV6L.js";
67
+ } from "./chunk-YKVBUWB6.js";
68
68
  import {
69
69
  DEFAULT_REDACTED_LOG_KEYS,
70
70
  DEPTH_TRUNCATED_PLACEHOLDER,
@@ -98,7 +98,7 @@ import {
98
98
  startSpan,
99
99
  startSpanAcrossTrackers,
100
100
  startSpanHandle
101
- } from "./chunk-C4AK6P5D.js";
101
+ } from "./chunk-NJULJZ3N.js";
102
102
  import {
103
103
  DEFAULT_PROJECT_CONFIG,
104
104
  createRegistry,
@@ -108,7 +108,7 @@ import {
108
108
  isPlainObject,
109
109
  isProjectConfigRegistered,
110
110
  registerProjectConfig
111
- } from "./chunk-PN2FPJXI.js";
111
+ } from "./chunk-55YXIACQ.js";
112
112
 
113
113
  // src/escapeHtml.ts
114
114
  var HTML_ESCAPE_MAP = {
@@ -171,7 +171,7 @@ var registerHook = (name, handler) => {
171
171
  };
172
172
  };
173
173
  var dispatchHook = async (name, payload, options = {}) => {
174
- const handlers = hookHandlers.get(name) ?? [];
174
+ const handlers = [...hookHandlers.get(name) ?? []];
175
175
  for (const handler of handlers) {
176
176
  let result;
177
177
  try {
@@ -218,7 +218,7 @@ var registerSyncHook = (name, handler) => {
218
218
  };
219
219
  };
220
220
  var dispatchSyncHook = (name, payload) => {
221
- const handlers = syncHookHandlers.get(name) ?? [];
221
+ const handlers = [...syncHookHandlers.get(name) ?? []];
222
222
  for (const handler of handlers) {
223
223
  try {
224
224
  handler(payload);
@@ -416,8 +416,13 @@ var warnOnBunEnvAutoload = (files) => {
416
416
  var loadEnvFiles = () => {
417
417
  const files = getEnvFiles();
418
418
  warnOnBunEnvAutoload(files);
419
- for (const [index, file] of files.entries()) {
420
- loadDotenv({ path: file, override: index > 0 });
419
+ const ambientKeys = new Set(Object.keys(process.env));
420
+ const fileValues = {};
421
+ for (const file of files) {
422
+ loadDotenv({ path: file, processEnv: fileValues, override: true });
423
+ }
424
+ for (const [key, value] of Object.entries(fileValues)) {
425
+ if (!ambientKeys.has(key)) process.env[key] = value;
421
426
  }
422
427
  if (process.env.LUCKYSTACK_ENV_DEBUG) {
423
428
  reportDuplicateEnvKeys(files);
@@ -479,32 +484,42 @@ var readBound = (target, prop) => {
479
484
  const value = Reflect.get(target, prop);
480
485
  return typeof value === "function" ? value.bind(target) : value;
481
486
  };
482
- var guardSocketsMap = (map) => new Proxy(map, {
487
+ var guardSocketsMap = (map, label) => new Proxy(map, {
483
488
  get(target, prop) {
484
489
  if (ENUMERATING_MAP_MEMBERS.has(prop)) {
485
- throw new LocalSocketEnumerationError("Enumerating `io.sockets.sockets`");
490
+ throw new LocalSocketEnumerationError(`Enumerating \`${label}.sockets\``);
486
491
  }
487
492
  return readBound(target, prop);
488
493
  }
489
494
  });
490
- var guardAdapter = (adapter) => new Proxy(adapter, {
495
+ var guardAdapter = (adapter, label) => new Proxy(adapter, {
491
496
  get(target, prop) {
492
497
  if (PER_INSTANCE_ADAPTER_MEMBERS.has(prop)) {
493
- throw new LocalSocketEnumerationError(`\`io.sockets.adapter.${String(prop)}\``);
498
+ throw new LocalSocketEnumerationError(`\`${label}.adapter.${String(prop)}\``);
494
499
  }
495
500
  return readBound(target, prop);
496
501
  }
497
502
  });
498
- var guardNamespace = (namespace) => new Proxy(namespace, {
503
+ var guardNamespace = (namespace, label) => new Proxy(namespace, {
499
504
  get(target, prop) {
500
- if (prop === "adapter") return guardAdapter(target.adapter);
501
- if (prop === "sockets") return guardSocketsMap(target.sockets);
505
+ if (prop === "adapter") return guardAdapter(target.adapter, label);
506
+ if (prop === "sockets") return guardSocketsMap(target.sockets, label);
502
507
  return readBound(target, prop);
503
508
  }
504
509
  });
510
+ var isGuardableNamespace = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "adapter") === "object" && Reflect.get(value, "sockets") instanceof Map;
505
511
  var guardLocalSocketEnumeration = (io) => new Proxy(io, {
506
512
  get(target, prop) {
507
- if (prop === "sockets") return guardNamespace(target.sockets);
513
+ if (prop === "sockets") return guardNamespace(target.sockets, "io.sockets");
514
+ const value = Reflect.get(target, prop);
515
+ if (prop === "of" && typeof value === "function") {
516
+ return (...args) => {
517
+ const namespace = Reflect.apply(value, target, args);
518
+ if (!isGuardableNamespace(namespace)) return namespace;
519
+ const name = args[0];
520
+ return guardNamespace(namespace, typeof name === "string" ? `io.of('${name}')` : "io.of(\u2026)");
521
+ };
522
+ }
508
523
  return readBound(target, prop);
509
524
  }
510
525
  });
@@ -561,9 +576,7 @@ var registerEmailSender = (sender) => {
561
576
  };
562
577
  var registerEmailSenders = (senders) => {
563
578
  registry4 = { ...senders };
564
- if (senders.default) {
565
- activeSender = senders.default;
566
- }
579
+ activeSender = senders.default ?? null;
567
580
  };
568
581
  var getEmailSender = () => activeSender ?? registry4.default ?? null;
569
582
  var getEmailSenderByName = (name) => {
@@ -592,6 +605,7 @@ var setCurrentErrorTrackerIdentity = (user) => {
592
605
  if (box) box.user = user;
593
606
  };
594
607
  var getCurrentErrorTrackerIdentity = () => identityStore.getStore()?.user ?? null;
608
+ var hasErrorTrackerIdentityScope = () => identityStore.getStore() !== void 0;
595
609
 
596
610
  // src/db.ts
597
611
  import { createRequire as createRequire2 } from "module";
@@ -953,6 +967,10 @@ import { createAdapter } from "@socket.io/redis-adapter";
953
967
  import { randomUUID } from "crypto";
954
968
  var BOOT_KEY_PREFIX = "luckystack:boot:";
955
969
  var DEFAULT_BOOT_KEY_TTL_SECONDS = 3600;
970
+ var bootUuidKey = (envKey) => {
971
+ const projectName = process.env.PROJECT_NAME;
972
+ return `${BOOT_KEY_PREFIX}${projectName && projectName.length > 0 ? projectName : "luckystack"}:${envKey}`;
973
+ };
956
974
  var getBootKeyTtlSeconds = () => getDeployConfig().routing?.bootKeyTtlSeconds ?? DEFAULT_BOOT_KEY_TTL_SECONDS;
957
975
  var getBootUuidRefreshIntervalMs = () => Math.max(100, Math.floor(getBootKeyTtlSeconds() * 1e3 / 3));
958
976
  var resolveEnvKey = () => {
@@ -961,16 +979,16 @@ var resolveEnvKey = () => {
961
979
  var writeBootUuid = async (envKey) => {
962
980
  const key = envKey ?? resolveEnvKey();
963
981
  const uuid = randomUUID();
964
- await redis.set(`${BOOT_KEY_PREFIX}${key}`, uuid, "EX", getBootKeyTtlSeconds());
982
+ await redis.set(bootUuidKey(key), uuid, "EX", getBootKeyTtlSeconds());
965
983
  return uuid;
966
984
  };
967
985
  var readBootUuid = async (envKey) => {
968
986
  const key = envKey ?? resolveEnvKey();
969
- return redis.get(`${BOOT_KEY_PREFIX}${key}`);
987
+ return redis.get(bootUuidKey(key));
970
988
  };
971
989
  var refreshBootUuid = async (envKey) => {
972
990
  const key = envKey ?? resolveEnvKey();
973
- const refreshed = await redis.expire(`${BOOT_KEY_PREFIX}${key}`, getBootKeyTtlSeconds());
991
+ const refreshed = await redis.expire(bootUuidKey(key), getBootKeyTtlSeconds());
974
992
  if (refreshed === 0) await writeBootUuid(key);
975
993
  };
976
994
  var startBootUuidHeartbeat = (envKey) => {
@@ -987,7 +1005,7 @@ var startBootUuidHeartbeat = (envKey) => {
987
1005
  },
988
1006
  (error) => {
989
1007
  getLogger().error(
990
- `[boot-uuid] failed to refresh ${BOOT_KEY_PREFIX}${key}; readiness may degrade if the TTL expires`,
1008
+ `[boot-uuid] failed to refresh ${bootUuidKey(key)}; readiness may degrade if the TTL expires`,
991
1009
  error instanceof Error ? error : new Error(String(error))
992
1010
  );
993
1011
  schedule();
@@ -1117,7 +1135,10 @@ var initConsolelog = () => {
1117
1135
  originalLog(`${colorCode}${extractedInfo}${COLORS.reset}`);
1118
1136
  originalLog(...args);
1119
1137
  } else {
1120
- originalLog(`${colorCode}${extractedInfo} -- ${args.join(" ")}${COLORS.reset}`);
1138
+ const firstNonString = args.findIndex((arg) => typeof arg !== "string");
1139
+ const leading = firstNonString === -1 ? args : args.slice(0, firstNonString);
1140
+ const rest = firstNonString === -1 ? [] : args.slice(firstNonString);
1141
+ originalLog(`${colorCode}${extractedInfo} -- ${leading.join(" ")}${COLORS.reset}`, ...rest);
1121
1142
  }
1122
1143
  };
1123
1144
  };
@@ -1447,7 +1468,8 @@ var extractTokenFromSocket = (socket2) => {
1447
1468
  const config = getProjectConfig();
1448
1469
  const cookie = socket2.handshake.headers.cookie;
1449
1470
  const sessionToken = typeof socket2.handshake.auth.token === "string" ? socket2.handshake.auth.token : null;
1450
- const cookieToken = getCookieValue(cookie, config.http.sessionCookieName);
1471
+ const cookieName = applyCookiePrefixConstraints(config.http.sessionCookieName, config.http.sessionCookiePrefix).name;
1472
+ const cookieToken = getCookieValue(cookie, cookieName);
1451
1473
  if (config.session.basedToken) {
1452
1474
  return sessionToken ?? cookieToken;
1453
1475
  }
@@ -1463,7 +1485,8 @@ var extractTokenFromRequest = (req) => {
1463
1485
  const authHeader = typeof rawAuthHeader === "string" ? rawAuthHeader : Array.isArray(rawAuthHeader) && typeof rawAuthHeader[0] === "string" ? rawAuthHeader[0] : void 0;
1464
1486
  const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
1465
1487
  const config = getProjectConfig();
1466
- const cookieToken = getCookieValue(req.headers.cookie, config.http.sessionCookieName);
1488
+ const cookieName = applyCookiePrefixConstraints(config.http.sessionCookieName, config.http.sessionCookiePrefix).name;
1489
+ const cookieToken = getCookieValue(req.headers.cookie, cookieName);
1467
1490
  if (config.session.basedToken) {
1468
1491
  return bearerToken ?? cookieToken;
1469
1492
  }
@@ -1955,6 +1978,36 @@ var parseObjectFields = (typeText) => {
1955
1978
  }
1956
1979
  return { fields, indexSignatures };
1957
1980
  };
1981
+ var wrapsWhole = (text, open, close) => {
1982
+ if (!text.startsWith(open) || !text.endsWith(close)) return false;
1983
+ let depth = 0;
1984
+ let inString = null;
1985
+ for (let index = 0; index < text.length; index += 1) {
1986
+ const char = text[index];
1987
+ if (inString) {
1988
+ if (char === "\\") index += 1;
1989
+ else if (char === inString) inString = null;
1990
+ continue;
1991
+ }
1992
+ if (char === '"' || char === "'") {
1993
+ inString = char;
1994
+ continue;
1995
+ }
1996
+ if (char === open) depth += 1;
1997
+ if (char === close) {
1998
+ depth -= 1;
1999
+ if (depth === 0) return index === text.length - 1;
2000
+ }
2001
+ }
2002
+ return false;
2003
+ };
2004
+ var unwrapParens = (text) => {
2005
+ let current = text.trim();
2006
+ while (wrapsWhole(current, "(", ")")) current = current.slice(1, -1).trim();
2007
+ return current;
2008
+ };
2009
+ var isObjectTypeText = (text) => wrapsWhole(text, "{", "}");
2010
+ var unquoteLiteral = (literal) => literal.slice(1, -1).replaceAll(/\\(['"\\])/g, "$1");
1958
2011
  var matchesIndexKeyType = ({ keyType, key }) => {
1959
2012
  const normalized = keyType.trim();
1960
2013
  if (normalized === "string") return true;
@@ -1964,7 +2017,7 @@ var matchesIndexKeyType = ({ keyType, key }) => {
1964
2017
  return parts.some((part) => matchesIndexKeyType({ keyType: part, key }));
1965
2018
  }
1966
2019
  if (normalized.startsWith("'") && normalized.endsWith("'") || normalized.startsWith('"') && normalized.endsWith('"')) {
1967
- return key === normalized.slice(1, -1);
2020
+ return key === unquoteLiteral(normalized);
1968
2021
  }
1969
2022
  return false;
1970
2023
  };
@@ -2010,6 +2063,45 @@ var parseRecordParts = (type) => {
2010
2063
  return null;
2011
2064
  };
2012
2065
  var MAX_VALIDATION_DEPTH = 64;
2066
+ var JSON_DATA_TYPES = /* @__PURE__ */ new Set(["JsonValue", "JsonObject", "JsonArray", "JsonPrimitive"]);
2067
+ var isJsonPrimitive = (value) => value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
2068
+ var isPlainObject2 = (value) => {
2069
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
2070
+ const prototype = Object.getPrototypeOf(value);
2071
+ return prototype === Object.prototype || prototype === null;
2072
+ };
2073
+ var validateJsonData = (type, value, path4, depth) => {
2074
+ if (depth > MAX_VALIDATION_DEPTH) {
2075
+ return { status: "error", message: `${path4}: input nesting exceeds the maximum depth of ${String(MAX_VALIDATION_DEPTH)}` };
2076
+ }
2077
+ if (isJsonPrimitive(value)) {
2078
+ return type === "JsonValue" || type === "JsonPrimitive" ? { status: "success" } : { status: "error", message: `${path4} should be ${type === "JsonArray" ? "a JSON array" : "a JSON object"}` };
2079
+ }
2080
+ if (type === "JsonPrimitive") {
2081
+ return { status: "error", message: `${path4} should be a JSON primitive` };
2082
+ }
2083
+ if (Array.isArray(value)) {
2084
+ if (type === "JsonObject") return { status: "error", message: `${path4} should be a JSON object` };
2085
+ for (const [index, element] of value.entries()) {
2086
+ const result = validateJsonData("JsonValue", element, `${path4}[${String(index)}]`, depth + 1);
2087
+ if (result.status === "error") return result;
2088
+ }
2089
+ return { status: "success" };
2090
+ }
2091
+ if (isPlainObject2(value)) {
2092
+ if (type === "JsonArray") return { status: "error", message: `${path4} should be a JSON array` };
2093
+ for (const [key, entry] of Object.entries(value)) {
2094
+ if (PROTO_POLLUTION_KEYS.has(key)) {
2095
+ return { status: "error", message: `${path4}.${key} is not allowed` };
2096
+ }
2097
+ if (entry === void 0) continue;
2098
+ const result = validateJsonData("JsonValue", entry, `${path4}.${key}`, depth + 1);
2099
+ if (result.status === "error") return result;
2100
+ }
2101
+ return { status: "success" };
2102
+ }
2103
+ return { status: "error", message: `${path4} should be JSON data` };
2104
+ };
2013
2105
  var validateType = (typeText, value, path4, depth = 0) => {
2014
2106
  if (depth > MAX_VALIDATION_DEPTH) {
2015
2107
  return { status: "error", message: `${path4}: input nesting exceeds the maximum depth of ${String(MAX_VALIDATION_DEPTH)}` };
@@ -2039,14 +2131,20 @@ var validateType = (typeText, value, path4, depth = 0) => {
2039
2131
  if (type.includes("&")) {
2040
2132
  const intersectionParts = splitTopLevel(type, "&").filter(Boolean);
2041
2133
  if (intersectionParts.length > 1) {
2134
+ const objectParts = intersectionParts.map((part) => unwrapParens(part));
2135
+ if (objectParts.every((part) => isObjectTypeText(part))) {
2136
+ const mergedBody = objectParts.map((part) => part.slice(1, -1)).join("; ");
2137
+ return validateType(`{ ${mergedBody} }`, value, path4, depth + 1);
2138
+ }
2042
2139
  for (const intersectionType of intersectionParts) {
2043
2140
  const result = validateType(intersectionType, value, path4, depth + 1);
2044
2141
  if (result.status === "error") return result;
2045
2142
  }
2046
2143
  return { status: "success" };
2047
2144
  }
2048
- if (intersectionParts.length === 1) {
2049
- return validateType(intersectionParts[0] ?? type, value, path4, depth + 1);
2145
+ const singleMember = intersectionParts[0] ?? type;
2146
+ if (intersectionParts.length === 1 && singleMember !== type) {
2147
+ return validateType(singleMember, value, path4, depth + 1);
2050
2148
  }
2051
2149
  }
2052
2150
  if (type.endsWith("[]")) {
@@ -2064,7 +2162,7 @@ var validateType = (typeText, value, path4, depth = 0) => {
2064
2162
  return { status: "success" };
2065
2163
  }
2066
2164
  if (type.startsWith("'") && type.endsWith("'") || type.startsWith('"') && type.endsWith('"')) {
2067
- const literal = type.slice(1, -1);
2165
+ const literal = unquoteLiteral(type);
2068
2166
  return value === literal ? { status: "success" } : { status: "error", message: `${path4} should equal ${literal}` };
2069
2167
  }
2070
2168
  const numericLiteral = parseFiniteNumericLiteral(type);
@@ -2081,6 +2179,9 @@ var validateType = (typeText, value, path4, depth = 0) => {
2081
2179
  if (type === "any" || type === "unknown") {
2082
2180
  return { status: "success" };
2083
2181
  }
2182
+ if (JSON_DATA_TYPES.has(type)) {
2183
+ return validateJsonData(type, value, path4, depth);
2184
+ }
2084
2185
  if (/^Record<.+>$/.test(type)) {
2085
2186
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
2086
2187
  return { status: "error", message: `${path4} should be an object` };
@@ -2171,7 +2272,7 @@ var validateInputByType = async ({
2171
2272
  return { status: "success" };
2172
2273
  }
2173
2274
  if (isProductionRuntime()) {
2174
- const { getProjectConfig: getProjectConfig2 } = await import("./projectConfig-EOJRMH36.js");
2275
+ const { getProjectConfig: getProjectConfig2 } = await import("./projectConfig-6QNMG5GZ.js");
2175
2276
  if (getProjectConfig2().validation.runtimeMode === "off") {
2176
2277
  return { status: "success" };
2177
2278
  }
@@ -2378,6 +2479,7 @@ export {
2378
2479
  applySocketMiddlewares,
2379
2480
  applyStrayKeyPrefix,
2380
2481
  attachSocketRedisAdapter,
2482
+ bootUuidKey,
2381
2483
  bootstrapEnv,
2382
2484
  buildApiResponseEventName,
2383
2485
  buildApiStreamEventName,
@@ -2482,6 +2584,7 @@ export {
2482
2584
  getSyncQueueSize,
2483
2585
  getUploadsDir,
2484
2586
  hasCookie,
2587
+ hasErrorTrackerIdentityScope,
2485
2588
  hashSynchronizedValue,
2486
2589
  hashSynchronizedValueWith,
2487
2590
  httpFetch,