From 2b190bcb5ebc6137606d81f22a63d72fbdbe20b2 Mon Sep 17 00:00:00 2001 From: ghou9khub Date: Wed, 28 Jan 2026 22:57:07 -0800 Subject: [PATCH] Added inflekt object conversion kebab case to camel case for cli usage --- packages/inflekt/README.md | 9 ++ packages/inflekt/__tests__/inflection.test.ts | 119 ++++++++++++++++++ packages/inflekt/src/index.ts | 1 + packages/inflekt/src/object.ts | 23 ++++ 4 files changed, 152 insertions(+) create mode 100644 packages/inflekt/src/object.ts diff --git a/packages/inflekt/README.md b/packages/inflekt/README.md index 3ef59d1..f9c5837 100644 --- a/packages/inflekt/README.md +++ b/packages/inflekt/README.md @@ -38,6 +38,7 @@ import { underscore, toFieldName, toQueryName, + inflektObject, } from 'inflekt'; // Basic singularization/pluralization @@ -65,6 +66,10 @@ underscore('UserProfile'); // 'user_profile' // GraphQL naming helpers toFieldName('Users'); // 'user' toQueryName('User'); // 'users' + +// Object key transformation (kebab-case to camelCase) +inflektObject({ 'schema-file': 'test.graphql', 'dry-run': true }); +// { schemaFile: 'test.graphql', dryRun: true } ``` ## API @@ -91,6 +96,10 @@ toQueryName('User'); // 'users' - `toFieldName(pluralTypeName)` - Convert plural PascalCase to singular camelCase field name - `toQueryName(singularTypeName)` - Convert singular PascalCase to plural camelCase query name +### Object Transformations + +- `inflektObject(obj)` - Convert kebab-case object keys to camelCase (useful for CLI argument conversion) + ## Latin Suffix Overrides This library handles Latin plural suffixes differently than the standard `inflection` package to match PostGraphile's behavior: diff --git a/packages/inflekt/__tests__/inflection.test.ts b/packages/inflekt/__tests__/inflection.test.ts index 6d86a36..c4ee6e4 100644 --- a/packages/inflekt/__tests__/inflection.test.ts +++ b/packages/inflekt/__tests__/inflection.test.ts @@ -12,6 +12,7 @@ import { fixCapitalisedPlural, toFieldName, toQueryName, + inflektObject, } from '../src'; describe('singularize', () => { @@ -198,3 +199,121 @@ describe('toQueryName', () => { expect(toQueryName('Category')).toBe('categories'); }); }); + +describe('inflektObject', () => { + it('should convert kebab-case keys to camelCase', () => { + const input = { + 'schema-file': 'test.graphql', + 'dry-run': true, + 'api-names': ['api1', 'api2'], + }; + const expected = { + schemaFile: 'test.graphql', + dryRun: true, + apiNames: ['api1', 'api2'], + }; + expect(inflektObject(input)).toEqual(expected); + }); + + it('should preserve camelCase keys', () => { + const input = { + endpoint: 'http://localhost:3000', + output: './generated', + verbose: false, + }; + expect(inflektObject(input)).toEqual(input); + }); + + it('should handle mixed kebab-case and camelCase keys', () => { + const input = { + 'schema-file': 'schema.graphql', + endpoint: 'http://localhost:3000', + 'react-query': true, + output: './dist', + 'browser-compatible': false, + }; + const expected = { + schemaFile: 'schema.graphql', + endpoint: 'http://localhost:3000', + reactQuery: true, + output: './dist', + browserCompatible: false, + }; + expect(inflektObject(input)).toEqual(expected); + }); + + it('should handle empty objects', () => { + expect(inflektObject({})).toEqual({}); + }); + + it('should handle objects with various value types', () => { + const input = { + 'string-value': 'test', + 'number-value': 42, + 'boolean-value': true, + 'null-value': null as null, + 'undefined-value': undefined as undefined, + 'array-value': [1, 2, 3], + 'object-value': { nested: 'value' }, + }; + const expected = { + stringValue: 'test', + numberValue: 42, + booleanValue: true, + nullValue: null as null, + undefinedValue: undefined as undefined, + arrayValue: [1, 2, 3], + objectValue: { nested: 'value' }, + }; + expect(inflektObject(input)).toEqual(expected); + }); + + it('should handle multiple consecutive hyphens', () => { + const input = { + 'multi-word-key-name': 'value', + }; + const expected = { + multiWordKeyName: 'value', + }; + expect(inflektObject(input)).toEqual(expected); + }); + + it('should preserve single-word keys', () => { + const input = { + endpoint: 'url', + schemas: ['public'], + orm: true, + }; + expect(inflektObject(input)).toEqual(input); + }); + + it('should handle CLI argument conversion use case', () => { + const argv = { + endpoint: 'http://localhost:5000/graphql', + 'schema-file': undefined as string | undefined, + output: 'codegen', + schemas: undefined as string[] | undefined, + 'api-names': undefined as string[] | undefined, + 'react-query': true, + orm: false, + 'browser-compatible': true, + authorization: 'Bearer token123', + 'dry-run': false, + verbose: true, + }; + const expected = { + endpoint: 'http://localhost:5000/graphql', + schemaFile: undefined as string | undefined, + output: 'codegen', + schemas: undefined as string[] | undefined, + apiNames: undefined as string[] | undefined, + reactQuery: true, + orm: false, + browserCompatible: true, + authorization: 'Bearer token123', + dryRun: false, + verbose: true, + }; + expect(inflektObject(argv)).toEqual(expected); + }); +}); diff --git a/packages/inflekt/src/index.ts b/packages/inflekt/src/index.ts index 4471786..9966f1d 100644 --- a/packages/inflekt/src/index.ts +++ b/packages/inflekt/src/index.ts @@ -8,3 +8,4 @@ export * from './pluralize'; export * from './case'; export * from './naming'; +export * from './object'; diff --git a/packages/inflekt/src/object.ts b/packages/inflekt/src/object.ts new file mode 100644 index 0000000..4f755d9 --- /dev/null +++ b/packages/inflekt/src/object.ts @@ -0,0 +1,23 @@ +/** + * Object key transformation utilities + */ + +/** + * Convert kebab-case keys to camelCase in an object + * @param obj - Object with kebab-case keys + * @returns New object with camelCase keys + * @example inflektObject({ 'schema-file': 'test.graphql', 'dry-run': true }) -> { schemaFile: 'test.graphql', dryRun: true } + */ +export function inflektObject>(obj: T): Record { + const result: Record = {}; + + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + // Convert kebab-case to camelCase + const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()); + result[camelKey] = obj[key]; + } + } + + return result; +}