deep-case-crafter 1.0.0 → 2.0.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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.cts +231 -0
  3. package/dist/index.d.mts +231 -0
  4. package/dist/index.d.ts +230 -4
  5. package/dist/index.js +1 -1
  6. package/dist/index.mjs +1 -0
  7. package/package.json +33 -23
  8. package/readme.md +63 -46
  9. package/dist/constants/formatterMap.d.ts +0 -21
  10. package/dist/constants/regex.d.ts +0 -9
  11. package/dist/dataTransformers/primitiveTransformer.d.ts +0 -7
  12. package/dist/dataTransformers/transformArray.d.ts +0 -19
  13. package/dist/dataTransformers/transformMap.d.ts +0 -18
  14. package/dist/dataTransformers/transformObject.d.ts +0 -21
  15. package/dist/dataTransformers/transformSingleWord.d.ts +0 -8
  16. package/dist/index.esm.js +0 -1
  17. package/dist/transform/internalTransform.d.ts +0 -15
  18. package/dist/transform/transform.d.ts +0 -21
  19. package/dist/transform/transformCase.d.ts +0 -23
  20. package/dist/types/helperTypes.d.ts +0 -3
  21. package/dist/types/stringCaseTypes.d.ts +0 -4
  22. package/dist/types/transformOptionTypes.d.ts +0 -41
  23. package/dist/types/transformTypes.d.ts +0 -279
  24. package/dist/utils/caseDetectors/isCamelCase.d.ts +0 -13
  25. package/dist/utils/caseDetectors/isKebabCase.d.ts +0 -13
  26. package/dist/utils/caseDetectors/isPascalCase.d.ts +0 -14
  27. package/dist/utils/caseDetectors/isSnakeCase.d.ts +0 -14
  28. package/dist/utils/detectSingleWord.d.ts +0 -37
  29. package/dist/utils/detectStringCase.d.ts +0 -17
  30. package/dist/utils/prepareStringTransformation.d.ts +0 -20
  31. package/dist/utils/stringFormatters/camelToKebabCase.d.ts +0 -14
  32. package/dist/utils/stringFormatters/camelToPascalCase.d.ts +0 -14
  33. package/dist/utils/stringFormatters/camelToSnakeCase.d.ts +0 -14
  34. package/dist/utils/stringFormatters/kebabToCamelCase.d.ts +0 -14
  35. package/dist/utils/stringFormatters/kebabToPascalCase.d.ts +0 -14
  36. package/dist/utils/stringFormatters/kebabToSnakeCase.d.ts +0 -14
  37. package/dist/utils/stringFormatters/pascalToCamelCase.d.ts +0 -14
  38. package/dist/utils/stringFormatters/pascalToKebabCase.d.ts +0 -15
  39. package/dist/utils/stringFormatters/pascalToSnakeCase.d.ts +0 -15
  40. package/dist/utils/stringFormatters/snakeToCamelCase.d.ts +0 -14
  41. package/dist/utils/stringFormatters/snakeToKebabCase.d.ts +0 -14
  42. package/dist/utils/stringFormatters/snakeToPascalCase.d.ts +0 -14
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 gyrgy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Represents the supported string case formats for transformation
3
+ */
4
+ type StringCase = 'camel' | 'pascal' | 'snake' | 'kebab';
5
+
6
+ /**
7
+ * Options for the transform function
8
+ */
9
+ interface TransformOptions {
10
+ /**
11
+ * The target casing format to transform to
12
+ * @default 'camel'
13
+ */
14
+ targetCase?: StringCase;
15
+ /**
16
+ * The source casing format to transform from
17
+ *
18
+ * When specified:
19
+ * - Provides precise TypeScript type transformations
20
+ * - Bypasses runtime case detection (more efficient)
21
+ * - Ensures consistent results if input has mixed casing
22
+ *
23
+ * When omitted:
24
+ * - Automatic case detection is used at runtime
25
+ * - TypeScript types will be less precise (string keys)
26
+ * - Works with mixed case inputs (each key detected separately)
27
+ *
28
+ * @example
29
+ * // With source specified - precise types
30
+ * const result = transform(data, { targetCase: 'camel', sourceCase: 'snake' });
31
+ * // result has exact transformed types
32
+ *
33
+ * // Without source - flexible runtime behavior
34
+ * const result = transform(data, { targetCase: 'camel' });
35
+ * // TypeScript types are more general
36
+ *
37
+ * @default undefined (automatic detection)
38
+ */
39
+ sourceCase?: StringCase;
40
+ }
41
+
42
+ /**
43
+ * Type utility that transforms a snake_case string to camelCase
44
+ * Example: 'hello_world' -> 'helloWorld'
45
+ */
46
+ type SnakeToCamel<S extends string> = S extends `${infer P}_${infer C}${infer R}` ? `${P}${Uppercase<C>}${SnakeToCamel<R>}` : S;
47
+ /**
48
+ * Type utility that transforms a snake_case string to PascalCase
49
+ * Example: 'hello_world' -> 'HelloWorld'
50
+ */
51
+ type SnakeWordsToPascal<Parts extends string[]> = Parts extends [
52
+ infer First extends string,
53
+ ...infer Rest extends string[]
54
+ ] ? `${Capitalize<First>}${SnakeWordsToPascal<Rest>}` : '';
55
+ type SnakeToWords<S extends string> = S extends `${infer P}_${infer R}` ? [P, ...SnakeToWords<R>] : [S];
56
+ type SnakeToPascal<S extends string> = S extends `${infer P}_${infer R}` ? SnakeWordsToPascal<[P, ...SnakeToWords<R>]> : Capitalize<S>;
57
+ /**
58
+ * Type utility that transforms a snake_case string to kebab-case
59
+ * Example: 'hello_world' -> 'hello-world'
60
+ */
61
+ type SnakeToKebab<S extends string> = S extends `${infer P}_${infer R}` ? `${P}-${SnakeToKebab<R>}` : S;
62
+ /**
63
+ * Type utility that transforms a camelCase string to snake_case
64
+ * Example: 'helloWorld' -> 'hello_world'
65
+ */
66
+ type CamelToSnake<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `_${Lowercase<C>}${CamelToSnake<R>}` : `${C}${CamelToSnake<R>}` : S;
67
+ /**
68
+ * Type utility that transforms a camelCase string to PascalCase
69
+ * Example: 'helloWorld' -> 'HelloWorld'
70
+ */
71
+ type CamelToPascal<S extends string> = Capitalize<S>;
72
+ /**
73
+ * Type utility that transforms a camelCase string to kebab-case
74
+ * Example: 'helloWorld' -> 'hello-world'
75
+ */
76
+ type CamelToKebab<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `-${Lowercase<C>}${CamelToKebab<R>}` : `${C}${CamelToKebab<R>}` : S;
77
+ /**
78
+ * Type utility that transforms a PascalCase string to camelCase
79
+ * Example: 'HelloWorld' -> 'helloWorld'
80
+ */
81
+ type PascalToCamel<S extends string> = S extends `${infer F}${infer R}` ? `${Lowercase<F>}${R}` : S;
82
+ /**
83
+ * Type utility that transforms a PascalCase string to snake_case
84
+ * Example: 'HelloWorld' -> 'hello_world'
85
+ */
86
+ type PascalToSnake<S extends string> = S extends `${infer F}${infer R}` ? R extends `` ? Lowercase<F> : `${Lowercase<F>}${PascalToSnakeInner<R>}` : S;
87
+ type PascalToSnakeInner<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `_${Lowercase<C>}${PascalToSnakeInner<R>}` : `${C}${PascalToSnakeInner<R>}` : S;
88
+ /**
89
+ * Type utility that transforms a PascalCase string to kebab-case
90
+ * Example: 'HelloWorld' -> 'hello-world'
91
+ */
92
+ type PascalToKebab<S extends string> = S extends `${infer F}${infer R}` ? R extends `` ? Lowercase<F> : `${Lowercase<F>}${PascalToKebabInner<R>}` : S;
93
+ type PascalToKebabInner<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `-${Lowercase<C>}${PascalToKebabInner<R>}` : `${C}${PascalToKebabInner<R>}` : S;
94
+ /**
95
+ * Type utility that transforms a kebab-case string to camelCase
96
+ * Example: 'hello-world' -> 'helloWorld'
97
+ */
98
+ type KebabToCamel<S extends string> = S extends `${infer P}-${infer C}${infer R}` ? `${P}${Uppercase<C>}${KebabToCamel<R>}` : S;
99
+ /**
100
+ * Type utility that transforms a kebab-case string to PascalCase
101
+ * Example: 'hello-world' -> 'HelloWorld'
102
+ */
103
+ type KebabWordsToPascal<Parts extends string[]> = Parts extends [
104
+ infer First extends string,
105
+ ...infer Rest extends string[]
106
+ ] ? `${Capitalize<First>}${KebabWordsToPascal<Rest>}` : '';
107
+ type KebabToWords<S extends string> = S extends `${infer P}-${infer R}` ? [P, ...KebabToWords<R>] : [S];
108
+ /**
109
+ * Type utility that transforms a kebab-case string to PascalCase
110
+ * Example: 'hello-world' -> 'HelloWorld'
111
+ */
112
+ type KebabToPascal<S extends string> = S extends `${infer P}-${infer R}` ? KebabWordsToPascal<[P, ...KebabToWords<R>]> : Capitalize<S>;
113
+ /**
114
+ * Type utility that transforms a kebab-case string to snake_case
115
+ * Example: 'hello-world' -> 'hello_world'
116
+ */
117
+ type KebabToSnake<S extends string> = S extends `${infer P}-${infer R}` ? `${P}_${KebabToSnake<R>}` : S;
118
+ /**
119
+ * Utility type to detect preserved keys that shouldn't be transformed.
120
+ * Preserved keys include those with leading/trailing special characters,
121
+ * unsupported patterns, or invalid starting/ending characters.
122
+ */
123
+ type ForbiddenStartChars = '_' | '-' | '$' | '&' | '%' | '#' | '@' | '!' | '*' | '+' | '=' | '~' | '`' | '^' | '(' | ')' | '[' | ']' | '{' | '}' | '|' | '\\' | ':' | ';' | '"' | "'" | '<' | '>' | ',' | '.' | '?' | '/';
124
+ type ForbiddenEndChars = '_' | '-' | '$' | '&' | '%' | '#' | '@' | '!' | '*' | '+' | '=' | '~' | '`' | '^' | '(' | ')' | '[' | ']' | '{' | '}' | '|' | '\\' | ':' | ';' | '"' | "'" | '<' | '>' | ',' | '.' | '?' | '/' | `${number}`;
125
+ type PreservedKey<K extends string> = K extends `${infer First}${string}` ? First extends ForbiddenStartChars ? true : K extends `${string}${infer Last}` ? Last extends ForbiddenEndChars ? true : K extends `${string}__${string}` | `${string}--${string}` ? true : false : false : false;
126
+ /**
127
+ * Type utility that selects the correct string transformation based on source and target casing
128
+ */
129
+ type TransformKey<K extends string, O extends TransformOptions> = PreservedKey<K> extends true ? K : undefined extends O['sourceCase'] ? string : O['sourceCase'] extends 'snake' ? undefined extends O['targetCase'] ? SnakeToCamel<K> : O['targetCase'] extends 'camel' ? SnakeToCamel<K> : O['targetCase'] extends 'pascal' ? SnakeToPascal<K> : O['targetCase'] extends 'kebab' ? SnakeToKebab<K> : K : O['sourceCase'] extends 'camel' ? undefined extends O['targetCase'] ? K : O['targetCase'] extends 'snake' ? CamelToSnake<K> : O['targetCase'] extends 'pascal' ? CamelToPascal<K> : O['targetCase'] extends 'kebab' ? CamelToKebab<K> : K : O['sourceCase'] extends 'pascal' ? undefined extends O['targetCase'] ? PascalToCamel<K> : O['targetCase'] extends 'camel' ? PascalToCamel<K> : O['targetCase'] extends 'snake' ? PascalToSnake<K> : O['targetCase'] extends 'kebab' ? PascalToKebab<K> : K : O['sourceCase'] extends 'kebab' ? undefined extends O['targetCase'] ? KebabToCamel<K> : O['targetCase'] extends 'camel' ? KebabToCamel<K> : O['targetCase'] extends 'pascal' ? KebabToPascal<K> : O['targetCase'] extends 'snake' ? KebabToSnake<K> : K : K;
130
+ /**
131
+ * Recursive type transformations
132
+ * These types handle nested structures like arrays, objects, Maps, and Sets
133
+ */
134
+ type SnakeToCamelRecursive<T> = T extends Array<infer U> ? Array<SnakeToCamelRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? SnakeToCamel<K> : K, SnakeToCamelRecursive<V>> : T extends Set<infer V> ? Set<SnakeToCamelRecursive<V>> : T extends object ? {
135
+ [K in keyof T as TransformKey<K & string, {
136
+ sourceCase: 'snake';
137
+ targetCase: 'camel';
138
+ }>]: SnakeToCamelRecursive<T[K]>;
139
+ } : T;
140
+ type SnakeToPascalRecursive<T> = T extends Array<infer U> ? Array<SnakeToPascalRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? SnakeToPascal<K> : K, SnakeToPascalRecursive<V>> : T extends Set<infer V> ? Set<SnakeToPascalRecursive<V>> : T extends object ? {
141
+ [K in keyof T as TransformKey<K & string, {
142
+ sourceCase: 'snake';
143
+ targetCase: 'pascal';
144
+ }>]: SnakeToPascalRecursive<T[K]>;
145
+ } : T;
146
+ type SnakeToKebabRecursive<T> = T extends Array<infer U> ? Array<SnakeToKebabRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? SnakeToKebab<K> : K, SnakeToKebabRecursive<V>> : T extends Set<infer V> ? Set<SnakeToKebabRecursive<V>> : T extends object ? {
147
+ [K in keyof T as TransformKey<K & string, {
148
+ sourceCase: 'snake';
149
+ targetCase: 'kebab';
150
+ }>]: SnakeToKebabRecursive<T[K]>;
151
+ } : T;
152
+ type CamelToSnakeRecursive<T> = T extends Array<infer U> ? Array<CamelToSnakeRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? CamelToSnake<K> : K, CamelToSnakeRecursive<V>> : T extends Set<infer V> ? Set<CamelToSnakeRecursive<V>> : T extends object ? {
153
+ [K in keyof T as TransformKey<K & string, {
154
+ sourceCase: 'camel';
155
+ targetCase: 'snake';
156
+ }>]: CamelToSnakeRecursive<T[K]>;
157
+ } : T;
158
+ type CamelToPascalRecursive<T> = T extends Array<infer U> ? Array<CamelToPascalRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? CamelToPascal<K> : K, CamelToPascalRecursive<V>> : T extends Set<infer V> ? Set<CamelToPascalRecursive<V>> : T extends object ? {
159
+ [K in keyof T as TransformKey<K & string, {
160
+ sourceCase: 'camel';
161
+ targetCase: 'pascal';
162
+ }>]: CamelToPascalRecursive<T[K]>;
163
+ } : T;
164
+ type CamelToKebabRecursive<T> = T extends Array<infer U> ? Array<CamelToKebabRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? CamelToKebab<K> : K, CamelToKebabRecursive<V>> : T extends Set<infer V> ? Set<CamelToKebabRecursive<V>> : T extends object ? {
165
+ [K in keyof T as TransformKey<K & string, {
166
+ sourceCase: 'camel';
167
+ targetCase: 'kebab';
168
+ }>]: CamelToKebabRecursive<T[K]>;
169
+ } : T;
170
+ type PascalToCamelRecursive<T> = T extends Array<infer U> ? Array<PascalToCamelRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? PascalToCamel<K> : K, PascalToCamelRecursive<V>> : T extends Set<infer V> ? Set<PascalToCamelRecursive<V>> : T extends object ? {
171
+ [K in keyof T as TransformKey<K & string, {
172
+ sourceCase: 'pascal';
173
+ targetCase: 'camel';
174
+ }>]: PascalToCamelRecursive<T[K]>;
175
+ } : T;
176
+ type PascalToSnakeRecursive<T> = T extends Array<infer U> ? Array<PascalToSnakeRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? PascalToSnake<K> : K, PascalToSnakeRecursive<V>> : T extends Set<infer V> ? Set<PascalToSnakeRecursive<V>> : T extends object ? {
177
+ [K in keyof T as TransformKey<K & string, {
178
+ sourceCase: 'pascal';
179
+ targetCase: 'snake';
180
+ }>]: PascalToSnakeRecursive<T[K]>;
181
+ } : T;
182
+ type PascalToKebabRecursive<T> = T extends Array<infer U> ? Array<PascalToKebabRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? PascalToKebab<K> : K, PascalToKebabRecursive<V>> : T extends Set<infer V> ? Set<PascalToKebabRecursive<V>> : T extends object ? {
183
+ [K in keyof T as TransformKey<K & string, {
184
+ sourceCase: 'pascal';
185
+ targetCase: 'kebab';
186
+ }>]: PascalToKebabRecursive<T[K]>;
187
+ } : T;
188
+ type KebabToCamelRecursive<T> = T extends Array<infer U> ? Array<KebabToCamelRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? KebabToCamel<K> : K, KebabToCamelRecursive<V>> : T extends Set<infer V> ? Set<KebabToCamelRecursive<V>> : T extends object ? {
189
+ [K in keyof T as TransformKey<K & string, {
190
+ sourceCase: 'kebab';
191
+ targetCase: 'camel';
192
+ }>]: KebabToCamelRecursive<T[K]>;
193
+ } : T;
194
+ type KebabToPascalRecursive<T> = T extends Array<infer U> ? Array<KebabToPascalRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? KebabToPascal<K> : K, KebabToPascalRecursive<V>> : T extends Set<infer V> ? Set<KebabToPascalRecursive<V>> : T extends object ? {
195
+ [K in keyof T as TransformKey<K & string, {
196
+ sourceCase: 'kebab';
197
+ targetCase: 'pascal';
198
+ }>]: KebabToPascalRecursive<T[K]>;
199
+ } : T;
200
+ type KebabToSnakeRecursive<T> = T extends Array<infer U> ? Array<KebabToSnakeRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? KebabToSnake<K> : K, KebabToSnakeRecursive<V>> : T extends Set<infer V> ? Set<KebabToSnakeRecursive<V>> : T extends object ? {
201
+ [K in keyof T as TransformKey<K & string, {
202
+ sourceCase: 'kebab';
203
+ targetCase: 'snake';
204
+ }>]: KebabToSnakeRecursive<T[K]>;
205
+ } : T;
206
+ /**
207
+ * Generic recursive transformation type
208
+ * Allows dynamically selecting the transformation based on source and target cases
209
+ */
210
+ type TransformRecursive<T, FromCase extends StringCase, ToCase extends StringCase> = FromCase extends 'snake' ? ToCase extends 'camel' ? SnakeToCamelRecursive<T> : ToCase extends 'pascal' ? SnakeToPascalRecursive<T> : ToCase extends 'kebab' ? SnakeToKebabRecursive<T> : T : FromCase extends 'camel' ? ToCase extends 'snake' ? CamelToSnakeRecursive<T> : ToCase extends 'pascal' ? CamelToPascalRecursive<T> : ToCase extends 'kebab' ? CamelToKebabRecursive<T> : T : FromCase extends 'pascal' ? ToCase extends 'snake' ? PascalToSnakeRecursive<T> : ToCase extends 'camel' ? PascalToCamelRecursive<T> : ToCase extends 'kebab' ? PascalToKebabRecursive<T> : T : FromCase extends 'kebab' ? ToCase extends 'snake' ? KebabToSnakeRecursive<T> : ToCase extends 'camel' ? KebabToCamelRecursive<T> : ToCase extends 'pascal' ? KebabToPascalRecursive<T> : T : T;
211
+
212
+ declare function transform<T, From extends StringCase, To extends StringCase>(data: T, options: TransformOptions & {
213
+ depth?: number;
214
+ sourceCase: From;
215
+ targetCase: To;
216
+ }): TransformRecursive<T, From, To>;
217
+ /**
218
+ * Transform data to a specified output type.
219
+ *
220
+ * Note: When using this overload, type safety is not enforced between the input, options, and output type.
221
+ * The 'sourceCase' option is intentionally omitted, as it is not used for type inference here.
222
+ */
223
+ declare function transform<T, K>(data: T, options?: Omit<TransformOptions, 'sourceCase'> & {
224
+ depth?: number;
225
+ }): K;
226
+ declare function transform<T>(data: T, options?: TransformOptions & {
227
+ depth?: number;
228
+ }): unknown;
229
+
230
+ export { transform };
231
+ export type { StringCase, TransformOptions };
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Represents the supported string case formats for transformation
3
+ */
4
+ type StringCase = 'camel' | 'pascal' | 'snake' | 'kebab';
5
+
6
+ /**
7
+ * Options for the transform function
8
+ */
9
+ interface TransformOptions {
10
+ /**
11
+ * The target casing format to transform to
12
+ * @default 'camel'
13
+ */
14
+ targetCase?: StringCase;
15
+ /**
16
+ * The source casing format to transform from
17
+ *
18
+ * When specified:
19
+ * - Provides precise TypeScript type transformations
20
+ * - Bypasses runtime case detection (more efficient)
21
+ * - Ensures consistent results if input has mixed casing
22
+ *
23
+ * When omitted:
24
+ * - Automatic case detection is used at runtime
25
+ * - TypeScript types will be less precise (string keys)
26
+ * - Works with mixed case inputs (each key detected separately)
27
+ *
28
+ * @example
29
+ * // With source specified - precise types
30
+ * const result = transform(data, { targetCase: 'camel', sourceCase: 'snake' });
31
+ * // result has exact transformed types
32
+ *
33
+ * // Without source - flexible runtime behavior
34
+ * const result = transform(data, { targetCase: 'camel' });
35
+ * // TypeScript types are more general
36
+ *
37
+ * @default undefined (automatic detection)
38
+ */
39
+ sourceCase?: StringCase;
40
+ }
41
+
42
+ /**
43
+ * Type utility that transforms a snake_case string to camelCase
44
+ * Example: 'hello_world' -> 'helloWorld'
45
+ */
46
+ type SnakeToCamel<S extends string> = S extends `${infer P}_${infer C}${infer R}` ? `${P}${Uppercase<C>}${SnakeToCamel<R>}` : S;
47
+ /**
48
+ * Type utility that transforms a snake_case string to PascalCase
49
+ * Example: 'hello_world' -> 'HelloWorld'
50
+ */
51
+ type SnakeWordsToPascal<Parts extends string[]> = Parts extends [
52
+ infer First extends string,
53
+ ...infer Rest extends string[]
54
+ ] ? `${Capitalize<First>}${SnakeWordsToPascal<Rest>}` : '';
55
+ type SnakeToWords<S extends string> = S extends `${infer P}_${infer R}` ? [P, ...SnakeToWords<R>] : [S];
56
+ type SnakeToPascal<S extends string> = S extends `${infer P}_${infer R}` ? SnakeWordsToPascal<[P, ...SnakeToWords<R>]> : Capitalize<S>;
57
+ /**
58
+ * Type utility that transforms a snake_case string to kebab-case
59
+ * Example: 'hello_world' -> 'hello-world'
60
+ */
61
+ type SnakeToKebab<S extends string> = S extends `${infer P}_${infer R}` ? `${P}-${SnakeToKebab<R>}` : S;
62
+ /**
63
+ * Type utility that transforms a camelCase string to snake_case
64
+ * Example: 'helloWorld' -> 'hello_world'
65
+ */
66
+ type CamelToSnake<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `_${Lowercase<C>}${CamelToSnake<R>}` : `${C}${CamelToSnake<R>}` : S;
67
+ /**
68
+ * Type utility that transforms a camelCase string to PascalCase
69
+ * Example: 'helloWorld' -> 'HelloWorld'
70
+ */
71
+ type CamelToPascal<S extends string> = Capitalize<S>;
72
+ /**
73
+ * Type utility that transforms a camelCase string to kebab-case
74
+ * Example: 'helloWorld' -> 'hello-world'
75
+ */
76
+ type CamelToKebab<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `-${Lowercase<C>}${CamelToKebab<R>}` : `${C}${CamelToKebab<R>}` : S;
77
+ /**
78
+ * Type utility that transforms a PascalCase string to camelCase
79
+ * Example: 'HelloWorld' -> 'helloWorld'
80
+ */
81
+ type PascalToCamel<S extends string> = S extends `${infer F}${infer R}` ? `${Lowercase<F>}${R}` : S;
82
+ /**
83
+ * Type utility that transforms a PascalCase string to snake_case
84
+ * Example: 'HelloWorld' -> 'hello_world'
85
+ */
86
+ type PascalToSnake<S extends string> = S extends `${infer F}${infer R}` ? R extends `` ? Lowercase<F> : `${Lowercase<F>}${PascalToSnakeInner<R>}` : S;
87
+ type PascalToSnakeInner<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `_${Lowercase<C>}${PascalToSnakeInner<R>}` : `${C}${PascalToSnakeInner<R>}` : S;
88
+ /**
89
+ * Type utility that transforms a PascalCase string to kebab-case
90
+ * Example: 'HelloWorld' -> 'hello-world'
91
+ */
92
+ type PascalToKebab<S extends string> = S extends `${infer F}${infer R}` ? R extends `` ? Lowercase<F> : `${Lowercase<F>}${PascalToKebabInner<R>}` : S;
93
+ type PascalToKebabInner<S extends string> = S extends `${infer C}${infer R}` ? C extends Uppercase<C> ? `-${Lowercase<C>}${PascalToKebabInner<R>}` : `${C}${PascalToKebabInner<R>}` : S;
94
+ /**
95
+ * Type utility that transforms a kebab-case string to camelCase
96
+ * Example: 'hello-world' -> 'helloWorld'
97
+ */
98
+ type KebabToCamel<S extends string> = S extends `${infer P}-${infer C}${infer R}` ? `${P}${Uppercase<C>}${KebabToCamel<R>}` : S;
99
+ /**
100
+ * Type utility that transforms a kebab-case string to PascalCase
101
+ * Example: 'hello-world' -> 'HelloWorld'
102
+ */
103
+ type KebabWordsToPascal<Parts extends string[]> = Parts extends [
104
+ infer First extends string,
105
+ ...infer Rest extends string[]
106
+ ] ? `${Capitalize<First>}${KebabWordsToPascal<Rest>}` : '';
107
+ type KebabToWords<S extends string> = S extends `${infer P}-${infer R}` ? [P, ...KebabToWords<R>] : [S];
108
+ /**
109
+ * Type utility that transforms a kebab-case string to PascalCase
110
+ * Example: 'hello-world' -> 'HelloWorld'
111
+ */
112
+ type KebabToPascal<S extends string> = S extends `${infer P}-${infer R}` ? KebabWordsToPascal<[P, ...KebabToWords<R>]> : Capitalize<S>;
113
+ /**
114
+ * Type utility that transforms a kebab-case string to snake_case
115
+ * Example: 'hello-world' -> 'hello_world'
116
+ */
117
+ type KebabToSnake<S extends string> = S extends `${infer P}-${infer R}` ? `${P}_${KebabToSnake<R>}` : S;
118
+ /**
119
+ * Utility type to detect preserved keys that shouldn't be transformed.
120
+ * Preserved keys include those with leading/trailing special characters,
121
+ * unsupported patterns, or invalid starting/ending characters.
122
+ */
123
+ type ForbiddenStartChars = '_' | '-' | '$' | '&' | '%' | '#' | '@' | '!' | '*' | '+' | '=' | '~' | '`' | '^' | '(' | ')' | '[' | ']' | '{' | '}' | '|' | '\\' | ':' | ';' | '"' | "'" | '<' | '>' | ',' | '.' | '?' | '/';
124
+ type ForbiddenEndChars = '_' | '-' | '$' | '&' | '%' | '#' | '@' | '!' | '*' | '+' | '=' | '~' | '`' | '^' | '(' | ')' | '[' | ']' | '{' | '}' | '|' | '\\' | ':' | ';' | '"' | "'" | '<' | '>' | ',' | '.' | '?' | '/' | `${number}`;
125
+ type PreservedKey<K extends string> = K extends `${infer First}${string}` ? First extends ForbiddenStartChars ? true : K extends `${string}${infer Last}` ? Last extends ForbiddenEndChars ? true : K extends `${string}__${string}` | `${string}--${string}` ? true : false : false : false;
126
+ /**
127
+ * Type utility that selects the correct string transformation based on source and target casing
128
+ */
129
+ type TransformKey<K extends string, O extends TransformOptions> = PreservedKey<K> extends true ? K : undefined extends O['sourceCase'] ? string : O['sourceCase'] extends 'snake' ? undefined extends O['targetCase'] ? SnakeToCamel<K> : O['targetCase'] extends 'camel' ? SnakeToCamel<K> : O['targetCase'] extends 'pascal' ? SnakeToPascal<K> : O['targetCase'] extends 'kebab' ? SnakeToKebab<K> : K : O['sourceCase'] extends 'camel' ? undefined extends O['targetCase'] ? K : O['targetCase'] extends 'snake' ? CamelToSnake<K> : O['targetCase'] extends 'pascal' ? CamelToPascal<K> : O['targetCase'] extends 'kebab' ? CamelToKebab<K> : K : O['sourceCase'] extends 'pascal' ? undefined extends O['targetCase'] ? PascalToCamel<K> : O['targetCase'] extends 'camel' ? PascalToCamel<K> : O['targetCase'] extends 'snake' ? PascalToSnake<K> : O['targetCase'] extends 'kebab' ? PascalToKebab<K> : K : O['sourceCase'] extends 'kebab' ? undefined extends O['targetCase'] ? KebabToCamel<K> : O['targetCase'] extends 'camel' ? KebabToCamel<K> : O['targetCase'] extends 'pascal' ? KebabToPascal<K> : O['targetCase'] extends 'snake' ? KebabToSnake<K> : K : K;
130
+ /**
131
+ * Recursive type transformations
132
+ * These types handle nested structures like arrays, objects, Maps, and Sets
133
+ */
134
+ type SnakeToCamelRecursive<T> = T extends Array<infer U> ? Array<SnakeToCamelRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? SnakeToCamel<K> : K, SnakeToCamelRecursive<V>> : T extends Set<infer V> ? Set<SnakeToCamelRecursive<V>> : T extends object ? {
135
+ [K in keyof T as TransformKey<K & string, {
136
+ sourceCase: 'snake';
137
+ targetCase: 'camel';
138
+ }>]: SnakeToCamelRecursive<T[K]>;
139
+ } : T;
140
+ type SnakeToPascalRecursive<T> = T extends Array<infer U> ? Array<SnakeToPascalRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? SnakeToPascal<K> : K, SnakeToPascalRecursive<V>> : T extends Set<infer V> ? Set<SnakeToPascalRecursive<V>> : T extends object ? {
141
+ [K in keyof T as TransformKey<K & string, {
142
+ sourceCase: 'snake';
143
+ targetCase: 'pascal';
144
+ }>]: SnakeToPascalRecursive<T[K]>;
145
+ } : T;
146
+ type SnakeToKebabRecursive<T> = T extends Array<infer U> ? Array<SnakeToKebabRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? SnakeToKebab<K> : K, SnakeToKebabRecursive<V>> : T extends Set<infer V> ? Set<SnakeToKebabRecursive<V>> : T extends object ? {
147
+ [K in keyof T as TransformKey<K & string, {
148
+ sourceCase: 'snake';
149
+ targetCase: 'kebab';
150
+ }>]: SnakeToKebabRecursive<T[K]>;
151
+ } : T;
152
+ type CamelToSnakeRecursive<T> = T extends Array<infer U> ? Array<CamelToSnakeRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? CamelToSnake<K> : K, CamelToSnakeRecursive<V>> : T extends Set<infer V> ? Set<CamelToSnakeRecursive<V>> : T extends object ? {
153
+ [K in keyof T as TransformKey<K & string, {
154
+ sourceCase: 'camel';
155
+ targetCase: 'snake';
156
+ }>]: CamelToSnakeRecursive<T[K]>;
157
+ } : T;
158
+ type CamelToPascalRecursive<T> = T extends Array<infer U> ? Array<CamelToPascalRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? CamelToPascal<K> : K, CamelToPascalRecursive<V>> : T extends Set<infer V> ? Set<CamelToPascalRecursive<V>> : T extends object ? {
159
+ [K in keyof T as TransformKey<K & string, {
160
+ sourceCase: 'camel';
161
+ targetCase: 'pascal';
162
+ }>]: CamelToPascalRecursive<T[K]>;
163
+ } : T;
164
+ type CamelToKebabRecursive<T> = T extends Array<infer U> ? Array<CamelToKebabRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? CamelToKebab<K> : K, CamelToKebabRecursive<V>> : T extends Set<infer V> ? Set<CamelToKebabRecursive<V>> : T extends object ? {
165
+ [K in keyof T as TransformKey<K & string, {
166
+ sourceCase: 'camel';
167
+ targetCase: 'kebab';
168
+ }>]: CamelToKebabRecursive<T[K]>;
169
+ } : T;
170
+ type PascalToCamelRecursive<T> = T extends Array<infer U> ? Array<PascalToCamelRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? PascalToCamel<K> : K, PascalToCamelRecursive<V>> : T extends Set<infer V> ? Set<PascalToCamelRecursive<V>> : T extends object ? {
171
+ [K in keyof T as TransformKey<K & string, {
172
+ sourceCase: 'pascal';
173
+ targetCase: 'camel';
174
+ }>]: PascalToCamelRecursive<T[K]>;
175
+ } : T;
176
+ type PascalToSnakeRecursive<T> = T extends Array<infer U> ? Array<PascalToSnakeRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? PascalToSnake<K> : K, PascalToSnakeRecursive<V>> : T extends Set<infer V> ? Set<PascalToSnakeRecursive<V>> : T extends object ? {
177
+ [K in keyof T as TransformKey<K & string, {
178
+ sourceCase: 'pascal';
179
+ targetCase: 'snake';
180
+ }>]: PascalToSnakeRecursive<T[K]>;
181
+ } : T;
182
+ type PascalToKebabRecursive<T> = T extends Array<infer U> ? Array<PascalToKebabRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? PascalToKebab<K> : K, PascalToKebabRecursive<V>> : T extends Set<infer V> ? Set<PascalToKebabRecursive<V>> : T extends object ? {
183
+ [K in keyof T as TransformKey<K & string, {
184
+ sourceCase: 'pascal';
185
+ targetCase: 'kebab';
186
+ }>]: PascalToKebabRecursive<T[K]>;
187
+ } : T;
188
+ type KebabToCamelRecursive<T> = T extends Array<infer U> ? Array<KebabToCamelRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? KebabToCamel<K> : K, KebabToCamelRecursive<V>> : T extends Set<infer V> ? Set<KebabToCamelRecursive<V>> : T extends object ? {
189
+ [K in keyof T as TransformKey<K & string, {
190
+ sourceCase: 'kebab';
191
+ targetCase: 'camel';
192
+ }>]: KebabToCamelRecursive<T[K]>;
193
+ } : T;
194
+ type KebabToPascalRecursive<T> = T extends Array<infer U> ? Array<KebabToPascalRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? KebabToPascal<K> : K, KebabToPascalRecursive<V>> : T extends Set<infer V> ? Set<KebabToPascalRecursive<V>> : T extends object ? {
195
+ [K in keyof T as TransformKey<K & string, {
196
+ sourceCase: 'kebab';
197
+ targetCase: 'pascal';
198
+ }>]: KebabToPascalRecursive<T[K]>;
199
+ } : T;
200
+ type KebabToSnakeRecursive<T> = T extends Array<infer U> ? Array<KebabToSnakeRecursive<U>> : T extends Map<infer K, infer V> ? Map<K extends string ? KebabToSnake<K> : K, KebabToSnakeRecursive<V>> : T extends Set<infer V> ? Set<KebabToSnakeRecursive<V>> : T extends object ? {
201
+ [K in keyof T as TransformKey<K & string, {
202
+ sourceCase: 'kebab';
203
+ targetCase: 'snake';
204
+ }>]: KebabToSnakeRecursive<T[K]>;
205
+ } : T;
206
+ /**
207
+ * Generic recursive transformation type
208
+ * Allows dynamically selecting the transformation based on source and target cases
209
+ */
210
+ type TransformRecursive<T, FromCase extends StringCase, ToCase extends StringCase> = FromCase extends 'snake' ? ToCase extends 'camel' ? SnakeToCamelRecursive<T> : ToCase extends 'pascal' ? SnakeToPascalRecursive<T> : ToCase extends 'kebab' ? SnakeToKebabRecursive<T> : T : FromCase extends 'camel' ? ToCase extends 'snake' ? CamelToSnakeRecursive<T> : ToCase extends 'pascal' ? CamelToPascalRecursive<T> : ToCase extends 'kebab' ? CamelToKebabRecursive<T> : T : FromCase extends 'pascal' ? ToCase extends 'snake' ? PascalToSnakeRecursive<T> : ToCase extends 'camel' ? PascalToCamelRecursive<T> : ToCase extends 'kebab' ? PascalToKebabRecursive<T> : T : FromCase extends 'kebab' ? ToCase extends 'snake' ? KebabToSnakeRecursive<T> : ToCase extends 'camel' ? KebabToCamelRecursive<T> : ToCase extends 'pascal' ? KebabToPascalRecursive<T> : T : T;
211
+
212
+ declare function transform<T, From extends StringCase, To extends StringCase>(data: T, options: TransformOptions & {
213
+ depth?: number;
214
+ sourceCase: From;
215
+ targetCase: To;
216
+ }): TransformRecursive<T, From, To>;
217
+ /**
218
+ * Transform data to a specified output type.
219
+ *
220
+ * Note: When using this overload, type safety is not enforced between the input, options, and output type.
221
+ * The 'sourceCase' option is intentionally omitted, as it is not used for type inference here.
222
+ */
223
+ declare function transform<T, K>(data: T, options?: Omit<TransformOptions, 'sourceCase'> & {
224
+ depth?: number;
225
+ }): K;
226
+ declare function transform<T>(data: T, options?: TransformOptions & {
227
+ depth?: number;
228
+ }): unknown;
229
+
230
+ export { transform };
231
+ export type { StringCase, TransformOptions };