{"id":16513777,"url":"https://github.com/wintercounter/transformed","last_synced_at":"2026-06-13T09:31:45.323Z","repository":{"id":148932827,"uuid":"310591539","full_name":"wintercounter/transformed","owner":"wintercounter","description":null,"archived":false,"fork":false,"pushed_at":"2021-01-03T21:06:59.000Z","size":54,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-05T21:57:15.560Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wintercounter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-06T12:28:42.000Z","updated_at":"2023-03-09T03:30:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"5e9ee54a-58e2-4b7a-a9a4-f753cb2605ef","html_url":"https://github.com/wintercounter/transformed","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wintercounter/transformed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wintercounter%2Ftransformed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wintercounter%2Ftransformed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wintercounter%2Ftransformed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wintercounter%2Ftransformed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wintercounter","download_url":"https://codeload.github.com/wintercounter/transformed/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wintercounter%2Ftransformed/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34279898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T16:10:16.614Z","updated_at":"2026-06-13T09:31:45.304Z","avatar_url":"https://github.com/wintercounter.png","language":"TypeScript","funding_links":["https://www.patreon.com/wintercounter"],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003etransformed ⚡\u003c/h1\u003e\n\u003cp\u003e\n  \u003ca href=\"#\" target=\"_blank\"\u003e\n    \u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://twitter.com/wintercounter2\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Twitter: wintercounter1\" src=\"https://img.shields.io/twitter/follow/wintercounter1.svg?style=social\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003e A lightweight, low-level, performant, customizable object transformer utility.\n\n-   Custom parsers per prop.\n-   Custom output transformer.\n-   Built-in value map support.\n-   Multi-key support.\n-   Post-instantiation configuration.\n\n## Install\n\n```sh\nnpm i transformed\n```\n\n## Usage\n\n```js\nimport transformed from 'transformed'\n\nconst myTransformer = transformed()\n\nmyTransformer({ foo: 'bar' })\n```\n\nBy default `transformed` won't do anything with your data, you need to define your rules:\n\n-   `props`: definitions of how to process which prop\n-   `outputTransformer`: how to process your output\n\n### Options\n\n-   `autoCamelCase` _(default: false)_: automatically adds support for _camelCase_ versions of the passed prop names.\n-   `hasOwnPropertyCheck` _(default: false)_: for a slight performance improvement we're not doing `hasOwnProperty` checks\n    by default, but you can enable for cases when not using simple objects as input.\n-   `toValueCache` _(default: true)_: Enables/disable toValue call caching. This can greatly improve performance in when\n    doing expensive repeated tasks using `toValue` calls.\n\n### API\n\n(InputObject): Whatever\nregistry: Map\u003cstring, Definition\u003e\noutputTransformer: OutputTransformer\noptions: Partial\u003cOptions\u003e\nsetOptions(options: Partial\u003cOptions\u003e): TransformedFn\nsetOutputTransformer(outputTransformer: OutputTransformer): TransformedFn\nsetProps(props: Props | ObjectProps): TransformedFn\ntoValue(prop: string, value: unknown)\n\n#### `transformed()` (default export)\n\nA constructor method to create your transformer instance.\n\n#### `setOptions()`\n\nSet options for your instance.\n\n```js\nconst myTransformer = transformed()\nmyTransformer.setOptions({\n    autoCamelCase: true,\n    foo: 'bar'\n})\n```\n\n\u003e You may add custom config keys/values. You can access these options inside your property parsers and output transformer.\n\n#### `setOutputTransformer()`\n\nSet `outputTransformer` for your instance.\n\n```js\nconst myOutputTransformer = ...\nconst myTransformer = transformed()\nmyTransformer.setOutputTransformer(myOutputTransformer)\n```\n\n\u003e Output transformers always should be set before calling any `setProps` because they have the capability to alter prop names when registering them.\n\n#### `setProps()`\n\nSet supported properties for your instance.\n\nProperties defined in \"Babel config fashion\". Arrays of property descriptors.\n\n```js\n// All props\nconst props = [\n    // Property\n    [\n        // Property names\n        ['p', 'pad', 'padding'],\n        // Optional value map for this property. Use `null` or leave emoty if not needed.\n        { large: '30px' },\n        // Optional value parsers\n        [input =\u003e output],\n        // Optional descriptor options for any extra options you want to add for yourself.\n        { foo: 'bar' }\n    ]\n]\n```\n\n```js\nconst props = [\n    [['p', 'pad', 'padding'], { large: '30px' }],\n    [['bg', 'background'], { cars: 'cars.png' }, [(input, prop) =\u003e ({ [prop]: `http://mysite.com/images/${input}` })]]\n]\n\nconst transform = transformed().setProps(props)\n\ntransform({\n    padding: 'large',\n    background: 'cars'\n})\n\n// Output: { padding: '30px', background: 'http://mysite.com/images/cars.png' }\n```\n\nIn case you're setting an existing prop it will:\n\n-   reuse the existing `property names` found in the registry, you don't need to redefine all;\n-   merge the passed `valueMap` with the existing one;\n-   merge the list of `parsers` with the existing one.\n\nBased on the circumstances you need to control the execution order of parser. Extending the `parser` list can be done\nusing Webpack style extend operator (`...`):\n\n##### ObjectProp shorthand\n\nYou may also pass a `key: valueMap` object. This is useful if you want re-configure some existing prop's value map, or\nyou simply want to set a single new prop with a value map.\nIt cannot set handlers and multiple keys.\n\n```js\nconst transform = transformed().setProps({ myProp: { foo: 'bar' } })\ntransform({ myProp: 'foo' })\n\n// Output: { myProp: 'bar' }\n```\n\n```js\nconst props = [\n    // In this case transformed will simply prepend your own parser before the existing ones\n    [['p', 'pad', 'padding'], null, [myOwnParser, '...']]\n]\n```\n\n#### `toValue()`\n\nSometimes you just want to get a value for a prop/value pair.\n\n```\nmyTransformer.toValue('padding', 'large')\n```\n\n#### `use()`\n\nA simple helper method used to achieve a streaming interface for customization. It awaits a function where you can do\nyour customization inside. It's just an API sugar.\n\n```js\n// Instead of\nuseMyCustomProp1(myTransformer)\nuseMyCustomProp2(myTransformer)\nuseMyCustomProp3(myTransformer)\n\n// You can do\nmyTransformer.use(myCustomProp1).use(myCustomProp2).use(myCustomProp3)\n```\n\n```\nmyTransformer.toValue('padding', 'large')\n```\n\n#### Creating Object Transformers\n\nObject transformer is just a single function with static properties that loops through each property and values using\nthe following API:\n\n-   `myOutputTransformer()`: returns your transformed output, receives the following arguments:\n    -   `output`: currently generated output in current iteration (on first iteration it's _defaultOutput_)\n    -   `value`: the generated value in the current iteration\n    -   `prop`: the prop name for the current iteration\n    -   `inputObject`: the original object passed to _transformed_\n    -   `transformedFn`: current _transformed_ instance used for this iteration\n-   `defaultOutput()`: _mandatory_ function returning the default output\n-   `unsupportedHandler()`: _optional_ you may specify a handler for unsupported (not registered) properties; receives\n    same arguments as your _outputTransformer_ function\n-   `camelCaseReducer`: _optional_ reducer function to alter how generated camelCase keys stored; parameters are the\n    same as for a normal `array.reduce` callback (accumulator, currentValue, index)\n    `transformed` will simply push it into the existing key list\n\n\u003e See **Complete Example** for details on usage.\n\n#### Creating parsers\n\nParsers are telling how to process values for a certain property. You can apply as many parser functions as you want,\nduring generation the next function will get the previous function's output value (pipe).\n\nThe parser function receives the following arguments:\n\n-   value: initial value, or the previous parser's output\n-   prop: property name,\n-   transformedFn: _transformed_ instance\n-   inputObject: original input object\n-   definition: definition object stored in the property registry for this prop\n\n```js\nconst alwaysBar = (input, prop) =\u003e ({ [prop]: 'bar' })\nconst myTransformer = transformed().setProps([[['foo'], null, [alwaysBar]]])\n\nmyTransformer({ foo: 'baz' })\n\n// Output: { foo: 'bar' }\n```\n\n\u003e See **Complete Example** for more advanced details on usage.\n\n#### Handling `unsupported` (un-registered) values\n\nKeys that don't have registered handler ignored by default. However, you can tell which key's you want to proceed with.\n\nThis can be useful for example when dealing with CSS, and you need to pass some ancient or browser specific\nstyle property.\n\nYou have tu use the prop key: `unsupported` which can be:\n\n-   `true`: all props allowed\n-   `string[]`: list of props to allow\n-   `string`: a single prop to allow\n\n```\n// `-moz-*` will be ignored\n{\n    padding: '10px',\n    '-moz-border-radius': '10px',\n    '-moz-foo-bar': 12\n}\n\n// only `-moz-foo-bar` will be ignored\n{\n    padding: '10px',\n    '-moz-border-radius': '10px',\n    '-moz-foo-bar': 12\n    unsupported: '-moz-foo-bar'\n}\n\n// allow all\n{\n    padding: '10px',\n    '-moz-border-radius': '10px',\n    '-moz-foo-bar': 12\n    unsupported: true\n}\n\n// specify what's allowed\n{\n    padding: '10px',\n    '-moz-border-radius': '10px',\n    '-moz-foo-bar': 12\n    unsupported: ['-moz-foo-bar', '-moz-border-radius']\n}\n\n```\n\n### Complete example\n\nLet's see a simple example to build string based CSS output for a Style Object:\n\n```js\nconst toCSSParser = (value, prop, transformedFn, inputObject, definition) =\u003e {\n    // Let's always use the last key as CSS key\n    const cssProperty = definition.keys[definition.keys.length - 1]\n    return `${cssProperty}: ${value};\\n`\n}\n// It'll just simply concat\nconst cssTransformer = (output, value) =\u003e `${output}${value}`\n// Default output is just a string we will concat into\ncssTransformer.defaultOutput = () =\u003e ''\n\nconst props = [\n    [['p', 'pad', 'padding'], { large: '30px' }, [toCSSParser]],\n    [['bg', 'background'], null, [toCSSParser]]\n]\n\nconst myTransformer = transformed().setOutputTransformer(cssTransformer).setProps(props)\n\nmyTransformer({ p: 'large', bg: './cars.png' })\n\n/**\n * Output:\n *\n * padding: 30px;\n * background: './cars.png'\n */\n```\n\n## Show your support\n\nGive a ⭐️ if this project helped you!\n\n\u003ca href=\"https://www.patreon.com/wintercounter\"\u003e\n  \u003cimg src=\"https://c5.patreon.com/external/logo/become_a_patron_button@2x.png\" width=\"160\"\u003e\n\u003c/a\u003e\n\n---\n\n_This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwintercounter%2Ftransformed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwintercounter%2Ftransformed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwintercounter%2Ftransformed/lists"}