@adaskothebeast/http-params-processor-key-custom-delimiter
v12.0.0
Published
Custom delimiter key formatting strategy for HttpParamsProcessor, for bespoke backend query parameter notations.
Maintainers
Readme
✂️ @adaskothebeast/http-params-processor-key-custom-delimiter
Bring your own delimiter to HttpParamsProcessor: user:name, user->name, api/users, with brackets or the same delimiter for arrays.
No runtime dependency beyond core (its only peer dependency, ^12.0.0). ESM + CJS. sideEffects: false.
📦 Install
npm i @adaskothebeast/http-params-processor-key-custom-delimiter @adaskothebeast/http-params-processor-core🎯 What it does
This is a key formatting strategy: it decides how nested keys are spelled while ParamsProcessor walks your object graph. Object properties are joined with a delimiter you choose (default ':'), while array elements keep bracket indices unless you ask for the delimiter there too. It exists for bespoke or legacy APIs whose notation does not match dots, brackets, Rails or flat underscores.
| Input | DefaultKeyFormattingStrategy (core) | This strategy (defaults) |
| ---------------------------- | ------------------------------------- | -------------------------- |
| { user: { name: 'John' } } | p.user.name | p:user:name |
| { items: ['a', 'b'] } | p.items[0], p.items[1] | p:items[0], p:items[1] |
| { arr: [{ id: '1' }] } | p.arr[0].id | p:arr[0]:id |
🧰 API
CustomDelimiterKeyFormattingStrategy
Implements IKeyFormattingStrategy from core.
| Member | Returns | Result |
| -------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------- |
| new CustomDelimiterKeyFormattingStrategy(objectDelimiter?, arrayFormat?) | - | Defaults: ':' and 'bracket' |
| formatObjectKey(parentKey, propertyKey) | string | `${parentKey}${objectDelimiter}${propertyKey}` |
| formatArrayKey(parentKey, index) | string | `${parentKey}[${index}]` or `${parentKey}${objectDelimiter}${index}` |
Constructor parameters:
| Parameter | Type | Default | Meaning |
| ----------------- | -------------------------- | ----------- | ----------------------------------------------------------- |
| objectDelimiter | string | ':' | Inserted between a parent key and a property name |
| arrayFormat | 'bracket' \| 'delimiter' | 'bracket' | 'bracket' keeps items[0], 'delimiter' emits items:0 |
transformComplexObject is not implemented, so nested objects and arrays are always traversed down to primitives.
⚡ Usage
import { ParamsProcessor } from '@adaskothebeast/http-params-processor-core';
import { CustomDelimiterKeyFormattingStrategy } from '@adaskothebeast/http-params-processor-key-custom-delimiter';
const processor = new ParamsProcessor({
keyFormatter: new CustomDelimiterKeyFormattingStrategy(),
});
processor.process('p', {
user: { name: 'John', profile: { email: '[email protected]' } },
items: ['a', 'b'],
});
// [
// ['p:user:name', 'John'],
// ['p:user:profile:email', '[email protected]'],
// ['p:items[0]', 'a'],
// ['p:items[1]', 'b'],
// ]The same keyFormatter option is accepted by every adapter (-angular, -angular-resource, -fetch, -axios, -react-tanstack-query, -react-swr), because they all forward their options object to ParamsProcessor.
🎛️ Options and configuration
new CustomDelimiterKeyFormattingStrategy(); // ':' + brackets
new CustomDelimiterKeyFormattingStrategy('->'); // user->name, items[0]
new CustomDelimiterKeyFormattingStrategy('/'); // api/users, api/users[0]
new CustomDelimiterKeyFormattingStrategy(':', 'delimiter'); // user:name, items:2| Constructor arguments | user + name | items + 2 |
| --------------------- | --------------- | -------------- |
| (none) | user:name | items[2] |
| '->' | user->name | items[2] |
| '/' | api/users | api/users[2] |
| ':', 'delimiter' | user:name | items:2 |
| '.', 'delimiter' | user.name | items.2 |
'delimiter' mode reuses objectDelimiter for indices, so array elements and object properties become indistinguishable in the key - pick it only when your backend does not need to tell them apart (or when it splits on the delimiter and infers arrays from numeric segments).
The strategy is stateless, so a single instance can be shared, and keyFormatter can also be passed per call to override the processor default.
📤 Output examples
const processor = new ParamsProcessor({
keyFormatter: new CustomDelimiterKeyFormattingStrategy(':', 'delimiter'),
});
processor.process('p', { arr: [{ id: '1', innerArr: [{ id: '1.1' }] }] });p:arr:0:id = 1
p:arr:0:innerArr:0:id = 1.1const arrow = new ParamsProcessor({
keyFormatter: new CustomDelimiterKeyFormattingStrategy('->'),
});
arrow.process('p', { user: { name: 'John' }, items: ['a'] });
// [['p->user->name', 'John'], ['p->items[0]', 'a']]
arrow.toQueryString('p', { user: { name: 'John' } });
// p-%3Euser-%3Ename=John⚠️ Edge cases
- Delimiters are percent encoded by
toQueryStringandtoURLSearchParams:':'becomes%3A,'/'becomes%2F,'->'becomes-%3E.processreturns raw keys, so if the backend must literally see:or/, build the URL yourself fromprocessoutput (both characters are legal unencoded in a query component). - The delimiter is inserted verbatim, with no escaping. If a property name contains the delimiter, the key becomes ambiguous - the same collision risk as
-key-flat. - An empty root key produces a leading delimiter (
process('', { user: 1 })gives:user). Pass a real root name. - In
'bracket'mode array keys are always[index], independent ofobjectDelimiter; there is no way to get empty brackets (items[]) - use-key-railsfor that. arrayFormataccepts only'bracket'and'delimiter'; any other value is rejected by TypeScript, and at runtime anything other than'bracket'behaves as'delimiter'.- Numeric object property keys are formatted like properties, not indices: with defaults,
formatObjectKey('data', '0')givesdata:0whileformatArrayKey('data', 0)givesdata[0]. null/undefinedvalues,$typediscriminators, empty objects and empty arrays are dropped bycorebefore this strategy is consulted; circular references throwError: Circular reference detected at key: <key>.
🔗 Related packages
- Fixed notations:
-key-bracket-notation(user[name]),-key-rails(items[]),-key-flat(user_name, one separator everywhere) - Single parameter:
-key-json - Engine:
-core(implementIKeyFormattingStrategyyourself if even this is not flexible enough)
Full matrix and adapter recipes: main README.
📄 License
MIT © Adam Pluciński
