{"_id":"@adaskothebeast/http-params-processor-key-rails","_rev":"4-956dc3517294aa4dd6349487d0ccc1df","name":"@adaskothebeast/http-params-processor-key-rails","dist-tags":{"latest":"12.0.0"},"versions":{"10.0.0":{"name":"@adaskothebeast/http-params-processor-key-rails","version":"10.0.0","_id":"@adaskothebeast/http-params-processor-key-rails@10.0.0","maintainers":[{"name":"adasko","email":"adaskothebeast@gmail.com"}],"dist":{"shasum":"f2b495b071a0f9eafc003ef9554a61c8b37a0943","tarball":"https://registry.npmjs.org/@adaskothebeast/http-params-processor-key-rails/-/http-params-processor-key-rails-10.0.0.tgz","fileCount":15,"integrity":"sha512-WkN7oi/1SushCpo/Khq9QpXH3DWmzgfGO1y+yCELctFWBVXbn9iCAX7rgjbGFxzyp/drlI1kb7sf20NYof+VLQ==","signatures":[{"sig":"MEUCIBmvare7PDs81h02HDQdQjG8saKk4H1Pp62CvUvfPUMzAiEA/SAVqfKxGP8ahV2jfewiI8Y4IWvHVBF/bsoF0Gvyc1o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27724},"main":"./src/index.js","type":"commonjs","types":"./src/index.d.ts","gitHead":"1e61d6323f67038b9af916e4f3d263a73fe76497","_npmUser":{"name":"adasko","email":"adaskothebeast@gmail.com"},"_npmVersion":"11.6.2","description":"> Transform complex TypeScript objects into query parameters for Angular, Axios, Fetch, and more","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"peerDependencies":{"@adaskothebeast/http-params-processor-core":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/http-params-processor-key-rails_10.0.0_1768077176150_0.6334782657679203","host":"s3://npm-registry-packages-npm-production"}},"11.0.0":{"name":"@adaskothebeast/http-params-processor-key-rails","version":"11.0.0","author":{"url":"https://github.com/adaskothebeast","name":"Adam Pluciński","email":"adaskothebeast@gmail.com"},"license":"MIT","_id":"@adaskothebeast/http-params-processor-key-rails@11.0.0","maintainers":[{"name":"adasko","email":"adaskothebeast@gmail.com"}],"homepage":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor","bugs":{"url":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor/issues"},"dist":{"shasum":"68a500d68f304d9b124298a30fe65c3026b77f3c","tarball":"https://registry.npmjs.org/@adaskothebeast/http-params-processor-key-rails/-/http-params-processor-key-rails-11.0.0.tgz","fileCount":8,"integrity":"sha512-g6YMMlmJB5XHueGTOmWDf8zf4y88LNknu7gjQiGrokGW8Ie/laGPL1RBuRhDAev+kIw5As4JhNz+6bcakfaCFQ==","signatures":[{"sig":"MEQCIEo+x0ZNk8paY0PYvU5N5Yyhg4KC9MV3HPUsZqKZRV0/AiAi5HCqhwKoxSYTZb3BBRWTv7Y86yHV62OdGxM1nFXesQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@adaskothebeast%2fhttp-params-processor-key-rails@11.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":38857},"main":"./index.cjs","type":"module","types":"./index.d.ts","module":"./index.js","exports":{".":{"types":"./index.d.ts","import":"./index.js","default":"./index.js","require":"./index.cjs"},"./package.json":"./package.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:16ab3e30-b8ff-47cf-9e16-9d20bc2ec580"}},"repository":{"url":"git+https://github.com/AdaskoTheBeAsT/HttpParamsProcessor.git","type":"git"},"_npmVersion":"11.6.2","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/http-params-processor-key-rails_11.0.0_1768758175788_0.5370273108872599","host":"s3://npm-registry-packages-npm-production"}},"11.1.0":{"name":"@adaskothebeast/http-params-processor-key-rails","version":"11.1.0","author":{"url":"https://github.com/adaskothebeast","name":"Adam Pluciński","email":"adaskothebeast@gmail.com"},"license":"MIT","_id":"@adaskothebeast/http-params-processor-key-rails@11.1.0","maintainers":[{"name":"adasko","email":"adaskothebeast@gmail.com"}],"homepage":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor","bugs":{"url":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor/issues"},"dist":{"shasum":"a54e98010d31d2e87c7b512a90705a54323bd389","tarball":"https://registry.npmjs.org/@adaskothebeast/http-params-processor-key-rails/-/http-params-processor-key-rails-11.1.0.tgz","fileCount":8,"integrity":"sha512-rej5+5PH3swIjKtv8KCg4ZrY3A4ooEbuQpSqmrXmgabw6s+00DNX1grObTa63GpzBCk8mS8Y/AjOg5i4B/vOEQ==","signatures":[{"sig":"MEYCIQChMSuouY3iXlAqkiZfIqUgyj5zhcjdLInct1H79xeyHQIhAJbZpTUJD8wO9vxkte7foFFeB1ezAnfKbK4FOG7yaaPO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@adaskothebeast%2fhttp-params-processor-key-rails@11.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":38857},"main":"./index.cjs","type":"module","types":"./index.d.ts","module":"./index.js","exports":{".":{"types":"./index.d.ts","import":"./index.js","default":"./index.js","require":"./index.cjs"},"./package.json":"./package.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:16ab3e30-b8ff-47cf-9e16-9d20bc2ec580"}},"repository":{"url":"git+https://github.com/AdaskoTheBeAsT/HttpParamsProcessor.git","type":"git"},"_npmVersion":"11.6.2","directories":{},"_nodeVersion":"24.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/http-params-processor-key-rails_11.1.0_1768758914020_0.4061528059415114","host":"s3://npm-registry-packages-npm-production"}},"12.0.0":{"name":"@adaskothebeast/http-params-processor-key-rails","version":"12.0.0","description":"Ruby on Rails and Rack style key formatting strategy for HttpParamsProcessor, emitting user[name] and items[] keys.","keywords":["http","http-params","query-string","query-params","querystring","nested-objects","serializer","typescript","key-formatting","rails","ruby","bracket-notation"],"license":"MIT","author":{"name":"Adam Pluciński","email":"adaskothebeast@gmail.com","url":"https://github.com/adaskothebeast"},"repository":{"type":"git","url":"git+https://github.com/AdaskoTheBeAsT/HttpParamsProcessor.git"},"bugs":{"url":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor/issues"},"homepage":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor","type":"module","sideEffects":false,"main":"./index.cjs","module":"./index.js","types":"./index.d.ts","peerDependencies":{"@adaskothebeast/http-params-processor-core":"^12.0.0"},"exports":{".":{"types":"./index.d.ts","import":"./index.js","default":"./index.js","require":"./index.cjs"},"./package.json":"./package.json"},"gitHead":"73d31a6c26a6f2819f6c98aabb36659532e4cdd0","_id":"@adaskothebeast/http-params-processor-key-rails@12.0.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-LtX4LXOE08FAjx98HPQy40g4nL/Y+RTk+1ZyY2MEVEi7weXBcdZroEIAIvu0f78KedSMwJOgcMXMbGQmyI932A==","shasum":"9f0e9dd63a4ed0dbeb3735ecb9f331087db31c45","tarball":"https://registry.npmjs.org/@adaskothebeast/http-params-processor-key-rails/-/http-params-processor-key-rails-12.0.0.tgz","fileCount":9,"unpackedSize":14247,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDileaQ0c+z7QTu4WvpBU5AgeoE8HnMSMhsLGRvMKVOtAiEA3CsoErTTSnRxTMEThAMRkaPrMCMwZ9Vka5X229EyUFk="}]},"_npmUser":{"name":"adasko","email":"adaskothebeast@gmail.com"},"directories":{},"maintainers":[{"name":"adasko","email":"adaskothebeast@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/http-params-processor-key-rails_12.0.0_1785236013011_0.5499544487553649"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-10T20:32:56.065Z","modified":"2026-07-28T10:53:33.360Z","10.0.0":"2026-01-10T20:32:56.306Z","11.0.0":"2026-01-18T17:42:55.994Z","11.1.0":"2026-01-18T17:55:14.189Z","12.0.0":"2026-07-28T10:53:33.155Z"},"bugs":{"url":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor/issues"},"author":{"name":"Adam Pluciński","email":"adaskothebeast@gmail.com","url":"https://github.com/adaskothebeast"},"license":"MIT","homepage":"https://github.com/AdaskoTheBeAsT/HttpParamsProcessor","repository":{"type":"git","url":"git+https://github.com/AdaskoTheBeAsT/HttpParamsProcessor.git"},"maintainers":[{"name":"adasko","email":"adaskothebeast@gmail.com"}],"readme":"# 🛤️ @adaskothebeast/http-params-processor-key-rails\n\n**Ruby on Rails and Rack style key formatting for [HttpParamsProcessor](https://github.com/AdaskoTheBeAsT/HttpParamsProcessor): `user[name]` for objects, `items[]` for array elements.**\n\n[![npm](https://img.shields.io/npm/v/%40adaskothebeast%2Fhttp-params-processor-key-rails?color=cb3837&logo=npm)](https://www.npmjs.com/package/@adaskothebeast/http-params-processor-key-rails)\n[![license](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\nNo runtime dependency beyond `core` (its only peer dependency, `^12.0.0`). ESM + CJS. `sideEffects: false`.\n\n---\n\n## 📦 Install\n\n```bash\nnpm i @adaskothebeast/http-params-processor-key-rails @adaskothebeast/http-params-processor-core\n```\n\n---\n\n## 🎯 What it does\n\nThis is a **key formatting strategy**: it decides how nested keys are spelled while `ParamsProcessor` walks your object graph. It emits exactly what `Rack::Utils.parse_nested_query` (and therefore Rails `params`) expects: brackets around object properties and **empty brackets** for array elements.\n\n| Input                                 | `DefaultKeyFormattingStrategy` (core) | `RailsKeyFormattingStrategy` (default) |\n| ------------------------------------- | ------------------------------------- | -------------------------------------- |\n| `{ user: { name: 'John' } }`          | `p.user.name`                         | `p[user][name]`                        |\n| `{ items: ['x', 'y'] }`               | `p.items[0]`, `p.items[1]`            | `p[items][]` twice                     |\n| `{ arr: [{ id: '1' }, { id: '2' }] }` | `p.arr[0].id`, `p.arr[1].id`          | `p[arr][][id]` twice                   |\n\nRack rebuilds arrays of hashes positionally: it starts a new hash whenever a key repeats, so `arr[][id]=1&arr[][id]=2` parses back to `[{ id: 1 }, { id: 2 }]`.\n\n---\n\n## 🧰 API\n\n### `RailsKeyFormattingStrategy`\n\nImplements `IKeyFormattingStrategy` from `core`.\n\n| Member                                         | Returns  | Result                                                   |\n| ---------------------------------------------- | -------- | -------------------------------------------------------- |\n| `new RailsKeyFormattingStrategy(arrayFormat?)` | -        | `arrayFormat` defaults to `'brackets'`                   |\n| `formatObjectKey(parentKey, propertyKey)`      | `string` | `` `${parentKey}[${propertyKey}]` `` in both formats     |\n| `formatArrayKey(parentKey, index)`             | `string` | `` `${parentKey}[]` `` or `` `${parentKey}[${index}]` `` |\n\n### `RailsArrayFormat`\n\n```ts\ntype RailsArrayFormat = 'brackets' | 'indexed';\n```\n\n| Value                  | Array key  | Use when                                                                 |\n| ---------------------- | ---------- | ------------------------------------------------------------------------ |\n| `'brackets'` (default) | `items[]`  | Idiomatic Rails/Rack: order carries the position                         |\n| `'indexed'`            | `items[0]` | Explicit indices, also accepted by Rack, needed for arrays inside arrays |\n\n`transformComplexObject` is not implemented, so nested objects and arrays are always traversed down to primitives.\n\n---\n\n## ⚡ Usage\n\n```ts\nimport { createParamsProcessor } from '@adaskothebeast/http-params-processor-core';\nimport { RailsKeyFormattingStrategy } from '@adaskothebeast/http-params-processor-key-rails';\n\nconst processor = createParamsProcessor({\n  keyFormatter: new RailsKeyFormattingStrategy(),\n});\n\nprocessor.process('p', { items: ['x', 'y'] });\n// [['p[items][]', 'x'], ['p[items][]', 'y']]\n\nprocessor.process('p', {\n  arr: [\n    { id: '1', text: 'first' },\n    { id: '2', text: 'second' },\n  ],\n});\n// [\n//   ['p[arr][][id]', '1'],\n//   ['p[arr][][text]', 'first'],\n//   ['p[arr][][id]', '2'],\n//   ['p[arr][][text]', 'second'],\n// ]\n```\n\n`process` preserves duplicate keys and their order, which is precisely what the empty bracket format relies on. The same `keyFormatter` option is accepted by every adapter (`-angular`, `-angular-resource`, `-fetch`, `-axios`, `-react-tanstack-query`, `-react-swr`).\n\n---\n\n## 🎛️ Options and configuration\n\n```ts\nnew RailsKeyFormattingStrategy(); // 'brackets' - items[]\nnew RailsKeyFormattingStrategy('brackets'); // same, explicit\nnew RailsKeyFormattingStrategy('indexed'); // items[0]\n```\n\nObject keys are bracketed in both modes; only array element keys differ.\n\n```ts\nconst processor = createParamsProcessor({\n  keyFormatter: new RailsKeyFormattingStrategy('indexed'),\n});\n\nprocessor.process('p', { arr: [{ id: '1' }, { id: '2' }] });\n// [['p[arr][0][id]', '1'], ['p[arr][1][id]', '2']]\n```\n\nThe strategy is stateless, so instances can be shared, and `keyFormatter` can also be passed per call to override the processor default.\n\n---\n\n## 📤 Output examples\n\n```text\n'brackets' (default)\np[items][]        = x\np[items][]        = y\np[arr][][id]      = 1\np[arr][][text]    = first\np[arr][][id]      = 2\np[arr][][text]    = second\n\n'indexed'\np[arr][0][id]     = 1\np[arr][1][id]     = 2\np[user][tags][2]  = ruby\n```\n\n```ts\nprocessor.toQueryString('p', { items: ['x', 'y'] });\n// p%5Bitems%5D%5B%5D=x&p%5Bitems%5D%5B%5D=y\n\nprocessor.toPlainObject('p', { items: ['x', 'y'] });\n// { 'p[items][]': ['x', 'y'] }   duplicate keys collapse into an array\n```\n\nOn the server, `p[items][]=x&p[items][]=y` becomes `params[:p][:items] == ['x', 'y']` in Rails, and Node's `qs` parses it into `{ p: { items: ['x', 'y'] } }`.\n\n---\n\n## ⚠️ Edge cases\n\n- In `'brackets'` mode the **index is ignored**: `formatArrayKey('items', 7)` is still `items[]`. Position comes from the order of the emitted pairs, so never sort or deduplicate the entries before sending them.\n- Rack's positional grouping cannot disambiguate an **array nested directly inside an array element** (`arr[][inner][]`); switch to `new RailsKeyFormattingStrategy('indexed')` for such payloads.\n- Grouping also breaks if two sibling elements do not carry the same properties (a `null`/`undefined` property is skipped by `core`, so that element emits fewer pairs and Rack may merge it with the next one). Use `'indexed'` for sparse objects.\n- `toPlainObject` merges the repeated `items[]` key into a string array, which is what `axios` `params` needs; `process` keeps the duplicates separate.\n- An **empty root key** yields keys starting with a bracket (`[user]`), so pass a real root name.\n- Numeric object property keys stay object keys: `formatObjectKey('data', '0')` gives `data[0]`.\n- `null`/`undefined` values, `$type` discriminators, empty objects and empty arrays are dropped by `core` before this strategy is consulted; circular references throw `Error: Circular reference detected at key: <key>`.\n\n---\n\n## 🔗 Related packages\n\n- Same object shape, indexed arrays only: [`-key-bracket-notation`](https://www.npmjs.com/package/@adaskothebeast/http-params-processor-key-bracket-notation) (PHP, Laravel, Symfony)\n- Other key strategies: [`-key-flat`](https://www.npmjs.com/package/@adaskothebeast/http-params-processor-key-flat) (`user_name`), [`-key-custom-delimiter`](https://www.npmjs.com/package/@adaskothebeast/http-params-processor-key-custom-delimiter) (`user:name`), [`-key-json`](https://www.npmjs.com/package/@adaskothebeast/http-params-processor-key-json) (whole subtree as one JSON value)\n- Engine: [`-core`](https://www.npmjs.com/package/@adaskothebeast/http-params-processor-core)\n\nFull matrix and adapter recipes: [main README](https://github.com/AdaskoTheBeAsT/HttpParamsProcessor#readme).\n\n---\n\n## 📄 License\n\n[MIT](./LICENSE) © Adam Pluciński\n","readmeFilename":"README.md","description":"Ruby on Rails and Rack style key formatting strategy for HttpParamsProcessor, emitting user[name] and items[] keys.","keywords":["http","http-params","query-string","query-params","querystring","nested-objects","serializer","typescript","key-formatting","rails","ruby","bracket-notation"]}