Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions FOOTER.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ pnpm test:watch

## Credits

Built for developers, with developers.
👉 https://launchql.com | https://hyperweb.io
**🛠 Built by the [Constructive](https://constructive.io) team — creators of modular Postgres tooling for secure, composable backends. If you like our work, contribute on [GitHub](https://github.com/constructive-io).**

## Disclaimer

Expand Down
89 changes: 89 additions & 0 deletions packages/inflekt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
underscore,
toFieldName,
toQueryName,
inflektTree,
} from 'inflekt';

// Basic singularization/pluralization
Expand Down Expand Up @@ -65,6 +66,14 @@ underscore('UserProfile'); // 'user_profile'
// GraphQL naming helpers
toFieldName('Users'); // 'user'
toQueryName('User'); // 'users'

// Deep object key transformation
const apiResponse = {
user_name: 'John',
order_items: [{ item_id: 1, product_name: 'Widget' }]
};
inflektTree(apiResponse, (key) => camelize(key, true));
// Result: { userName: 'John', orderItems: [{ itemId: 1, productName: 'Widget' }] }
```

## API
Expand All @@ -91,6 +100,86 @@ toQueryName('User'); // 'users'
- `toFieldName(pluralTypeName)` - Convert plural PascalCase to singular camelCase field name
- `toQueryName(singularTypeName)` - Convert singular PascalCase to plural camelCase query name

### Deep Object Transformation

- `inflektTree(obj, transformer, options?)` - Recursively transform all property names in an object tree

## Deep Object Key Transformation

The `inflektTree` function recursively transforms all property names in an object tree using any transformer function. This is useful for converting API responses between naming conventions.

### Basic Usage

```typescript
// Convert snake_case API response to camelCase for frontend
const apiResponse = {
user_name: 'John',
user_profile: {
profile_image: 'https://example.com/avatar.jpg',
account_status: 'active'
},
order_items: [
{ item_id: 1, item_name: 'Product A' },
{ item_id: 2, item_name: 'Product B' }
]
};

const result = inflektTree(apiResponse, (key) => camelize(key, true));
// Result:
// {
// userName: 'John',
// userProfile: {
// profileImage: 'https://example.com/avatar.jpg',
// accountStatus: 'active'
// },
// orderItems: [
// { itemId: 1, itemName: 'Product A' },
// { itemId: 2, itemName: 'Product B' }
// ]
// }

// Convert camelCase frontend data to snake_case for API
const frontendData = { userName: 'John', orderItems: [{ itemId: 1 }] };
const payload = inflektTree(frontendData, underscore);
// Result: { user_name: 'John', order_items: [{ item_id: 1 }] }
```

### Skipping Keys

Use the `skip` option to preserve certain keys:

```typescript
// Skip keys starting with underscore
const input = {
user_name: 'John',
_private_field: 'secret',
_metadata: { _internal: true }
};

const result = inflektTree(input, (key) => camelize(key, true), {
skip: (key) => key.startsWith('_')
});
// Result: { userName: 'John', _private_field: 'secret', _metadata: { _internal: true } }

// Skip specific keys
const result2 = inflektTree(input, (key) => camelize(key, true), {
skip: (key) => key === 'created_at' || key === 'updated_at'
});

// Skip based on path depth (only transform top 2 levels)
const result3 = inflektTree(deepObject, (key) => camelize(key, true), {
skip: (key, path) => path.length > 1
});
```

### Features

- Handles nested objects and arrays of any depth
- Preserves `Date` objects (clones them)
- Preserves `null` and `undefined` values
- Returns primitives unchanged
- Works with any transformer function

## Latin Suffix Overrides

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