@stackframe/stack-shared 2.8.19 → 2.8.21

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 (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/config/schema.d.mts +35 -11
  3. package/dist/config/schema.d.ts +35 -11
  4. package/dist/config/schema.js +24 -3
  5. package/dist/config/schema.js.map +1 -1
  6. package/dist/esm/config/schema.js +25 -4
  7. package/dist/esm/config/schema.js.map +1 -1
  8. package/dist/esm/interface/client-interface.js +1 -1
  9. package/dist/esm/interface/client-interface.js.map +1 -1
  10. package/dist/esm/interface/crud/projects.js +1 -2
  11. package/dist/esm/interface/crud/projects.js.map +1 -1
  12. package/dist/esm/schema-fields.js +0 -2
  13. package/dist/esm/schema-fields.js.map +1 -1
  14. package/dist/esm/utils/errors.js +3 -0
  15. package/dist/esm/utils/errors.js.map +1 -1
  16. package/dist/esm/utils/esbuild.js +85 -0
  17. package/dist/esm/utils/esbuild.js.map +1 -0
  18. package/dist/esm/utils/globals.js.map +1 -1
  19. package/dist/esm/utils/json.js +4 -4
  20. package/dist/esm/utils/json.js.map +1 -1
  21. package/dist/esm/utils/objects.js.map +1 -1
  22. package/dist/esm/utils/react.js +19 -0
  23. package/dist/esm/utils/react.js.map +1 -1
  24. package/dist/interface/client-interface.js +1 -1
  25. package/dist/interface/client-interface.js.map +1 -1
  26. package/dist/interface/crud/current-user.d.mts +1 -1
  27. package/dist/interface/crud/current-user.d.ts +1 -1
  28. package/dist/interface/crud/project-api-keys.d.mts +4 -4
  29. package/dist/interface/crud/project-api-keys.d.ts +4 -4
  30. package/dist/interface/crud/projects.d.mts +0 -6
  31. package/dist/interface/crud/projects.d.ts +0 -6
  32. package/dist/interface/crud/projects.js +1 -2
  33. package/dist/interface/crud/projects.js.map +1 -1
  34. package/dist/interface/crud/team-member-profiles.d.mts +2 -2
  35. package/dist/interface/crud/team-member-profiles.d.ts +2 -2
  36. package/dist/interface/crud/users.d.mts +4 -4
  37. package/dist/interface/crud/users.d.ts +4 -4
  38. package/dist/known-errors.d.mts +1 -1
  39. package/dist/known-errors.d.ts +1 -1
  40. package/dist/schema-fields.d.mts +1 -2
  41. package/dist/schema-fields.d.ts +1 -2
  42. package/dist/schema-fields.js +0 -3
  43. package/dist/schema-fields.js.map +1 -1
  44. package/dist/utils/errors.js +3 -0
  45. package/dist/utils/errors.js.map +1 -1
  46. package/dist/utils/esbuild.d.mts +10 -0
  47. package/dist/utils/esbuild.d.ts +10 -0
  48. package/dist/utils/esbuild.js +121 -0
  49. package/dist/utils/esbuild.js.map +1 -0
  50. package/dist/utils/globals.js.map +1 -1
  51. package/dist/utils/json.d.mts +2 -2
  52. package/dist/utils/json.d.ts +2 -2
  53. package/dist/utils/json.js +5 -5
  54. package/dist/utils/json.js.map +1 -1
  55. package/dist/utils/objects.d.mts +2 -1
  56. package/dist/utils/objects.d.ts +2 -1
  57. package/dist/utils/objects.js.map +1 -1
  58. package/dist/utils/react.d.mts +12 -4
  59. package/dist/utils/react.d.ts +12 -4
  60. package/dist/utils/react.js +21 -0
  61. package/dist/utils/react.js.map +1 -1
  62. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/objects.tsx"],"sourcesContent":["import { StackAssertionError } from \"./errors\";\nimport { identity } from \"./functions\";\nimport { stringCompare } from \"./strings\";\n\nexport function isNotNull<T>(value: T): value is NonNullable<T> {\n return value !== null && value !== undefined;\n}\nundefined?.test(\"isNotNull\", ({ expect }) => {\n expect(isNotNull(null)).toBe(false);\n expect(isNotNull(undefined)).toBe(false);\n expect(isNotNull(0)).toBe(true);\n expect(isNotNull(\"\")).toBe(true);\n expect(isNotNull(false)).toBe(true);\n expect(isNotNull({})).toBe(true);\n expect(isNotNull([])).toBe(true);\n});\n\nexport type DeepPartial<T> = T extends object ? (T extends (infer E)[] ? T : { [P in keyof T]?: DeepPartial<T[P]> }) : T;\nexport type DeepRequired<T> = T extends object ? (T extends (infer E)[] ? T : { [P in keyof T]-?: DeepRequired<T[P]> }) : T;\n\n/**\n * Assumes both objects are primitives, arrays, or non-function plain objects, and compares them deeply.\n *\n * Note that since they are assumed to be plain objects, this function does not compare prototypes.\n */\nexport function deepPlainEquals<T>(obj1: T, obj2: unknown, options: { ignoreUndefinedValues?: boolean } = {}): obj2 is T {\n if (typeof obj1 !== typeof obj2) return false;\n if (obj1 === obj2) return true;\n\n switch (typeof obj1) {\n case 'object': {\n if (!obj1 || !obj2) return false;\n\n if (Array.isArray(obj1) || Array.isArray(obj2)) {\n if (!Array.isArray(obj1) || !Array.isArray(obj2)) return false;\n if (obj1.length !== obj2.length) return false;\n return obj1.every((v, i) => deepPlainEquals(v, obj2[i], options));\n }\n\n const entries1 = Object.entries(obj1).filter(([k, v]) => !options.ignoreUndefinedValues || v !== undefined);\n const entries2 = Object.entries(obj2).filter(([k, v]) => !options.ignoreUndefinedValues || v !== undefined);\n if (entries1.length !== entries2.length) return false;\n return entries1.every(([k, v1]) => {\n const e2 = entries2.find(([k2]) => k === k2);\n if (!e2) return false;\n return deepPlainEquals(v1, e2[1], options);\n });\n }\n case 'undefined':\n case 'string':\n case 'number':\n case 'boolean':\n case 'bigint':\n case 'symbol':\n case 'function':{\n return false;\n }\n default: {\n throw new Error(\"Unexpected typeof \" + typeof obj1);\n }\n }\n}\nundefined?.test(\"deepPlainEquals\", ({ expect }) => {\n // Simple values\n expect(deepPlainEquals(1, 1)).toBe(true);\n expect(deepPlainEquals(\"test\", \"test\")).toBe(true);\n expect(deepPlainEquals(1, 2)).toBe(false);\n expect(deepPlainEquals(\"test\", \"other\")).toBe(false);\n\n // Arrays\n expect(deepPlainEquals([1, 2, 3], [1, 2, 3])).toBe(true);\n expect(deepPlainEquals([1, 2, 3], [1, 2, 4])).toBe(false);\n expect(deepPlainEquals([1, 2, 3], [1, 2])).toBe(false);\n\n // Objects\n expect(deepPlainEquals({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true);\n expect(deepPlainEquals({ a: 1, b: 2 }, { a: 1, b: 3 })).toBe(false);\n expect(deepPlainEquals({ a: 1, b: 2 }, { a: 1 })).toBe(false);\n\n // Nested structures\n expect(deepPlainEquals({ a: 1, b: [1, 2, { c: 3 }] }, { a: 1, b: [1, 2, { c: 3 }] })).toBe(true);\n expect(deepPlainEquals({ a: 1, b: [1, 2, { c: 3 }] }, { a: 1, b: [1, 2, { c: 4 }] })).toBe(false);\n\n // With options\n expect(deepPlainEquals({ a: 1, b: undefined }, { a: 1 }, { ignoreUndefinedValues: true })).toBe(true);\n expect(deepPlainEquals({ a: 1, b: undefined }, { a: 1 })).toBe(false);\n});\n\nexport function isCloneable<T>(obj: T): obj is Exclude<T, symbol | Function> {\n return typeof obj !== 'symbol' && typeof obj !== 'function';\n}\n\nexport function shallowClone<T extends object>(obj: T): T {\n if (!isCloneable(obj)) throw new StackAssertionError(\"shallowClone does not support symbols or functions\", { obj });\n\n if (Array.isArray(obj)) return obj.map(identity) as T;\n return { ...obj };\n}\nundefined?.test(\"shallowClone\", ({ expect }) => {\n expect(shallowClone({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });\n expect(shallowClone([1, 2, 3])).toEqual([1, 2, 3]);\n expect(() => shallowClone(() => {})).toThrow();\n});\n\nexport function deepPlainClone<T>(obj: T): T {\n if (typeof obj === 'function') throw new StackAssertionError(\"deepPlainClone does not support functions\");\n if (typeof obj === 'symbol') throw new StackAssertionError(\"deepPlainClone does not support symbols\");\n if (typeof obj !== 'object' || !obj) return obj;\n if (Array.isArray(obj)) return obj.map(deepPlainClone) as any;\n return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, deepPlainClone(v)])) as any;\n}\nundefined?.test(\"deepPlainClone\", ({ expect }) => {\n // Primitive values\n expect(deepPlainClone(1)).toBe(1);\n expect(deepPlainClone(\"test\")).toBe(\"test\");\n expect(deepPlainClone(null)).toBe(null);\n expect(deepPlainClone(undefined)).toBe(undefined);\n\n // Arrays\n const arr = [1, 2, 3];\n const clonedArr = deepPlainClone(arr);\n expect(clonedArr).toEqual(arr);\n expect(clonedArr).not.toBe(arr); // Different reference\n\n // Objects\n const obj = { a: 1, b: 2 };\n const clonedObj = deepPlainClone(obj);\n expect(clonedObj).toEqual(obj);\n expect(clonedObj).not.toBe(obj); // Different reference\n\n // Nested structures\n const nested = { a: 1, b: [1, 2, { c: 3 }] };\n const clonedNested = deepPlainClone(nested);\n expect(clonedNested).toEqual(nested);\n expect(clonedNested).not.toBe(nested); // Different reference\n expect(clonedNested.b).not.toBe(nested.b); // Different reference for nested array\n expect(clonedNested.b[2]).not.toBe(nested.b[2]); // Different reference for nested object\n\n // Error cases\n expect(() => deepPlainClone(() => {})).toThrow();\n expect(() => deepPlainClone(Symbol())).toThrow();\n});\n\nexport type DeepMerge<T, U> = Omit<T, keyof U> & Omit<U, keyof T> & DeepMergeInner<Pick<T, keyof U & keyof T>, Pick<U, keyof U & keyof T>>;\ntype DeepMergeInner<T, U> = {\n [K in keyof U]-?:\n undefined extends U[K]\n ? K extends keyof T\n ? T[K] extends object\n ? Exclude<U[K], undefined> extends object\n ? DeepMerge<T[K], Exclude<U[K], undefined>>\n : T[K] | Exclude<U[K], undefined>\n : T[K] | Exclude<U[K], undefined>\n : Exclude<U[K], undefined>\n : K extends keyof T\n ? T[K] extends object\n ? U[K] extends object\n ? DeepMerge<T[K], U[K]>\n : U[K]\n : U[K]\n : U[K];\n};\nexport function deepMerge<T extends {}, U extends {}>(baseObj: T, mergeObj: U): DeepMerge<T, U> {\n if ([baseObj, mergeObj, ...Object.values(baseObj), ...Object.values(mergeObj)].some(o => !isCloneable(o))) throw new StackAssertionError(\"deepMerge does not support functions or symbols\", { baseObj, mergeObj });\n\n const res: any = shallowClone(baseObj);\n for (const [key, mergeValue] of Object.entries(mergeObj)) {\n if (has(res, key as any)) {\n const baseValue = get(res, key as any);\n if (isObjectLike(baseValue) && isObjectLike(mergeValue)) {\n set(res, key, deepMerge(baseValue, mergeValue));\n continue;\n }\n }\n set(res, key, mergeValue);\n }\n return res as any;\n}\nundefined?.test(\"deepMerge\", ({ expect }) => {\n // Test merging flat objects\n expect(deepMerge({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 });\n expect(deepMerge({ a: 1 }, { a: 2 })).toEqual({ a: 2 });\n expect(deepMerge({ a: 1, b: 2 }, { b: 3, c: 4 })).toEqual({ a: 1, b: 3, c: 4 });\n\n // Test with nested objects\n expect(deepMerge(\n { a: { x: 1, y: 2 }, b: 3 },\n { a: { y: 3, z: 4 }, c: 5 }\n )).toEqual({ a: { x: 1, y: 3, z: 4 }, b: 3, c: 5 });\n\n // Test with arrays\n expect(deepMerge(\n { a: [1, 2], b: 3 },\n { a: [3, 4], c: 5 }\n )).toEqual({ a: [3, 4], b: 3, c: 5 });\n\n // Test with null values\n expect(deepMerge(\n { a: { x: 1 }, b: null },\n { a: { y: 2 }, b: { z: 3 } }\n )).toEqual({ a: { x: 1, y: 2 }, b: { z: 3 } });\n\n // Test with undefined values\n expect(deepMerge(\n { a: 1, b: undefined },\n { b: 2, c: 3 }\n )).toEqual({ a: 1, b: 2, c: 3 });\n\n // Test deeply nested structures\n expect(deepMerge(\n {\n a: {\n x: { deep: 1 },\n y: [1, 2]\n },\n b: 2\n },\n {\n a: {\n x: { deeper: 3 },\n y: [3, 4]\n },\n c: 3\n }\n )).toEqual({\n a: {\n x: { deep: 1, deeper: 3 },\n y: [3, 4]\n },\n b: 2,\n c: 3\n });\n\n // Test with empty objects\n expect(deepMerge({}, { a: 1 })).toEqual({ a: 1 });\n expect(deepMerge({ a: 1 }, {})).toEqual({ a: 1 });\n expect(deepMerge({}, {})).toEqual({});\n\n // Test that original objects are not modified\n const base = { a: { x: 1 }, b: 2 };\n const merge = { a: { y: 2 }, c: 3 };\n const baseClone = deepPlainClone(base);\n const mergeClone = deepPlainClone(merge);\n\n const result = deepMerge(base, merge);\n expect(base).toEqual(baseClone);\n expect(merge).toEqual(mergeClone);\n expect(result).toEqual({ a: { x: 1, y: 2 }, b: 2, c: 3 });\n\n // Test error cases\n expect(() => deepMerge({ a: () => {} }, { b: 2 })).toThrow();\n expect(() => deepMerge({ a: 1 }, { b: () => {} })).toThrow();\n expect(() => deepMerge({ a: Symbol() }, { b: 2 })).toThrow();\n expect(() => deepMerge({ a: 1 }, { b: Symbol() })).toThrow();\n});\n\nexport function typedEntries<T extends {}>(obj: T): [keyof T, T[keyof T]][] {\n return Object.entries(obj) as any;\n}\nundefined?.test(\"typedEntries\", ({ expect }) => {\n expect(typedEntries({})).toEqual([]);\n expect(typedEntries({ a: 1, b: 2 })).toEqual([[\"a\", 1], [\"b\", 2]]);\n expect(typedEntries({ a: \"hello\", b: true, c: null })).toEqual([[\"a\", \"hello\"], [\"b\", true], [\"c\", null]]);\n\n // Test with object containing methods\n const objWithMethod = { a: 1, b: () => \"test\" };\n const entries = typedEntries(objWithMethod);\n expect(entries.length).toBe(2);\n expect(entries[0][0]).toBe(\"a\");\n expect(entries[0][1]).toBe(1);\n expect(entries[1][0]).toBe(\"b\");\n expect(typeof entries[1][1]).toBe(\"function\");\n});\n\nexport function typedFromEntries<K extends PropertyKey, V>(entries: (readonly [K, V])[]): Record<K, V> {\n return Object.fromEntries(entries) as any;\n}\nundefined?.test(\"typedFromEntries\", ({ expect }) => {\n expect(typedFromEntries([])).toEqual({});\n expect(typedFromEntries([[\"a\", 1], [\"b\", 2]])).toEqual({ a: 1, b: 2 });\n\n // Test with mixed types (using type assertion)\n const mixedEntries = [[\"a\", \"hello\"], [\"b\", true], [\"c\", null]] as [string, string | boolean | null][];\n const mixedObj = typedFromEntries(mixedEntries);\n expect(mixedObj).toEqual({ a: \"hello\", b: true, c: null });\n\n // Test with function values\n const fn = () => \"test\";\n type MixedValue = number | (() => string);\n const fnEntries: [string, MixedValue][] = [[\"a\", 1], [\"b\", fn]];\n const obj = typedFromEntries(fnEntries);\n expect(obj.a).toBe(1);\n expect(typeof obj.b).toBe(\"function\");\n // Type assertion needed for the function call\n expect((obj.b as () => string)()).toBe(\"test\");\n});\n\nexport function typedKeys<T extends {}>(obj: T): (keyof T)[] {\n return Object.keys(obj) as any;\n}\nundefined?.test(\"typedKeys\", ({ expect }) => {\n expect(typedKeys({})).toEqual([]);\n expect(typedKeys({ a: 1, b: 2 })).toEqual([\"a\", \"b\"]);\n expect(typedKeys({ a: \"hello\", b: true, c: null })).toEqual([\"a\", \"b\", \"c\"]);\n\n // Test with object containing methods\n const objWithMethod = { a: 1, b: () => \"test\" };\n expect(typedKeys(objWithMethod)).toEqual([\"a\", \"b\"]);\n});\n\nexport function typedValues<T extends {}>(obj: T): T[keyof T][] {\n return Object.values(obj) as any;\n}\nundefined?.test(\"typedValues\", ({ expect }) => {\n expect(typedValues({})).toEqual([]);\n expect(typedValues({ a: 1, b: 2 })).toEqual([1, 2]);\n\n // Test with mixed types\n type MixedObj = { a: string, b: boolean, c: null };\n const mixedObj: MixedObj = { a: \"hello\", b: true, c: null };\n expect(typedValues(mixedObj)).toEqual([\"hello\", true, null]);\n\n // Test with object containing methods\n type ObjWithFn = { a: number, b: () => string };\n const fn = () => \"test\";\n const objWithMethod: ObjWithFn = { a: 1, b: fn };\n const values = typedValues(objWithMethod);\n expect(values.length).toBe(2);\n expect(values[0]).toBe(1);\n expect(typeof values[1]).toBe(\"function\");\n // Need to cast to the correct type\n const fnValue = values[1] as () => string;\n expect(fnValue()).toBe(\"test\");\n});\n\nexport function typedAssign<T extends {}, U extends {}>(target: T, source: U): T & U {\n return Object.assign(target, source);\n}\nundefined?.test(\"typedAssign\", ({ expect }) => {\n // Test with empty objects\n const emptyTarget = {};\n const emptyResult = typedAssign(emptyTarget, { a: 1 });\n expect(emptyResult).toEqual({ a: 1 });\n expect(emptyResult).toBe(emptyTarget); // Same reference\n\n // Test with non-empty target\n const target = { a: 1, b: 2 };\n const result = typedAssign(target, { c: 3, d: 4 });\n expect(result).toEqual({ a: 1, b: 2, c: 3, d: 4 });\n expect(result).toBe(target); // Same reference\n\n // Test with overlapping properties\n const targetWithOverlap = { a: 1, b: 2 };\n const resultWithOverlap = typedAssign(targetWithOverlap, { b: 3, c: 4 });\n expect(resultWithOverlap).toEqual({ a: 1, b: 3, c: 4 });\n expect(resultWithOverlap).toBe(targetWithOverlap); // Same reference\n});\n\nexport type FilterUndefined<T> =\n & { [k in keyof T as (undefined extends T[k] ? (T[k] extends undefined | void ? never : k) : never)]+?: T[k] & ({} | null) }\n & { [k in keyof T as (undefined extends T[k] ? never : k)]: T[k] & ({} | null) }\n\n/**\n * Returns a new object with all undefined values removed. Useful when spreading optional parameters on an object, as\n * TypeScript's `Partial<XYZ>` type allows `undefined` values.\n */\nexport function filterUndefined<T extends object>(obj: T): FilterUndefined<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as any;\n}\nundefined?.test(\"filterUndefined\", ({ expect }) => {\n expect(filterUndefined({})).toEqual({});\n expect(filterUndefined({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });\n expect(filterUndefined({ a: 1, b: undefined })).toEqual({ a: 1 });\n expect(filterUndefined({ a: undefined, b: undefined })).toEqual({});\n expect(filterUndefined({ a: null, b: undefined })).toEqual({ a: null });\n expect(filterUndefined({ a: 0, b: \"\", c: false, d: undefined })).toEqual({ a: 0, b: \"\", c: false });\n});\n\nexport type FilterUndefinedOrNull<T> = FilterUndefined<{ [k in keyof T]: null extends T[k] ? NonNullable<T[k]> | undefined : T[k] }>;\n\n/**\n * Returns a new object with all undefined and null values removed. Useful when spreading optional parameters on an object, as\n * TypeScript's `Partial<XYZ>` type allows `undefined` values.\n */\nexport function filterUndefinedOrNull<T extends object>(obj: T): FilterUndefinedOrNull<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== null)) as any;\n}\nundefined?.test(\"filterUndefinedOrNull\", ({ expect }) => {\n expect(filterUndefinedOrNull({})).toEqual({});\n expect(filterUndefinedOrNull({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });\n});\n\nexport type DeepFilterUndefined<T> = T extends object ? FilterUndefined<{ [K in keyof T]: DeepFilterUndefined<T[K]> }> : T;\n\nexport function deepFilterUndefined<T extends object>(obj: T): DeepFilterUndefined<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined).map(([k, v]) => [k, isObjectLike(v) ? deepFilterUndefined(v) : v])) as any;\n}\nundefined?.test(\"deepFilterUndefined\", ({ expect }) => {\n expect(deepFilterUndefined({ a: 1, b: undefined })).toEqual({ a: 1 });\n});\n\nexport function pick<T extends {}, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n return Object.fromEntries(Object.entries(obj).filter(([k]) => keys.includes(k as K))) as any;\n}\nundefined?.test(\"pick\", ({ expect }) => {\n const obj = { a: 1, b: 2, c: 3, d: 4 };\n expect(pick(obj, [\"a\", \"c\"])).toEqual({ a: 1, c: 3 });\n expect(pick(obj, [])).toEqual({});\n expect(pick(obj, [\"a\", \"e\" as keyof typeof obj])).toEqual({ a: 1 });\n // Use type assertion for empty object to avoid TypeScript error\n expect(pick({} as Record<string, unknown>, [\"a\"])).toEqual({});\n});\n\nexport function omit<T extends {}, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\n if (!Array.isArray(keys)) throw new StackAssertionError(\"omit: keys must be an array\", { obj, keys });\n return Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k as K))) as any;\n}\nundefined?.test(\"omit\", ({ expect }) => {\n const obj = { a: 1, b: 2, c: 3, d: 4 };\n expect(omit(obj, [\"a\", \"c\"])).toEqual({ b: 2, d: 4 });\n expect(omit(obj, [])).toEqual(obj);\n expect(omit(obj, [\"a\", \"e\" as keyof typeof obj])).toEqual({ b: 2, c: 3, d: 4 });\n // Use type assertion for empty object to avoid TypeScript error\n expect(omit({} as Record<string, unknown>, [\"a\"])).toEqual({});\n});\n\nexport function split<T extends {}, K extends keyof T>(obj: T, keys: K[]): [Pick<T, K>, Omit<T, K>] {\n return [pick(obj, keys), omit(obj, keys)];\n}\nundefined?.test(\"split\", ({ expect }) => {\n const obj = { a: 1, b: 2, c: 3, d: 4 };\n expect(split(obj, [\"a\", \"c\"])).toEqual([{ a: 1, c: 3 }, { b: 2, d: 4 }]);\n expect(split(obj, [])).toEqual([{}, obj]);\n expect(split(obj, [\"a\", \"e\" as keyof typeof obj])).toEqual([{ a: 1 }, { b: 2, c: 3, d: 4 }]);\n // Use type assertion for empty object to avoid TypeScript error\n expect(split({} as Record<string, unknown>, [\"a\"])).toEqual([{}, {}]);\n});\n\nexport function mapValues<T extends object, U>(obj: T, fn: (value: T extends (infer E)[] ? E : T[keyof T]) => U): Record<keyof T, U> {\n if (Array.isArray(obj)) {\n return obj.map(v => fn(v)) as any;\n }\n return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, fn(v)])) as any;\n}\nundefined?.test(\"mapValues\", ({ expect }) => {\n expect(mapValues({ a: 1, b: 2 }, v => v * 2)).toEqual({ a: 2, b: 4 });\n expect(mapValues([1, 2, 3], v => v * 2)).toEqual([2, 4, 6]);\n});\n\nexport function sortKeys<T extends object>(obj: T): T {\n if (Array.isArray(obj)) {\n return [...obj] as any;\n }\n return Object.fromEntries(Object.entries(obj).sort(([a], [b]) => stringCompare(a, b))) as any;\n}\nundefined?.test(\"sortKeys\", ({ expect }) => {\n const obj = {\n \"1\": 0,\n \"10\": 1,\n b: 2,\n \"2\": 3,\n a: 4,\n \"-3.33\": 5,\n \"-4\": 6,\n \"-3\": 7,\n abc: 8,\n \"a-b\": 9,\n ab: 10,\n ac: 11,\n aa: 12,\n aab: 13,\n };\n expect(Object.entries(sortKeys(obj))).toEqual([\n [\"1\", 0],\n [\"2\", 3],\n [\"10\", 1],\n [\"-3\", 7],\n [\"-3.33\", 5],\n [\"-4\", 6],\n [\"a\", 4],\n [\"a-b\", 9],\n [\"aa\", 12],\n [\"aab\", 13],\n [\"ab\", 10],\n [\"abc\", 8],\n [\"ac\", 11],\n [\"b\", 2],\n ]);\n});\n\nexport function deepSortKeys<T extends object>(obj: T): T {\n return sortKeys(mapValues(obj, v => isObjectLike(v) ? deepSortKeys(v) : v)) as any;\n}\nundefined?.test(\"deepSortKeys\", ({ expect }) => {\n const obj = {\n h: { i: { k: 9, j: 8 }, l: 10 },\n b: { d: 3, c: 2 },\n a: 1,\n e: [4, 5, { g: 7, f: 6 }],\n };\n const sorted = deepSortKeys(obj);\n expect(Object.entries(sorted)).toEqual([\n [\"a\", 1],\n [\"b\", { c: 2, d: 3 }],\n [\"e\", [4, 5, { f: 6, g: 7 }]],\n [\"h\", { i: { j: 8, k: 9 }, l: 10 }],\n ]);\n expect(Object.entries(sorted.b)).toEqual([\n [\"c\", 2],\n [\"d\", 3],\n ]);\n expect(Object.entries(sorted.e[2])).toEqual([\n [\"f\", 6],\n [\"g\", 7],\n ]);\n expect(Object.entries(sorted.h)).toEqual([\n [\"i\", { j: 8, k: 9 }],\n [\"l\", 10],\n ]);\n expect(Object.entries(sorted.h.i)).toEqual([\n [\"j\", 8],\n [\"k\", 9],\n ]);\n});\n\nexport function set<T extends object, K extends keyof T>(obj: T, key: K, value: T[K]) {\n Object.defineProperty(obj, key, { value, writable: true, configurable: true, enumerable: true });\n}\n\nexport function get<T extends object, K extends keyof T>(obj: T, key: K): T[K] {\n const descriptor = Object.getOwnPropertyDescriptor(obj, key);\n if (!descriptor) throw new StackAssertionError(`get: key ${String(key)} does not exist`, { obj, key });\n return descriptor.value;\n}\n\nexport function getOrUndefined<T extends object, K extends keyof T>(obj: T, key: K): T[K] | undefined {\n return has(obj, key) ? get(obj, key) : undefined;\n}\n\nexport function has<T extends object, K extends keyof T>(obj: T, key: K): obj is T & { [k in K]: unknown } {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nundefined?.test(\"has\", ({ expect }) => {\n const obj = { a: 1, b: undefined, c: null };\n expect(has(obj, \"a\")).toBe(true);\n expect(has(obj, \"b\")).toBe(true);\n expect(has(obj, \"c\")).toBe(true);\n expect(has(obj, \"d\" as keyof typeof obj)).toBe(false);\n});\n\n\nexport function hasAndNotUndefined<T extends object, K extends keyof T>(obj: T, key: K): obj is T & { [k in K]: Exclude<T[K], undefined> } {\n return has(obj, key) && get(obj, key) !== undefined;\n}\n\nexport function deleteKey<T extends object, K extends keyof T>(obj: T, key: K) {\n if (has(obj, key)) {\n Reflect.deleteProperty(obj, key);\n } else {\n throw new StackAssertionError(`deleteKey: key ${String(key)} does not exist`, { obj, key });\n }\n}\n\nexport function isObjectLike(value: unknown): value is object {\n return (typeof value === 'object' || typeof value === 'function') && value !== null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/objects.tsx"],"sourcesContent":["import { StackAssertionError } from \"./errors\";\nimport { identity } from \"./functions\";\nimport { stringCompare } from \"./strings\";\n\nexport function isNotNull<T>(value: T): value is NonNullable<T> {\n return value !== null && value !== undefined;\n}\nundefined?.test(\"isNotNull\", ({ expect }) => {\n expect(isNotNull(null)).toBe(false);\n expect(isNotNull(undefined)).toBe(false);\n expect(isNotNull(0)).toBe(true);\n expect(isNotNull(\"\")).toBe(true);\n expect(isNotNull(false)).toBe(true);\n expect(isNotNull({})).toBe(true);\n expect(isNotNull([])).toBe(true);\n});\n\nexport type DeepPartial<T> = T extends object ? (T extends (infer E)[] ? T : { [P in keyof T]?: DeepPartial<T[P]> }) : T;\nexport type DeepRequired<T> = T extends object ? (T extends (infer E)[] ? T : { [P in keyof T]-?: DeepRequired<T[P]> }) : T;\n\n/**\n * Assumes both objects are primitives, arrays, or non-function plain objects, and compares them deeply.\n *\n * Note that since they are assumed to be plain objects, this function does not compare prototypes.\n */\nexport function deepPlainEquals<T>(obj1: T, obj2: unknown, options: { ignoreUndefinedValues?: boolean } = {}): obj2 is T {\n if (typeof obj1 !== typeof obj2) return false;\n if (obj1 === obj2) return true;\n\n switch (typeof obj1) {\n case 'object': {\n if (!obj1 || !obj2) return false;\n\n if (Array.isArray(obj1) || Array.isArray(obj2)) {\n if (!Array.isArray(obj1) || !Array.isArray(obj2)) return false;\n if (obj1.length !== obj2.length) return false;\n return obj1.every((v, i) => deepPlainEquals(v, obj2[i], options));\n }\n\n const entries1 = Object.entries(obj1).filter(([k, v]) => !options.ignoreUndefinedValues || v !== undefined);\n const entries2 = Object.entries(obj2).filter(([k, v]) => !options.ignoreUndefinedValues || v !== undefined);\n if (entries1.length !== entries2.length) return false;\n return entries1.every(([k, v1]) => {\n const e2 = entries2.find(([k2]) => k === k2);\n if (!e2) return false;\n return deepPlainEquals(v1, e2[1], options);\n });\n }\n case 'undefined':\n case 'string':\n case 'number':\n case 'boolean':\n case 'bigint':\n case 'symbol':\n case 'function':{\n return false;\n }\n default: {\n throw new Error(\"Unexpected typeof \" + typeof obj1);\n }\n }\n}\nundefined?.test(\"deepPlainEquals\", ({ expect }) => {\n // Simple values\n expect(deepPlainEquals(1, 1)).toBe(true);\n expect(deepPlainEquals(\"test\", \"test\")).toBe(true);\n expect(deepPlainEquals(1, 2)).toBe(false);\n expect(deepPlainEquals(\"test\", \"other\")).toBe(false);\n\n // Arrays\n expect(deepPlainEquals([1, 2, 3], [1, 2, 3])).toBe(true);\n expect(deepPlainEquals([1, 2, 3], [1, 2, 4])).toBe(false);\n expect(deepPlainEquals([1, 2, 3], [1, 2])).toBe(false);\n\n // Objects\n expect(deepPlainEquals({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true);\n expect(deepPlainEquals({ a: 1, b: 2 }, { a: 1, b: 3 })).toBe(false);\n expect(deepPlainEquals({ a: 1, b: 2 }, { a: 1 })).toBe(false);\n\n // Nested structures\n expect(deepPlainEquals({ a: 1, b: [1, 2, { c: 3 }] }, { a: 1, b: [1, 2, { c: 3 }] })).toBe(true);\n expect(deepPlainEquals({ a: 1, b: [1, 2, { c: 3 }] }, { a: 1, b: [1, 2, { c: 4 }] })).toBe(false);\n\n // With options\n expect(deepPlainEquals({ a: 1, b: undefined }, { a: 1 }, { ignoreUndefinedValues: true })).toBe(true);\n expect(deepPlainEquals({ a: 1, b: undefined }, { a: 1 })).toBe(false);\n});\n\nexport function isCloneable<T>(obj: T): obj is Exclude<T, symbol | Function> {\n return typeof obj !== 'symbol' && typeof obj !== 'function';\n}\n\nexport function shallowClone<T extends object>(obj: T): T {\n if (!isCloneable(obj)) throw new StackAssertionError(\"shallowClone does not support symbols or functions\", { obj });\n\n if (Array.isArray(obj)) return obj.map(identity) as T;\n return { ...obj };\n}\nundefined?.test(\"shallowClone\", ({ expect }) => {\n expect(shallowClone({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });\n expect(shallowClone([1, 2, 3])).toEqual([1, 2, 3]);\n expect(() => shallowClone(() => {})).toThrow();\n});\n\nexport function deepPlainClone<T>(obj: T): T {\n if (typeof obj === 'function') throw new StackAssertionError(\"deepPlainClone does not support functions\");\n if (typeof obj === 'symbol') throw new StackAssertionError(\"deepPlainClone does not support symbols\");\n if (typeof obj !== 'object' || !obj) return obj;\n if (Array.isArray(obj)) return obj.map(deepPlainClone) as any;\n return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, deepPlainClone(v)])) as any;\n}\nundefined?.test(\"deepPlainClone\", ({ expect }) => {\n // Primitive values\n expect(deepPlainClone(1)).toBe(1);\n expect(deepPlainClone(\"test\")).toBe(\"test\");\n expect(deepPlainClone(null)).toBe(null);\n expect(deepPlainClone(undefined)).toBe(undefined);\n\n // Arrays\n const arr = [1, 2, 3];\n const clonedArr = deepPlainClone(arr);\n expect(clonedArr).toEqual(arr);\n expect(clonedArr).not.toBe(arr); // Different reference\n\n // Objects\n const obj = { a: 1, b: 2 };\n const clonedObj = deepPlainClone(obj);\n expect(clonedObj).toEqual(obj);\n expect(clonedObj).not.toBe(obj); // Different reference\n\n // Nested structures\n const nested = { a: 1, b: [1, 2, { c: 3 }] };\n const clonedNested = deepPlainClone(nested);\n expect(clonedNested).toEqual(nested);\n expect(clonedNested).not.toBe(nested); // Different reference\n expect(clonedNested.b).not.toBe(nested.b); // Different reference for nested array\n expect(clonedNested.b[2]).not.toBe(nested.b[2]); // Different reference for nested object\n\n // Error cases\n expect(() => deepPlainClone(() => {})).toThrow();\n expect(() => deepPlainClone(Symbol())).toThrow();\n});\n\nexport type DeepMerge<T, U> = U extends any ? DeepMergeNonDistributive<T, U> : never; // distributive conditional type https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types\ntype DeepMergeNonDistributive<T, U> = Omit<T, keyof U> & Omit<U, keyof T> & DeepMergeInner<Pick<T, keyof U & keyof T>, Pick<U, keyof U & keyof T>>;\ntype DeepMergeInner<T, U> = {\n [K in keyof U]-?:\n undefined extends U[K]\n ? K extends keyof T\n ? T[K] extends object\n ? Exclude<U[K], undefined> extends object\n ? DeepMerge<T[K], Exclude<U[K], undefined>>\n : T[K] | Exclude<U[K], undefined>\n : T[K] | Exclude<U[K], undefined>\n : Exclude<U[K], undefined>\n : K extends keyof T\n ? T[K] extends object\n ? U[K] extends object\n ? DeepMerge<T[K], U[K]>\n : U[K]\n : U[K]\n : U[K];\n};\nexport function deepMerge<T extends {}, U extends {}>(baseObj: T, mergeObj: U): DeepMerge<T, U> {\n if ([baseObj, mergeObj, ...Object.values(baseObj), ...Object.values(mergeObj)].some(o => !isCloneable(o))) throw new StackAssertionError(\"deepMerge does not support functions or symbols\", { baseObj, mergeObj });\n\n const res: any = shallowClone(baseObj);\n for (const [key, mergeValue] of Object.entries(mergeObj)) {\n if (has(res, key as any)) {\n const baseValue = get(res, key as any);\n if (isObjectLike(baseValue) && isObjectLike(mergeValue)) {\n set(res, key, deepMerge(baseValue, mergeValue));\n continue;\n }\n }\n set(res, key, mergeValue);\n }\n return res as any;\n}\nundefined?.test(\"deepMerge\", ({ expect }) => {\n // Test merging flat objects\n expect(deepMerge({ a: 1 }, { b: 2 })).toEqual({ a: 1, b: 2 });\n expect(deepMerge({ a: 1 }, { a: 2 })).toEqual({ a: 2 });\n expect(deepMerge({ a: 1, b: 2 }, { b: 3, c: 4 })).toEqual({ a: 1, b: 3, c: 4 });\n\n // Test with nested objects\n expect(deepMerge(\n { a: { x: 1, y: 2 }, b: 3 },\n { a: { y: 3, z: 4 }, c: 5 }\n )).toEqual({ a: { x: 1, y: 3, z: 4 }, b: 3, c: 5 });\n\n // Test with arrays\n expect(deepMerge(\n { a: [1, 2], b: 3 },\n { a: [3, 4], c: 5 }\n )).toEqual({ a: [3, 4], b: 3, c: 5 });\n\n // Test with null values\n expect(deepMerge(\n { a: { x: 1 }, b: null },\n { a: { y: 2 }, b: { z: 3 } }\n )).toEqual({ a: { x: 1, y: 2 }, b: { z: 3 } });\n\n // Test with undefined values\n expect(deepMerge(\n { a: 1, b: undefined },\n { b: 2, c: 3 }\n )).toEqual({ a: 1, b: 2, c: 3 });\n\n // Test deeply nested structures\n expect(deepMerge(\n {\n a: {\n x: { deep: 1 },\n y: [1, 2]\n },\n b: 2\n },\n {\n a: {\n x: { deeper: 3 },\n y: [3, 4]\n },\n c: 3\n }\n )).toEqual({\n a: {\n x: { deep: 1, deeper: 3 },\n y: [3, 4]\n },\n b: 2,\n c: 3\n });\n\n // Test with empty objects\n expect(deepMerge({}, { a: 1 })).toEqual({ a: 1 });\n expect(deepMerge({ a: 1 }, {})).toEqual({ a: 1 });\n expect(deepMerge({}, {})).toEqual({});\n\n // Test that original objects are not modified\n const base = { a: { x: 1 }, b: 2 };\n const merge = { a: { y: 2 }, c: 3 };\n const baseClone = deepPlainClone(base);\n const mergeClone = deepPlainClone(merge);\n\n const result = deepMerge(base, merge);\n expect(base).toEqual(baseClone);\n expect(merge).toEqual(mergeClone);\n expect(result).toEqual({ a: { x: 1, y: 2 }, b: 2, c: 3 });\n\n // Test error cases\n expect(() => deepMerge({ a: () => {} }, { b: 2 })).toThrow();\n expect(() => deepMerge({ a: 1 }, { b: () => {} })).toThrow();\n expect(() => deepMerge({ a: Symbol() }, { b: 2 })).toThrow();\n expect(() => deepMerge({ a: 1 }, { b: Symbol() })).toThrow();\n});\n\nexport function typedEntries<T extends {}>(obj: T): [keyof T, T[keyof T]][] {\n return Object.entries(obj) as any;\n}\nundefined?.test(\"typedEntries\", ({ expect }) => {\n expect(typedEntries({})).toEqual([]);\n expect(typedEntries({ a: 1, b: 2 })).toEqual([[\"a\", 1], [\"b\", 2]]);\n expect(typedEntries({ a: \"hello\", b: true, c: null })).toEqual([[\"a\", \"hello\"], [\"b\", true], [\"c\", null]]);\n\n // Test with object containing methods\n const objWithMethod = { a: 1, b: () => \"test\" };\n const entries = typedEntries(objWithMethod);\n expect(entries.length).toBe(2);\n expect(entries[0][0]).toBe(\"a\");\n expect(entries[0][1]).toBe(1);\n expect(entries[1][0]).toBe(\"b\");\n expect(typeof entries[1][1]).toBe(\"function\");\n});\n\nexport function typedFromEntries<K extends PropertyKey, V>(entries: (readonly [K, V])[]): Record<K, V> {\n return Object.fromEntries(entries) as any;\n}\nundefined?.test(\"typedFromEntries\", ({ expect }) => {\n expect(typedFromEntries([])).toEqual({});\n expect(typedFromEntries([[\"a\", 1], [\"b\", 2]])).toEqual({ a: 1, b: 2 });\n\n // Test with mixed types (using type assertion)\n const mixedEntries = [[\"a\", \"hello\"], [\"b\", true], [\"c\", null]] as [string, string | boolean | null][];\n const mixedObj = typedFromEntries(mixedEntries);\n expect(mixedObj).toEqual({ a: \"hello\", b: true, c: null });\n\n // Test with function values\n const fn = () => \"test\";\n type MixedValue = number | (() => string);\n const fnEntries: [string, MixedValue][] = [[\"a\", 1], [\"b\", fn]];\n const obj = typedFromEntries(fnEntries);\n expect(obj.a).toBe(1);\n expect(typeof obj.b).toBe(\"function\");\n // Type assertion needed for the function call\n expect((obj.b as () => string)()).toBe(\"test\");\n});\n\nexport function typedKeys<T extends {}>(obj: T): (keyof T)[] {\n return Object.keys(obj) as any;\n}\nundefined?.test(\"typedKeys\", ({ expect }) => {\n expect(typedKeys({})).toEqual([]);\n expect(typedKeys({ a: 1, b: 2 })).toEqual([\"a\", \"b\"]);\n expect(typedKeys({ a: \"hello\", b: true, c: null })).toEqual([\"a\", \"b\", \"c\"]);\n\n // Test with object containing methods\n const objWithMethod = { a: 1, b: () => \"test\" };\n expect(typedKeys(objWithMethod)).toEqual([\"a\", \"b\"]);\n});\n\nexport function typedValues<T extends {}>(obj: T): T[keyof T][] {\n return Object.values(obj) as any;\n}\nundefined?.test(\"typedValues\", ({ expect }) => {\n expect(typedValues({})).toEqual([]);\n expect(typedValues({ a: 1, b: 2 })).toEqual([1, 2]);\n\n // Test with mixed types\n type MixedObj = { a: string, b: boolean, c: null };\n const mixedObj: MixedObj = { a: \"hello\", b: true, c: null };\n expect(typedValues(mixedObj)).toEqual([\"hello\", true, null]);\n\n // Test with object containing methods\n type ObjWithFn = { a: number, b: () => string };\n const fn = () => \"test\";\n const objWithMethod: ObjWithFn = { a: 1, b: fn };\n const values = typedValues(objWithMethod);\n expect(values.length).toBe(2);\n expect(values[0]).toBe(1);\n expect(typeof values[1]).toBe(\"function\");\n // Need to cast to the correct type\n const fnValue = values[1] as () => string;\n expect(fnValue()).toBe(\"test\");\n});\n\nexport function typedAssign<T extends {}, U extends {}>(target: T, source: U): T & U {\n return Object.assign(target, source);\n}\nundefined?.test(\"typedAssign\", ({ expect }) => {\n // Test with empty objects\n const emptyTarget = {};\n const emptyResult = typedAssign(emptyTarget, { a: 1 });\n expect(emptyResult).toEqual({ a: 1 });\n expect(emptyResult).toBe(emptyTarget); // Same reference\n\n // Test with non-empty target\n const target = { a: 1, b: 2 };\n const result = typedAssign(target, { c: 3, d: 4 });\n expect(result).toEqual({ a: 1, b: 2, c: 3, d: 4 });\n expect(result).toBe(target); // Same reference\n\n // Test with overlapping properties\n const targetWithOverlap = { a: 1, b: 2 };\n const resultWithOverlap = typedAssign(targetWithOverlap, { b: 3, c: 4 });\n expect(resultWithOverlap).toEqual({ a: 1, b: 3, c: 4 });\n expect(resultWithOverlap).toBe(targetWithOverlap); // Same reference\n});\n\nexport type FilterUndefined<T> =\n & { [k in keyof T as (undefined extends T[k] ? (T[k] extends undefined | void ? never : k) : never)]+?: T[k] & ({} | null) }\n & { [k in keyof T as (undefined extends T[k] ? never : k)]: T[k] & ({} | null) }\n\n/**\n * Returns a new object with all undefined values removed. Useful when spreading optional parameters on an object, as\n * TypeScript's `Partial<XYZ>` type allows `undefined` values.\n */\nexport function filterUndefined<T extends object>(obj: T): FilterUndefined<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as any;\n}\nundefined?.test(\"filterUndefined\", ({ expect }) => {\n expect(filterUndefined({})).toEqual({});\n expect(filterUndefined({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });\n expect(filterUndefined({ a: 1, b: undefined })).toEqual({ a: 1 });\n expect(filterUndefined({ a: undefined, b: undefined })).toEqual({});\n expect(filterUndefined({ a: null, b: undefined })).toEqual({ a: null });\n expect(filterUndefined({ a: 0, b: \"\", c: false, d: undefined })).toEqual({ a: 0, b: \"\", c: false });\n});\n\nexport type FilterUndefinedOrNull<T> = FilterUndefined<{ [k in keyof T]: null extends T[k] ? NonNullable<T[k]> | undefined : T[k] }>;\n\n/**\n * Returns a new object with all undefined and null values removed. Useful when spreading optional parameters on an object, as\n * TypeScript's `Partial<XYZ>` type allows `undefined` values.\n */\nexport function filterUndefinedOrNull<T extends object>(obj: T): FilterUndefinedOrNull<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== null)) as any;\n}\nundefined?.test(\"filterUndefinedOrNull\", ({ expect }) => {\n expect(filterUndefinedOrNull({})).toEqual({});\n expect(filterUndefinedOrNull({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 });\n});\n\nexport type DeepFilterUndefined<T> = T extends object ? FilterUndefined<{ [K in keyof T]: DeepFilterUndefined<T[K]> }> : T;\n\nexport function deepFilterUndefined<T extends object>(obj: T): DeepFilterUndefined<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined).map(([k, v]) => [k, isObjectLike(v) ? deepFilterUndefined(v) : v])) as any;\n}\nundefined?.test(\"deepFilterUndefined\", ({ expect }) => {\n expect(deepFilterUndefined({ a: 1, b: undefined })).toEqual({ a: 1 });\n});\n\nexport function pick<T extends {}, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n return Object.fromEntries(Object.entries(obj).filter(([k]) => keys.includes(k as K))) as any;\n}\nundefined?.test(\"pick\", ({ expect }) => {\n const obj = { a: 1, b: 2, c: 3, d: 4 };\n expect(pick(obj, [\"a\", \"c\"])).toEqual({ a: 1, c: 3 });\n expect(pick(obj, [])).toEqual({});\n expect(pick(obj, [\"a\", \"e\" as keyof typeof obj])).toEqual({ a: 1 });\n // Use type assertion for empty object to avoid TypeScript error\n expect(pick({} as Record<string, unknown>, [\"a\"])).toEqual({});\n});\n\nexport function omit<T extends {}, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\n if (!Array.isArray(keys)) throw new StackAssertionError(\"omit: keys must be an array\", { obj, keys });\n return Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k as K))) as any;\n}\nundefined?.test(\"omit\", ({ expect }) => {\n const obj = { a: 1, b: 2, c: 3, d: 4 };\n expect(omit(obj, [\"a\", \"c\"])).toEqual({ b: 2, d: 4 });\n expect(omit(obj, [])).toEqual(obj);\n expect(omit(obj, [\"a\", \"e\" as keyof typeof obj])).toEqual({ b: 2, c: 3, d: 4 });\n // Use type assertion for empty object to avoid TypeScript error\n expect(omit({} as Record<string, unknown>, [\"a\"])).toEqual({});\n});\n\nexport function split<T extends {}, K extends keyof T>(obj: T, keys: K[]): [Pick<T, K>, Omit<T, K>] {\n return [pick(obj, keys), omit(obj, keys)];\n}\nundefined?.test(\"split\", ({ expect }) => {\n const obj = { a: 1, b: 2, c: 3, d: 4 };\n expect(split(obj, [\"a\", \"c\"])).toEqual([{ a: 1, c: 3 }, { b: 2, d: 4 }]);\n expect(split(obj, [])).toEqual([{}, obj]);\n expect(split(obj, [\"a\", \"e\" as keyof typeof obj])).toEqual([{ a: 1 }, { b: 2, c: 3, d: 4 }]);\n // Use type assertion for empty object to avoid TypeScript error\n expect(split({} as Record<string, unknown>, [\"a\"])).toEqual([{}, {}]);\n});\n\nexport function mapValues<T extends object, U>(obj: T, fn: (value: T extends (infer E)[] ? E : T[keyof T]) => U): Record<keyof T, U> {\n if (Array.isArray(obj)) {\n return obj.map(v => fn(v)) as any;\n }\n return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, fn(v)])) as any;\n}\nundefined?.test(\"mapValues\", ({ expect }) => {\n expect(mapValues({ a: 1, b: 2 }, v => v * 2)).toEqual({ a: 2, b: 4 });\n expect(mapValues([1, 2, 3], v => v * 2)).toEqual([2, 4, 6]);\n});\n\nexport function sortKeys<T extends object>(obj: T): T {\n if (Array.isArray(obj)) {\n return [...obj] as any;\n }\n return Object.fromEntries(Object.entries(obj).sort(([a], [b]) => stringCompare(a, b))) as any;\n}\nundefined?.test(\"sortKeys\", ({ expect }) => {\n const obj = {\n \"1\": 0,\n \"10\": 1,\n b: 2,\n \"2\": 3,\n a: 4,\n \"-3.33\": 5,\n \"-4\": 6,\n \"-3\": 7,\n abc: 8,\n \"a-b\": 9,\n ab: 10,\n ac: 11,\n aa: 12,\n aab: 13,\n };\n expect(Object.entries(sortKeys(obj))).toEqual([\n [\"1\", 0],\n [\"2\", 3],\n [\"10\", 1],\n [\"-3\", 7],\n [\"-3.33\", 5],\n [\"-4\", 6],\n [\"a\", 4],\n [\"a-b\", 9],\n [\"aa\", 12],\n [\"aab\", 13],\n [\"ab\", 10],\n [\"abc\", 8],\n [\"ac\", 11],\n [\"b\", 2],\n ]);\n});\n\nexport function deepSortKeys<T extends object>(obj: T): T {\n return sortKeys(mapValues(obj, v => isObjectLike(v) ? deepSortKeys(v) : v)) as any;\n}\nundefined?.test(\"deepSortKeys\", ({ expect }) => {\n const obj = {\n h: { i: { k: 9, j: 8 }, l: 10 },\n b: { d: 3, c: 2 },\n a: 1,\n e: [4, 5, { g: 7, f: 6 }],\n };\n const sorted = deepSortKeys(obj);\n expect(Object.entries(sorted)).toEqual([\n [\"a\", 1],\n [\"b\", { c: 2, d: 3 }],\n [\"e\", [4, 5, { f: 6, g: 7 }]],\n [\"h\", { i: { j: 8, k: 9 }, l: 10 }],\n ]);\n expect(Object.entries(sorted.b)).toEqual([\n [\"c\", 2],\n [\"d\", 3],\n ]);\n expect(Object.entries(sorted.e[2])).toEqual([\n [\"f\", 6],\n [\"g\", 7],\n ]);\n expect(Object.entries(sorted.h)).toEqual([\n [\"i\", { j: 8, k: 9 }],\n [\"l\", 10],\n ]);\n expect(Object.entries(sorted.h.i)).toEqual([\n [\"j\", 8],\n [\"k\", 9],\n ]);\n});\n\nexport function set<T extends object, K extends keyof T>(obj: T, key: K, value: T[K]) {\n Object.defineProperty(obj, key, { value, writable: true, configurable: true, enumerable: true });\n}\n\nexport function get<T extends object, K extends keyof T>(obj: T, key: K): T[K] {\n const descriptor = Object.getOwnPropertyDescriptor(obj, key);\n if (!descriptor) throw new StackAssertionError(`get: key ${String(key)} does not exist`, { obj, key });\n return descriptor.value;\n}\n\nexport function getOrUndefined<T extends object, K extends keyof T>(obj: T, key: K): T[K] | undefined {\n return has(obj, key) ? get(obj, key) : undefined;\n}\n\nexport function has<T extends object, K extends keyof T>(obj: T, key: K): obj is T & { [k in K]: unknown } {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n\nundefined?.test(\"has\", ({ expect }) => {\n const obj = { a: 1, b: undefined, c: null };\n expect(has(obj, \"a\")).toBe(true);\n expect(has(obj, \"b\")).toBe(true);\n expect(has(obj, \"c\")).toBe(true);\n expect(has(obj, \"d\" as keyof typeof obj)).toBe(false);\n});\n\n\nexport function hasAndNotUndefined<T extends object, K extends keyof T>(obj: T, key: K): obj is T & { [k in K]: Exclude<T[K], undefined> } {\n return has(obj, key) && get(obj, key) !== undefined;\n}\n\nexport function deleteKey<T extends object, K extends keyof T>(obj: T, key: K) {\n if (has(obj, key)) {\n Reflect.deleteProperty(obj, key);\n } else {\n throw new StackAssertionError(`deleteKey: key ${String(key)} does not exist`, { obj, key });\n }\n}\n\nexport function isObjectLike(value: unknown): value is object {\n return (typeof value === 'object' || typeof value === 'function') && value !== null;\n}\n"],"mappings":"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","names":[]}
