Skip to content

Commit 2b190bc

Browse files
committed
Added inflekt object conversion kebab case to camel case for cli usage
1 parent 6e7b772 commit 2b190bc

4 files changed

Lines changed: 152 additions & 0 deletions

File tree

packages/inflekt/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
underscore,
3939
toFieldName,
4040
toQueryName,
41+
inflektObject,
4142
} from 'inflekt';
4243

4344
// Basic singularization/pluralization
@@ -65,6 +66,10 @@ underscore('UserProfile'); // 'user_profile'
6566
// GraphQL naming helpers
6667
toFieldName('Users'); // 'user'
6768
toQueryName('User'); // 'users'
69+
70+
// Object key transformation (kebab-case to camelCase)
71+
inflektObject({ 'schema-file': 'test.graphql', 'dry-run': true });
72+
// { schemaFile: 'test.graphql', dryRun: true }
6873
```
6974

7075
## API
@@ -91,6 +96,10 @@ toQueryName('User'); // 'users'
9196
- `toFieldName(pluralTypeName)` - Convert plural PascalCase to singular camelCase field name
9297
- `toQueryName(singularTypeName)` - Convert singular PascalCase to plural camelCase query name
9398

99+
### Object Transformations
100+
101+
- `inflektObject(obj)` - Convert kebab-case object keys to camelCase (useful for CLI argument conversion)
102+
94103
## Latin Suffix Overrides
95104

96105
This library handles Latin plural suffixes differently than the standard `inflection` package to match PostGraphile's behavior:

packages/inflekt/__tests__/inflection.test.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
fixCapitalisedPlural,
1313
toFieldName,
1414
toQueryName,
15+
inflektObject,
1516
} from '../src';
1617

1718
describe('singularize', () => {
@@ -198,3 +199,121 @@ describe('toQueryName', () => {
198199
expect(toQueryName('Category')).toBe('categories');
199200
});
200201
});
202+
203+
describe('inflektObject', () => {
204+
it('should convert kebab-case keys to camelCase', () => {
205+
const input = {
206+
'schema-file': 'test.graphql',
207+
'dry-run': true,
208+
'api-names': ['api1', 'api2'],
209+
};
210+
const expected = {
211+
schemaFile: 'test.graphql',
212+
dryRun: true,
213+
apiNames: ['api1', 'api2'],
214+
};
215+
expect(inflektObject(input)).toEqual(expected);
216+
});
217+
218+
it('should preserve camelCase keys', () => {
219+
const input = {
220+
endpoint: 'http://localhost:3000',
221+
output: './generated',
222+
verbose: false,
223+
};
224+
expect(inflektObject(input)).toEqual(input);
225+
});
226+
227+
it('should handle mixed kebab-case and camelCase keys', () => {
228+
const input = {
229+
'schema-file': 'schema.graphql',
230+
endpoint: 'http://localhost:3000',
231+
'react-query': true,
232+
output: './dist',
233+
'browser-compatible': false,
234+
};
235+
const expected = {
236+
schemaFile: 'schema.graphql',
237+
endpoint: 'http://localhost:3000',
238+
reactQuery: true,
239+
output: './dist',
240+
browserCompatible: false,
241+
};
242+
expect(inflektObject(input)).toEqual(expected);
243+
});
244+
245+
it('should handle empty objects', () => {
246+
expect(inflektObject({})).toEqual({});
247+
});
248+
249+
it('should handle objects with various value types', () => {
250+
const input = {
251+
'string-value': 'test',
252+
'number-value': 42,
253+
'boolean-value': true,
254+
'null-value': null as null,
255+
'undefined-value': undefined as undefined,
256+
'array-value': [1, 2, 3],
257+
'object-value': { nested: 'value' },
258+
};
259+
const expected = {
260+
stringValue: 'test',
261+
numberValue: 42,
262+
booleanValue: true,
263+
nullValue: null as null,
264+
undefinedValue: undefined as undefined,
265+
arrayValue: [1, 2, 3],
266+
objectValue: { nested: 'value' },
267+
};
268+
expect(inflektObject(input)).toEqual(expected);
269+
});
270+
271+
it('should handle multiple consecutive hyphens', () => {
272+
const input = {
273+
'multi-word-key-name': 'value',
274+
};
275+
const expected = {
276+
multiWordKeyName: 'value',
277+
};
278+
expect(inflektObject(input)).toEqual(expected);
279+
});
280+
281+
it('should preserve single-word keys', () => {
282+
const input = {
283+
endpoint: 'url',
284+
schemas: ['public'],
285+
orm: true,
286+
};
287+
expect(inflektObject(input)).toEqual(input);
288+
});
289+
290+
it('should handle CLI argument conversion use case', () => {
291+
const argv = {
292+
endpoint: 'http://localhost:5000/graphql',
293+
'schema-file': undefined as string | undefined,
294+
output: 'codegen',
295+
schemas: undefined as string[] | undefined,
296+
'api-names': undefined as string[] | undefined,
297+
'react-query': true,
298+
orm: false,
299+
'browser-compatible': true,
300+
authorization: 'Bearer token123',
301+
'dry-run': false,
302+
verbose: true,
303+
};
304+
const expected = {
305+
endpoint: 'http://localhost:5000/graphql',
306+
schemaFile: undefined as string | undefined,
307+
output: 'codegen',
308+
schemas: undefined as string[] | undefined,
309+
apiNames: undefined as string[] | undefined,
310+
reactQuery: true,
311+
orm: false,
312+
browserCompatible: true,
313+
authorization: 'Bearer token123',
314+
dryRun: false,
315+
verbose: true,
316+
};
317+
expect(inflektObject(argv)).toEqual(expected);
318+
});
319+
});

packages/inflekt/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
export * from './pluralize';
99
export * from './case';
1010
export * from './naming';
11+
export * from './object';

packages/inflekt/src/object.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Object key transformation utilities
3+
*/
4+
5+
/**
6+
* Convert kebab-case keys to camelCase in an object
7+
* @param obj - Object with kebab-case keys
8+
* @returns New object with camelCase keys
9+
* @example inflektObject({ 'schema-file': 'test.graphql', 'dry-run': true }) -> { schemaFile: 'test.graphql', dryRun: true }
10+
*/
11+
export function inflektObject<T extends Record<string, any>>(obj: T): Record<string, any> {
12+
const result: Record<string, any> = {};
13+
14+
for (const key in obj) {
15+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
16+
// Convert kebab-case to camelCase
17+
const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
18+
result[camelKey] = obj[key];
19+
}
20+
}
21+
22+
return result;
23+
}

0 commit comments

Comments
 (0)