fork of hey-api/openapi-ts because I need some additional things
1import type { FromRef, FromRefs, Ref, Refs } from './types';
2
3/**
4 * Wraps a single value in a Ref object.
5 *
6 * If the value is already a Ref, returns it as-is (idempotent).
7 *
8 * @example
9 * ```ts
10 * const r = ref(123); // { '~ref': 123 }
11 * console.log(r['~ref']); // 123
12 *
13 * const r2 = ref(r); // { '~ref': 123 } (not double-wrapped)
14 * ```
15 */
16export const ref = <T>(value: T): Ref<T> => {
17 if (isRef(value)) {
18 return value as Ref<T>;
19 }
20 return { '~ref': value } as Ref<T>;
21};
22
23/**
24 * Converts a plain object to an object of Refs (deep, per property).
25 *
26 * @example
27 * ```ts
28 * const obj = { a: 1, b: "x" };
29 * const refs = refs(obj); // { a: { '~ref': 1 }, b: { '~ref': "x" } }
30 * ```
31 */
32export const refs = <T extends Record<string, unknown>>(obj: T): Refs<T> => {
33 const result = {} as Refs<T>;
34 for (const key in obj) {
35 if (Object.prototype.hasOwnProperty.call(obj, key)) {
36 result[key] = ref(obj[key]);
37 }
38 }
39 return result;
40};
41
42/**
43 * Unwraps a single Ref object to its value.
44 *
45 * @example
46 * ```ts
47 * const r = { '~ref': 42 };
48 * const n = fromRef(r); // 42
49 * console.log(n); // 42
50 * ```
51 */
52export const fromRef = <T extends Ref<unknown> | undefined>(ref: T): FromRef<T> =>
53 ref?.['~ref'] as FromRef<T>;
54
55/**
56 * Converts an object of Refs back to a plain object (unwraps all refs).
57 *
58 * @example
59 * ```ts
60 * const refs = { a: { '~ref': 1 }, b: { '~ref': "x" } };
61 * const plain = fromRefs(refs); // { a: 1, b: "x" }
62 * ```
63 */
64export const fromRefs = <T extends Refs<Record<string, unknown>>>(obj: T): FromRefs<T> => {
65 const result = {} as FromRefs<T>;
66 for (const key in obj) {
67 if (Object.prototype.hasOwnProperty.call(obj, key)) {
68 result[key] = fromRef(obj[key]!) as (typeof result)[typeof key];
69 }
70 }
71 return result;
72};
73
74/**
75 * Checks whether a value is a Ref object.
76 *
77 * @param value Value to check
78 * @returns True if the value is a Ref object.
79 */
80export const isRef = <T>(value: unknown): value is Ref<T> =>
81 typeof value === 'object' && value !== null && '~ref' in value;