/** * A type that removes the `.docs` from the given string type `T`. * Mainly used to target "join" field in PayloadCMS. * * @example * ```ts * type CleanedString = RemoveDoc<"example.docs.a.b.docs.c">; // "example.a.b.c" * ``` */ export type RemoveDotDoc = T extends `${infer A}.docs${infer B}` ? RemoveDotDoc<`${A}${B}`> : T; // 1) Depth utilities, with Prev clamped to 0 type BuildArray< N extends number, Arr extends unknown[] = [], > = Arr["length"] extends N ? Arr : BuildArray; type Prev = D extends 0 ? 0 : BuildArray extends [unknown, ...infer Rest] ? Rest["length"] : never; // 2) MaxDepth default export type DefaultQueryMaxDepth = 5; // 3) ObjectPaths // - always emit the immediate key // - recurse only when D > 0 and the type is a non-string object export type ObjectPaths< T, D extends number = DefaultQueryMaxDepth, P extends string = "", > = T extends object ? RemoveDotDoc<{ [K in keyof T & (string | number)]: | `${P}${K}` | ( D extends 0 ? never : Exclude extends Array ? ObjectPaths, Prev, `${P}${K}.`> : Exclude extends object ? ObjectPaths, Prev, `${P}${K}.`> : never ); }[keyof T & (string | number)]> : never;