@@ -3,6 +3,11 @@ import React from "react";
3
3
  import { isBrowserLike } from "./env.js";
4
4
  import { neverResolve } from "./promises.js";
5
5
  import { deindent } from "./strings.js";
6
+ function componentWrapper(displayName, render) {
7
+ const Component = forwardRefIfNeeded(render);
8
+ Component.displayName = displayName;
9
+ return Component;
10
+ }
6
11
  function forwardRefIfNeeded(render) {
7
12
  const version = React.version;
8
13
  const major = parseInt(version.split(".")[0]);
@@ -31,6 +36,18 @@ function suspend() {
31
36
  React.use(neverResolve());
32
37
  throw new Error("Somehow a Promise that never resolves was resolved?");
33
38
  }
39
+ function mapRef(ref, mapper) {
40
+ let last = null;
41
+ return {
42
+ get current() {
43
+ const input = ref.current;
44
+ if (last === null || input !== last[0]) {
45
+ last = [input, mapper(input)];
46
+ }
47
+ return last[1];
48
+ }
49
+ };
50
+ }
34
51
  function useInstantState(initialValue) {
35
52
  const [, setState] = React.useState(initialValue);
36
53
  const ref = React.useRef(initialValue);
@@ -79,8 +96,10 @@ function suspendIfSsr(caller) {
79
96
  }
80
97
  export {
81
98
  NoSuspenseBoundaryError,
99
+ componentWrapper,
82
100
  forwardRefIfNeeded,
83
101
  getNodeText,
102
+ mapRef,
84
103
  suspend,
85
104
  suspendIfSsr,
86
105
  useInstantState
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/react.tsx"],"sourcesContent":["import React, { MutableRefObject } from \"react\";\nimport { isBrowserLike } from \"./env\";\nimport { neverResolve } from \"./promises\";\nimport { deindent } from \"./strings\";\n\nexport function forwardRefIfNeeded<T, P = {}>(render: React.ForwardRefRenderFunction<T, P>): React.FC<P & { ref?: React.Ref<T> }> {\n // TODO: when we drop support for react 18, remove this\n\n const version = React.version;\n const major = parseInt(version.split(\".\")[0]);\n if (major < 19) {\n return React.forwardRef<T, P>(render as any) as any;\n } else {\n return ((props: P) => render(props, (props as any).ref)) as any;\n }\n}\nundefined?.test(\"forwardRefIfNeeded\", ({ expect }) => {\n // Mock React.version and React.forwardRef\n const originalVersion = React.version;\n const originalForwardRef = React.forwardRef;\n\n try {\n // Test with React version < 19\n Object.defineProperty(React, 'version', { value: '18.2.0', writable: true });\n\n // Create a render function\n const renderFn = (props: any, ref: any) => null;\n\n // Call forwardRefIfNeeded\n const result = forwardRefIfNeeded(renderFn);\n\n // Verify the function returns something\n expect(result).toBeDefined();\n\n // Test with React version >= 19\n Object.defineProperty(React, 'version', { value: '19.0.0', writable: true });\n\n // Call forwardRefIfNeeded again with React 19\n const result19 = forwardRefIfNeeded(renderFn);\n\n // Verify the function returns something\n expect(result19).toBeDefined();\n } finally {\n // Restore original values\n Object.defineProperty(React, 'version', { value: originalVersion });\n React.forwardRef = originalForwardRef;\n }\n});\n\nexport function getNodeText(node: React.ReactNode): string {\n if ([\"number\", \"string\"].includes(typeof node)) {\n return `${node}`;\n }\n if (!node) {\n return \"\";\n }\n if (Array.isArray(node)) {\n return node.map(getNodeText).join(\"\");\n }\n if (typeof node === \"object\" && \"props\" in node) {\n return getNodeText(node.props.children);\n }\n throw new Error(`Unknown node type: ${typeof node}`);\n}\nundefined?.test(\"getNodeText\", ({ expect }) => {\n // Test with string\n expect(getNodeText(\"hello\")).toBe(\"hello\");\n\n // Test with number\n expect(getNodeText(42)).toBe(\"42\");\n\n // Test with null/undefined\n expect(getNodeText(null)).toBe(\"\");\n expect(getNodeText(undefined)).toBe(\"\");\n\n // Test with array\n expect(getNodeText([\"hello\", \" \", \"world\"])).toBe(\"hello world\");\n expect(getNodeText([1, 2, 3])).toBe(\"123\");\n\n // Test with mixed array\n expect(getNodeText([\"hello\", 42, null])).toBe(\"hello42\");\n\n // Test with React element (mocked)\n const mockElement = {\n props: {\n children: \"child text\"\n }\n } as React.ReactElement;\n expect(getNodeText(mockElement)).toBe(\"child text\");\n\n // Test with nested React elements\n const nestedElement = {\n props: {\n children: {\n props: {\n children: \"nested text\"\n }\n } as React.ReactElement\n }\n } as React.ReactElement;\n expect(getNodeText(nestedElement)).toBe(\"nested text\");\n\n // Test with array of React elements\n const arrayOfElements = [\n { props: { children: \"first\" } } as React.ReactElement,\n { props: { children: \"second\" } } as React.ReactElement\n ];\n expect(getNodeText(arrayOfElements)).toBe(\"firstsecond\");\n});\n\n/**\n * Suspends the currently rendered component indefinitely. Will not unsuspend unless the component rerenders.\n *\n * You can use this to translate older query- or AsyncResult-based code to new the Suspense system, for example: `if (query.isLoading) suspend();`\n */\nexport function suspend(): never {\n React.use(neverResolve());\n throw new Error(\"Somehow a Promise that never resolves was resolved?\");\n}\n\nexport type InstantStateRef<T> = Readonly<MutableRefObject<T>>;\n\n/**\n * Like useState, but its value is immediately available.\n */\nexport function useInstantState<T>(initialValue: T): [InstantStateRef<T>, (value: T) => void] {\n const [, setState] = React.useState(initialValue);\n const ref = React.useRef(initialValue);\n const setValue = React.useCallback((value: T) => {\n setState(value);\n ref.current = value;\n }, []);\n return [ref, setValue];\n}\n\nexport class NoSuspenseBoundaryError extends Error {\n digest: string;\n reason: string;\n\n constructor(options: { caller?: string }) {\n super(deindent`\n ${options.caller ?? \"This code path\"} attempted to display a loading indicator, but didn't find a Suspense boundary above it. Please read the error message below carefully.\n \n The fix depends on which of the 3 scenarios caused it:\n \n 1. You are missing a loading.tsx file in your app directory. Fix it by adding a loading.tsx file in your app directory.\n\n 2. The component is rendered in the root (outermost) layout.tsx or template.tsx file. Next.js does not wrap those files in a Suspense boundary, even if there is a loading.tsx file in the same folder. To fix it, wrap your layout inside a route group like this:\n\n - app\n - - layout.tsx // contains <html> and <body>, alongside providers and other components that don't need ${options.caller ?? \"this code path\"}\n - - loading.tsx // required for suspense\n - - (main)\n - - - layout.tsx // contains the main layout of your app, like a sidebar or a header, and can use ${options.caller ?? \"this code path\"}\n - - - route.tsx // your actual main page\n - - - the rest of your app\n\n For more information on this approach, see Next's documentation on route groups: https://nextjs.org/docs/app/building-your-application/routing/route-groups\n \n 3. You caught this error with try-catch or a custom error boundary. Fix this by rethrowing the error or not catching it in the first place.\n\n See: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n\n More information on SSR and Suspense boundaries: https://react.dev/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content\n `);\n\n this.name = \"NoSuspenseBoundaryError\";\n this.reason = options.caller ?? \"suspendIfSsr()\";\n\n // set the digest so nextjs doesn't log the error\n // https://github.com/vercel/next.js/blob/d01d6d9c35a8c2725b3d74c1402ab76d4779a6cf/packages/next/src/shared/lib/lazy-dynamic/bailout-to-csr.ts#L14\n this.digest = \"BAILOUT_TO_CLIENT_SIDE_RENDERING\";\n }\n}\nundefined?.test(\"NoSuspenseBoundaryError\", ({ expect }) => {\n // Test with default options\n const defaultError = new NoSuspenseBoundaryError({});\n expect(defaultError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(defaultError.reason).toBe(\"suspendIfSsr()\");\n expect(defaultError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(defaultError.message).toContain(\"This code path attempted to display a loading indicator\");\n\n // Test with custom caller\n const customError = new NoSuspenseBoundaryError({ caller: \"CustomComponent\" });\n expect(customError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(customError.reason).toBe(\"CustomComponent\");\n expect(customError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(customError.message).toContain(\"CustomComponent attempted to display a loading indicator\");\n\n // Verify error message contains all the necessary information\n expect(customError.message).toContain(\"loading.tsx\");\n expect(customError.message).toContain(\"route groups\");\n expect(customError.message).toContain(\"https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\");\n});\n\n\n/**\n * Use this in a component or a hook to disable SSR. Should be wrapped in a Suspense boundary, or it will throw an error.\n */\nexport function suspendIfSsr(caller?: string) {\n if (!isBrowserLike()) {\n throw new NoSuspenseBoundaryError({ caller });\n }\n}\n"],"mappings":";AAAA,OAAO,WAAiC;AACxC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AAElB,SAAS,mBAA8B,QAAoF;AAGhI,QAAM,UAAU,MAAM;AACtB,QAAM,QAAQ,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAC5C,MAAI,QAAQ,IAAI;AACd,WAAO,MAAM,WAAiB,MAAa;AAAA,EAC7C,OAAO;AACL,WAAQ,CAAC,UAAa,OAAO,OAAQ,MAAc,GAAG;AAAA,EACxD;AACF;AAkCO,SAAS,YAAY,MAA+B;AACzD,MAAI,CAAC,UAAU,QAAQ,EAAE,SAAS,OAAO,IAAI,GAAG;AAC9C,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK,IAAI,WAAW,EAAE,KAAK,EAAE;AAAA,EACtC;AACA,MAAI,OAAO,SAAS,YAAY,WAAW,MAAM;AAC/C,WAAO,YAAY,KAAK,MAAM,QAAQ;AAAA,EACxC;AACA,QAAM,IAAI,MAAM,sBAAsB,OAAO,IAAI,EAAE;AACrD;AAoDO,SAAS,UAAiB;AAC/B,QAAM,IAAI,aAAa,CAAC;AACxB,QAAM,IAAI,MAAM,qDAAqD;AACvE;AAOO,SAAS,gBAAmB,cAA2D;AAC5F,QAAM,CAAC,EAAE,QAAQ,IAAI,MAAM,SAAS,YAAY;AAChD,QAAM,MAAM,MAAM,OAAO,YAAY;AACrC,QAAM,WAAW,MAAM,YAAY,CAAC,UAAa;AAC/C,aAAS,KAAK;AACd,QAAI,UAAU;AAAA,EAChB,GAAG,CAAC,CAAC;AACL,SAAO,CAAC,KAAK,QAAQ;AACvB;AAEO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EAIjD,YAAY,SAA8B;AACxC,UAAM;AAAA,QACF,QAAQ,UAAU,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kHASwE,QAAQ,UAAU,gBAAgB;AAAA;AAAA;AAAA,6GAGvC,QAAQ,UAAU,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAW1I;AAED,SAAK,OAAO;AACZ,SAAK,SAAS,QAAQ,UAAU;AAIhC,SAAK,SAAS;AAAA,EAChB;AACF;AA0BO,SAAS,aAAa,QAAiB;AAC5C,MAAI,CAAC,cAAc,GAAG;AACpB,UAAM,IAAI,wBAAwB,EAAE,OAAO,CAAC;AAAA,EAC9C;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/react.tsx"],"sourcesContent":["import React from \"react\";\nimport { isBrowserLike } from \"./env\";\nimport { neverResolve } from \"./promises\";\nimport { deindent } from \"./strings\";\n\nexport function componentWrapper<\n C extends React.ComponentType<any> | keyof React.JSX.IntrinsicElements,\n ExtraProps extends {} = {}\n>(displayName: string, render: React.ForwardRefRenderFunction<RefFromComponent<C>, React.ComponentPropsWithRef<C> & ExtraProps>) {\n const Component = forwardRefIfNeeded(render);\n Component.displayName = displayName;\n return Component;\n}\ntype RefFromComponent<C extends React.ComponentType<any> | keyof React.JSX.IntrinsicElements> = NonNullable<RefFromComponentDistCond<React.ComponentPropsWithRef<C>[\"ref\"]>>;\ntype RefFromComponentDistCond<A> = A extends React.RefObject<infer T> ? T : never; // distributive conditional type; see https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types\n\nexport function forwardRefIfNeeded<T, P = {}>(render: React.ForwardRefRenderFunction<T, P>): React.FC<P & { ref?: React.Ref<T> }> {\n // TODO: when we drop support for react 18, remove this\n\n const version = React.version;\n const major = parseInt(version.split(\".\")[0]);\n if (major < 19) {\n return React.forwardRef<T, P>(render as any) as any;\n } else {\n return ((props: P) => render(props, (props as any).ref)) as any;\n }\n}\n\nexport function getNodeText(node: React.ReactNode): string {\n if ([\"number\", \"string\"].includes(typeof node)) {\n return `${node}`;\n }\n if (!node) {\n return \"\";\n }\n if (Array.isArray(node)) {\n return node.map(getNodeText).join(\"\");\n }\n if (typeof node === \"object\" && \"props\" in node) {\n return getNodeText(node.props.children);\n }\n throw new Error(`Unknown node type: ${typeof node}`);\n}\nundefined?.test(\"getNodeText\", ({ expect }) => {\n // Test with string\n expect(getNodeText(\"hello\")).toBe(\"hello\");\n\n // Test with number\n expect(getNodeText(42)).toBe(\"42\");\n\n // Test with null/undefined\n expect(getNodeText(null)).toBe(\"\");\n expect(getNodeText(undefined)).toBe(\"\");\n\n // Test with array\n expect(getNodeText([\"hello\", \" \", \"world\"])).toBe(\"hello world\");\n expect(getNodeText([1, 2, 3])).toBe(\"123\");\n\n // Test with mixed array\n expect(getNodeText([\"hello\", 42, null])).toBe(\"hello42\");\n\n // Test with React element (mocked)\n const mockElement = {\n props: {\n children: \"child text\"\n }\n } as React.ReactElement;\n expect(getNodeText(mockElement)).toBe(\"child text\");\n\n // Test with nested React elements\n const nestedElement = {\n props: {\n children: {\n props: {\n children: \"nested text\"\n }\n } as React.ReactElement\n }\n } as React.ReactElement;\n expect(getNodeText(nestedElement)).toBe(\"nested text\");\n\n // Test with array of React elements\n const arrayOfElements = [\n { props: { children: \"first\" } } as React.ReactElement,\n { props: { children: \"second\" } } as React.ReactElement\n ];\n expect(getNodeText(arrayOfElements)).toBe(\"firstsecond\");\n});\n\n/**\n * Suspends the currently rendered component indefinitely. Will not unsuspend unless the component rerenders.\n *\n * You can use this to translate older query- or AsyncResult-based code to new the Suspense system, for example: `if (query.isLoading) suspend();`\n */\nexport function suspend(): never {\n React.use(neverResolve());\n throw new Error(\"Somehow a Promise that never resolves was resolved?\");\n}\n\nexport function mapRef<T, R>(ref: ReadonlyRef<T>, mapper: (value: T) => R): ReadonlyRef<R> {\n let last: [T, R] | null = null;\n return {\n get current() {\n const input = ref.current;\n if (last === null || input !== last[0]) {\n last = [input, mapper(input)];\n }\n return last[1];\n },\n };\n}\n\nexport type ReadonlyRef<T> = {\n readonly current: T,\n};\n\n/**\n * Like useState, but its value is immediately available.\n */\nexport function useInstantState<T>(initialValue: T): [ReadonlyRef<T>, (value: T) => void] {\n const [, setState] = React.useState(initialValue);\n const ref = React.useRef(initialValue);\n const setValue = React.useCallback((value: T) => {\n setState(value);\n ref.current = value;\n }, []);\n return [ref, setValue];\n}\n\nexport class NoSuspenseBoundaryError extends Error {\n digest: string;\n reason: string;\n\n constructor(options: { caller?: string }) {\n super(deindent`\n ${options.caller ?? \"This code path\"} attempted to display a loading indicator, but didn't find a Suspense boundary above it. Please read the error message below carefully.\n \n The fix depends on which of the 3 scenarios caused it:\n \n 1. You are missing a loading.tsx file in your app directory. Fix it by adding a loading.tsx file in your app directory.\n\n 2. The component is rendered in the root (outermost) layout.tsx or template.tsx file. Next.js does not wrap those files in a Suspense boundary, even if there is a loading.tsx file in the same folder. To fix it, wrap your layout inside a route group like this:\n\n - app\n - - layout.tsx // contains <html> and <body>, alongside providers and other components that don't need ${options.caller ?? \"this code path\"}\n - - loading.tsx // required for suspense\n - - (main)\n - - - layout.tsx // contains the main layout of your app, like a sidebar or a header, and can use ${options.caller ?? \"this code path\"}\n - - - route.tsx // your actual main page\n - - - the rest of your app\n\n For more information on this approach, see Next's documentation on route groups: https://nextjs.org/docs/app/building-your-application/routing/route-groups\n \n 3. You caught this error with try-catch or a custom error boundary. Fix this by rethrowing the error or not catching it in the first place.\n\n See: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n\n More information on SSR and Suspense boundaries: https://react.dev/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content\n `);\n\n this.name = \"NoSuspenseBoundaryError\";\n this.reason = options.caller ?? \"suspendIfSsr()\";\n\n // set the digest so nextjs doesn't log the error\n // https://github.com/vercel/next.js/blob/d01d6d9c35a8c2725b3d74c1402ab76d4779a6cf/packages/next/src/shared/lib/lazy-dynamic/bailout-to-csr.ts#L14\n this.digest = \"BAILOUT_TO_CLIENT_SIDE_RENDERING\";\n }\n}\nundefined?.test(\"NoSuspenseBoundaryError\", ({ expect }) => {\n // Test with default options\n const defaultError = new NoSuspenseBoundaryError({});\n expect(defaultError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(defaultError.reason).toBe(\"suspendIfSsr()\");\n expect(defaultError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(defaultError.message).toContain(\"This code path attempted to display a loading indicator\");\n\n // Test with custom caller\n const customError = new NoSuspenseBoundaryError({ caller: \"CustomComponent\" });\n expect(customError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(customError.reason).toBe(\"CustomComponent\");\n expect(customError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(customError.message).toContain(\"CustomComponent attempted to display a loading indicator\");\n\n // Verify error message contains all the necessary information\n expect(customError.message).toContain(\"loading.tsx\");\n expect(customError.message).toContain(\"route groups\");\n expect(customError.message).toContain(\"https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\");\n});\n\n\n/**\n * Use this in a component or a hook to disable SSR. Should be wrapped in a Suspense boundary, or it will throw an error.\n */\nexport function suspendIfSsr(caller?: string) {\n if (!isBrowserLike()) {\n throw new NoSuspenseBoundaryError({ caller });\n }\n}\n"],"mappings":";AAAA,OAAO,WAAW;AAClB,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AAElB,SAAS,iBAGd,aAAqB,QAA0G;AAC/H,QAAM,YAAY,mBAAmB,MAAM;AAC3C,YAAU,cAAc;AACxB,SAAO;AACT;AAIO,SAAS,mBAA8B,QAAoF;AAGhI,QAAM,UAAU,MAAM;AACtB,QAAM,QAAQ,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAC5C,MAAI,QAAQ,IAAI;AACd,WAAO,MAAM,WAAiB,MAAa;AAAA,EAC7C,OAAO;AACL,WAAQ,CAAC,UAAa,OAAO,OAAQ,MAAc,GAAG;AAAA,EACxD;AACF;AAEO,SAAS,YAAY,MAA+B;AACzD,MAAI,CAAC,UAAU,QAAQ,EAAE,SAAS,OAAO,IAAI,GAAG;AAC9C,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,KAAK,IAAI,WAAW,EAAE,KAAK,EAAE;AAAA,EACtC;AACA,MAAI,OAAO,SAAS,YAAY,WAAW,MAAM;AAC/C,WAAO,YAAY,KAAK,MAAM,QAAQ;AAAA,EACxC;AACA,QAAM,IAAI,MAAM,sBAAsB,OAAO,IAAI,EAAE;AACrD;AAoDO,SAAS,UAAiB;AAC/B,QAAM,IAAI,aAAa,CAAC;AACxB,QAAM,IAAI,MAAM,qDAAqD;AACvE;AAEO,SAAS,OAAa,KAAqB,QAAyC;AACzF,MAAI,OAAsB;AAC1B,SAAO;AAAA,IACL,IAAI,UAAU;AACZ,YAAM,QAAQ,IAAI;AAClB,UAAI,SAAS,QAAQ,UAAU,KAAK,CAAC,GAAG;AACtC,eAAO,CAAC,OAAO,OAAO,KAAK,CAAC;AAAA,MAC9B;AACA,aAAO,KAAK,CAAC;AAAA,IACf;AAAA,EACF;AACF;AASO,SAAS,gBAAmB,cAAuD;AACxF,QAAM,CAAC,EAAE,QAAQ,IAAI,MAAM,SAAS,YAAY;AAChD,QAAM,MAAM,MAAM,OAAO,YAAY;AACrC,QAAM,WAAW,MAAM,YAAY,CAAC,UAAa;AAC/C,aAAS,KAAK;AACd,QAAI,UAAU;AAAA,EAChB,GAAG,CAAC,CAAC;AACL,SAAO,CAAC,KAAK,QAAQ;AACvB;AAEO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EAIjD,YAAY,SAA8B;AACxC,UAAM;AAAA,QACF,QAAQ,UAAU,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kHASwE,QAAQ,UAAU,gBAAgB;AAAA;AAAA;AAAA,6GAGvC,QAAQ,UAAU,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAW1I;AAED,SAAK,OAAO;AACZ,SAAK,SAAS,QAAQ,UAAU;AAIhC,SAAK,SAAS;AAAA,EAChB;AACF;AA0BO,SAAS,aAAa,QAAiB;AAC5C,MAAI,CAAC,cAAc,GAAG;AACpB,UAAM,IAAI,wBAAwB,EAAE,OAAO,CAAC;AAAA,EAC9C;AACF;","names":[]}
@@ -121,7 +121,7 @@ var StackClientInterface = class {
121
121
  );
122
122
  if (retriedResult.status === "error") {
123
123
  if (import_globals.globalVar.navigator && !import_globals.globalVar.navigator.onLine) {
124
- throw new Error("Failed to send Stack network request. It seems like you are offline, please check your internet connection and try again. This is not an error with Stack Auth. (window.navigator.onLine is falsy)", { cause: retriedResult.error });
124
+ throw new Error("You are offline. Please check your internet connection and try again. (window.navigator.onLine is falsy)", { cause: retriedResult.error });
125
125
  }
126
126
  throw await this._createNetworkError(retriedResult.error, session, requestType);
127
127
  }