{"id":13494774,"url":"https://github.com/aralroca/default-composer","last_synced_at":"2025-05-16T10:08:43.754Z","repository":{"id":169992103,"uuid":"645861300","full_name":"aralroca/default-composer","owner":"aralroca","description":"A tiny (~500B) JavaScript library that allows you to set default values for nested objects","archived":false,"fork":false,"pushed_at":"2023-11-22T16:07:22.000Z","size":145,"stargazers_count":469,"open_issues_count":0,"forks_count":11,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-09T03:02:56.775Z","etag":null,"topics":["composer","defaults","javascript","json","merge","mix","nested-objects","tree","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aralroca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-05-26T15:56:47.000Z","updated_at":"2024-12-15T17:57:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"f48fa297-a273-4def-a5a2-ad49af0c4af4","html_url":"https://github.com/aralroca/default-composer","commit_stats":{"total_commits":49,"total_committers":6,"mean_commits":8.166666666666666,"dds":"0.20408163265306123","last_synced_commit":"3b0884d2e9e302693843ca3b452a81d075d0a7e3"},"previous_names":["aralroca/default-composer"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aralroca%2Fdefault-composer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aralroca%2Fdefault-composer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aralroca%2Fdefault-composer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aralroca%2Fdefault-composer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aralroca","download_url":"https://codeload.github.com/aralroca/default-composer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509478,"owners_count":22082892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["composer","defaults","javascript","json","merge","mix","nested-objects","tree","typescript"],"created_at":"2024-07-31T19:01:28.009Z","updated_at":"2025-05-16T10:08:38.745Z","avatar_url":"https://github.com/aralroca.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"./logo.svg\" alt=\"Default composer logo\" width=\"100\" height=\"100\" /\u003e\n\u003ch1\u003e\n\u003cdiv\u003e\u003cb\u003eDefault composer\u003c/b\u003e\u003c/div\u003e\n\u003c/h1\u003e\n\u003c/div\u003e\n\n_A **tiny** (~500B) **JavaScript library** that allows you to set **default values** for **nested objects**_\n\n[![npm version](https://badge.fury.io/js/default-composer.svg)](https://badge.fury.io/js/default-composer)\n[![gzip size](https://img.badgesize.io/https://unpkg.com/default-composer?compression=gzip\u0026label=gzip)](https://unpkg.com/default-composer)\n[![CI Status](https://github.com/aralroca/default-composer/actions/workflows/test.yml/badge.svg)](https://github.com/aralroca/default-composer/actions/workflows/test.yml)\n[![Maintenance Status](https://badgen.net/badge/maintenance/active/green)](https://github.com/aralroca/default-composer#maintenance-status)\n[![Weekly downloads](https://badgen.net/npm/dw/default-composer?color=blue)](https://www.npmjs.com/package/default-composer)\n[![PRs Welcome][badge-prwelcome]][prwelcome]\u003c!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --\u003e\n[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-)\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:END --\u003e\n\n[badge-prwelcome]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n\n[prwelcome]: http://makeapullrequest.com\n\n\"default-composer\" is a JavaScript library that allows you to set default values for **nested objects**. The library replaces empty strings/arrays/objects, null, or undefined values in an existing object with the defined default values, which helps simplify programming logic and reduce the amount of code needed to set default values.\n\n**Content**:\n\n- [1. Installation](#installation)\n- [2. Usage](#usage)\n- [3. API](#api)\n  - [`defaultComposer`](#defaultcomposer)\n  - [`setConfig`](#setconfig)\n    - [`isDefaultableValue`](#isdefaultablevalue)\n    - [`mergeArrays`](#mergearrays)\n- [4. TypeScript](#typescript)\n- [5. Contributing](#contributing)\n- [6. License](#license)\n- [7. Credits](#credits)\n- [8. Contributors](#contributors-)\n\n## Installation\n\nYou can install \"default-composer\" using npm:\n\n```bh\nnpm install default-composer\n```\n\nor with yarn:\n\n```bh\nyarn add default-composer\n```\n\n## Usage\n\nTo use \"default-composer\", simply import the library and call the `defaultComposer()` function with the default values object and the original object that you want to set default values for. For example:\n\n```js\nimport { defaultComposer } from \"default-composer\";\n\nconst defaults = {\n  name: \"Aral 😊\",\n  surname: \"\",\n  isDeveloper: true,\n  isDesigner: false,\n  age: 33,\n  address: {\n    street: \"123 Main St\",\n    city: \"Anytown\",\n    state: \"CA\",\n  },\n  emails: [\"contact@aralroca.com\"],\n  hobbies: [\"programming\"],\n};\n\nconst originalObject = {\n  name: \"Aral\",\n  emails: [],\n  phone: \"555555555\",\n  age: null,\n  address: {\n    zip: \"54321\",\n  },\n  hobbies: [\"parkour\", \"computer science\", \"books\", \"nature\"],\n};\n\nconst result = defaultComposer(defaults, originalObject);\n\nconsole.log(result);\n```\n\nThis will output:\n\n```js\n{\n  name: 'Aral',\n  surname: '',\n  isDeveloper: true,\n  isDesigner: false,\n  emails: ['contact@aralroca.com'],\n  phone: '555555555',\n  age: 33,\n  address: {\n    street: '123 Main St',\n    city: 'Anytown',\n    state: 'CA',\n    zip: '54321'\n  },\n  hobbies: ['parkour', 'computer science', 'books', 'nature'],\n}\n```\n\n## API\n\n### `defaultComposer`\n\n```js\ndefaultComposer(defaultsPriorityN, [..., defaultsPriority2, defaultsPriority1, objectWithData])\n```\n\nThis function takes one or more objects as arguments and returns a new object with default values applied. The first argument should be an object containing the default values to apply. Subsequent arguments should be the objects to apply the default values to.\n\nIf a property in a given object is either empty, null, or undefined, and the corresponding property in the defaults object is not empty, null, or undefined, the default value will be used.\n\n**Example**:\n\n```js\nimport { defaultComposer } from \"default-composer\";\n\nconst defaultsPriority1 = {\n  name: \"Aral 😊\",\n  hobbies: [\"reading\"],\n};\n\nconst defaultsPriority2 = {\n  name: \"Aral 🤔\",\n  age: 33,\n  address: {\n    street: \"123 Main St\",\n    city: \"Anytown\",\n    state: \"CA\",\n    zip: \"12345\",\n  },\n  hobbies: [\"reading\", \"hiking\"],\n};\n\nconst object = {\n  address: {\n    street: \"\",\n    city: \"Anothercity\",\n    state: \"NY\",\n    zip: \"\",\n  },\n  hobbies: [\"running\"],\n};\n\nconst result = defaultComposer(defaultsPriority2, defaultsPriority1, object);\n\nconsole.log(result);\n```\n\nThis will output:\n\n```js\n{\n  name: 'Aral 😊',\n  age: 33,\n  address: {\n    street: '123 Main St',\n    city: 'Anothercity',\n    state: 'NY',\n    zip: '12345'\n  },\n  hobbies: ['running']\n}\n```\n\n### `setConfig`\n\n`setConfig` is a function that allows you to set configuration options for `defaultComposer`.\n\nThis is the available configuration:\n\n- **`isDefaultableValue`**, is a function that determines whether a value should be considered defaultable or not.\n- **`mergeArrays`**, is a boolean to define if you want to merge arrays (`true`) or not (`false`), when is set to `false` is just replacing to the default value when the original array is empty. By default is `false`.\n\n#### `isDefaultableValue`\n\nYou can use `setConfig` to provide your own implementation of `isDefaultableValue` if you need to customize this behavior.\n\n```ts\ntype IsDefaultableValueParams = ({\n  key,\n  value,\n  defaultableValue,\n}: {\n  key: string;\n  value: unknown;\n  defaultableValue: boolean; // In case you want to re-use the default behavior\n}) =\u003e boolean;\n```\n\nThe `defaultableValue` boolean is the result of the default behavior of `isDefaultableValue`. By default, is detected as `defaultableValue` when is `null`, `undefined`, an empty `string`, an empty `array`, or an empty `object`.\n\nHere is an example of how you can use `setConfig`:\n\n```ts\nimport { defaultComposer, setConfig } from \"default-composer\";\n\nconst isNullOrWhitespace = ({ key, value }) =\u003e {\n  return value === null || (typeof value === \"string\" \u0026\u0026 value.trim() === \"\");\n};\n\nsetConfig({ isDefaultableValue: isNullOrWhitespace });\n\nconst defaults = { example: \"replaced\", anotherExample: \"also replaced\" };\nconst originalObject = { example: \"   \", anotherExample: null };\nconst result = defaultComposer\u003cany\u003e(defaults, originalObject);\nconsole.log(result); // { example: 'replaced', anotherExample: 'also replaced' }\n```\n\nHere is another example of how you can use `setConfig` reusing the `defaultableValue`:\n\n```ts\nimport { defaultComposer, setConfig } from \"default-composer\";\n\nsetConfig({\n  isDefaultableValue({ key, value, defaultableValue }) {\n    return (\n      defaultableValue || (typeof value === \"string\" \u0026\u0026 value.trim() === \"\")\n    );\n  },\n});\n\nconst defaults = { example: \"replaced\", anotherExample: \"also replaced\" };\nconst originalObject = { example: \"   \", anotherExample: null };\nconst result = defaultComposer\u003cany\u003e(defaults, originalObject);\nconsole.log(result); // { example: 'replaced', anotherExample: 'also replaced' }\n```\n\n#### `mergeArrays`\n\nExample to merge arrays:\n\n```ts\nconst defaults = {\n  hobbies: [\"reading\"],\n};\n\nconst object = {\n  hobbies: [\"running\"],\n};\nsetConfig({ mergeArrays: true});\n\ndefaultComposer\u003cany\u003e(defaults, object)) // { hobbies: [\"reading\", \"running\"]}\n```\n\n## TypeScript\n\nIn order to use in TypeScript you can pass a generic with the expected output, and all the expected input by default should be partials of this generic.\n\nExample:\n\n```ts\ntype Addres = {\n  street: string;\n  city: string;\n  state: string;\n  zip: string;\n};\n\ntype User = {\n  name: string;\n  age: number;\n  address: Address;\n  hobbies: string[];\n};\n\nconst defaults = {\n  name: \"Aral 😊\",\n  hobbies: [\"reading\"],\n};\n\nconst object = {\n  age: 33,\n  address: {\n    street: \"\",\n    city: \"Anothercity\",\n    state: \"NY\",\n    zip: \"\",\n  },\n  hobbies: [],\n};\n\ndefaultComposer\u003cUser\u003e(defaults, object);\n```\n\n## Contributing\n\nContributions to \"default-composer\" are welcome! If you find a bug or want to suggest a new feature, please open an issue on the GitHub repository. If you want to contribute code, please fork the repository and submit a pull request with your changes.\n\n## License\n\n\"default-composer\" is licensed under the MIT license. See [LICENSE](LICENSE) for more information.\n\n## Credits\n\n\"default-composer\" was created by [Aral Roca](https://github.com/aralroca).\n\n\u003cimg src=\"https://img.shields.io/twitter/follow/aralroca?style=social\u0026logo=twitter\"\n            alt=\"follow on Twitter\"\u003e\u003c/a\u003e\n\n## Contributors ✨\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://aralroca.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/13313058?v=4?s=100\" width=\"100px;\" alt=\"Aral Roca Gomez\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAral Roca Gomez\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/aralroca/default-composer/commits?author=aralroca\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#maintenance-aralroca\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://robinpokorny.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/68341?v=4?s=100\" width=\"100px;\" alt=\"Robin Pokorny\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRobin Pokorny\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/aralroca/default-composer/commits?author=robinpokorny\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/leeferwagen\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1287545?v=4?s=100\" width=\"100px;\" alt=\"Muslim Idris\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMuslim Idris\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/aralroca/default-composer/commits?author=leeferwagen\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/namhtpyn\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/16488178?v=4?s=100\" width=\"100px;\" alt=\"namhtpyn\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003enamhtpyn\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#infra-namhtpyn\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/Josuto\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6097850?v=4?s=100\" width=\"100px;\" alt=\"Josu Martinez\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJosu Martinez\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/aralroca/default-composer/issues?q=author%3AJosuto\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faralroca%2Fdefault-composer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faralroca%2Fdefault-composer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faralroca%2Fdefault-composer/lists"}