{"id":16773820,"url":"https://github.com/ziflex/compose-record","last_synced_at":"2026-04-01T21:04:25.448Z","repository":{"id":32907441,"uuid":"145603539","full_name":"ziflex/compose-record","owner":"ziflex","description":"Type-safe utility library for creating nested Immutable Records","archived":false,"fork":false,"pushed_at":"2023-03-04T02:56:51.000Z","size":950,"stargazers_count":1,"open_issues_count":5,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-04T01:58:47.443Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://ziflex.github.io/compose-record","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/ziflex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2018-08-21T18:27:45.000Z","updated_at":"2020-12-10T02:10:00.000Z","dependencies_parsed_at":"2025-02-17T23:32:50.743Z","dependency_job_id":"32376370-0472-4282-9691-c5efee8e0b3b","html_url":"https://github.com/ziflex/compose-record","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ziflex/compose-record","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziflex%2Fcompose-record","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziflex%2Fcompose-record/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziflex%2Fcompose-record/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziflex%2Fcompose-record/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ziflex","download_url":"https://codeload.github.com/ziflex/compose-record/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ziflex%2Fcompose-record/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31014567,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T02:58:54.984Z","status":"ssl_error","status_checked_at":"2026-03-27T02:58:46.993Z","response_time":164,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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-13T06:47:06.661Z","updated_at":"2026-03-27T03:27:29.231Z","avatar_url":"https://github.com/ziflex.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# compose-record\n\u003e Type-safe utility library for creating nested Immutable Records\n\n[![npm version](https://badge.fury.io/js/compose-record.svg)](https://www.npmjs.com/package/compose-record)\n[![Build Status](https://github.com/ziflex/compose-record/workflows/build/badge.svg)](https://github.com/ziflex/compose-record/actions)\n\n## Motivation\n\n[Immutable.js](https://facebook.github.io/immutable-js/) is a great library. Unfortunatelly, in v3 it does not support nested Records well, making its usability less pleasant.\nThe main purpose of this libary is to make our (my) life easier and reduce the amount of boilerplate code by providing a robust and typesafe wrapper around [Immutable.Record](https://facebook.github.io/immutable-js/docs/#/Record) class which initializes all other nested Immutable classes. It works like ``fromJS`` but for ``Record``.\n\n## Quick start\n\nThe following example shows a very basic use of ``compose-class`` using nested Records.\n\n````javascript\nimport { compose } from 'compose-record';\n\nconst Address = compose({\n    name: \"Address\",\n    properties: {\n        street: { type: String },\n        apt: { type: Number }\n    }\n});\n\nconst Profile = compose({\n    name: \"Profile\",\n    properties: {\n        name: { type: String },\n        address: { type: Address }\n    }\n});\n\nconst p = new Profile();\n\nconsole.log(p.toJS()); \n/*\n * {\n *     name: ''\n *     address: {\n *         street: '',\n *         apt: 0\n *     }\n * }\n * /\n\n````\n\n## Default values\n\nAll properties support custom default value. By default, these values are defined by their types.   \n\n````javascript\nimport { compose } from 'compose-record';\n\nconst Address = compose({\n    name: \"Address\",\n    properties: {\n        street: { type: String },\n        apt: { type: Number }\n    }\n});\n\nconst Profile = compose({\n    name: \"Profile\",\n    properties: {\n        name: {\n            type: String,\n            defaultValue: 'unknown'\n        },\n        address: {\n            type: Address,\n            defaultValue: {\n                street: 'unknown',\n                apt: -1\n            }\n        }\n    }\n});\n\nconst p = new Profile();\n\nconsole.log(p.toJS());\n\n/*\n * {\n *     name: 'unknown',\n *     address: {\n *         street: 'unknown',\n *         apt: -1\n *     }\n * }\n */\n````\n\n## Extension\n\n``compose-record`` allows you to extend your Records with other(s).\n\n````javascript\nimport { compose } from 'compose-record';\n\nconst Entity = compose({\n    name: \"Entity\",\n    properties: {\n        id: { type: Number }\n    }\n});\n\nconst User = compose({\n    name: \"User\",\n    extends: Entity,\n    properties: {\n        name: { type: String }\n    }\n});\n\nconst u = new User();\n\nconsole.log(p.toJS());\n\n/*\n * {\n *     id: 0,\n *     name: ''\n * }\n */\n\n````\n\n## Item types\n\nThat all works fine with Record and primitive types. But what if we need to have a List or a Map with nested Records? ``compose-record`` has a special option for these: ``items``. \n``items`` is a nested type descriptor that informs ``compose-record`` how to wrap the underlying values.\nIt's optional, by default ``compose-record`` will use a value as it is.\n\n````javascript\nimport { compose } from 'compose-record';\nimport { List } from 'immutable';\n\nconst User = compose({\n    name: 'User',\n    properties: {\n        name: { type: String }\n    }\n});\n\nconst Group = compose({\n    name: 'Group',\n    properties: {\n        users: { \n            type: List,\n            items: {\n                type: User\n            }\n        }\n    }\n});\n\nconst u = new Group({\n    users: [\n        { name: 'Mike Wazowski' },\n        { name: 'James P. Sullivan' }\n    ]\n});\n\nconsole.log(p.toJS());\n\n/*\n *    {\n *        users: [\n *            { name: 'Mike Wazowski' },\n *            { name: 'James P. Sullivan' }\n *        ]\n *     }\n */\n\n````\n\nYou can build even more complex scenarios:\n\n````javascript\nimport { compose } from 'compose-record';\nimport { List, Map } from 'immutable';\n\nconst User = compose({\n    name: 'User',\n    properties: {\n        name: { type: String }\n    }\n});\n\nconst Group = compose({\n    name: 'Group',\n    properties: {\n        users: { \n            type: Map,\n            items: {\n                type: List,\n                items: {\n                    type: User\n                }\n            }\n        }\n    }\n});\n\nconst u = new Group({\n    users: {\n        monsters: [\n            { name: 'Mike Wazowski' },\n            { name: 'James P. Sullivan' }\n        ],\n        humans: [\n            { name: 'Boo' }\n        ]\n    }\n});\n\nconsole.log(p.toJS());\n\n/*\n * {\n *     users: {\n *         monsters: [\n *             { name: 'Mike Wazowski' },\n *             { name: 'James P. Sullivan' }\n *         ],\n *      humans: [\n *          { name: 'Boo' }\n *      ]\n *   }\n * }\n */\n\n````\n\n**Note:** There is one caveat: It works only for constructors. All further inserts require you to pass an instance of a nested Record. This is a limiation of ```compose-record``` which might be solved in the future.\n\nCurrent work around is to get a type descriptor and use ``Record.createPropertyInstance()`` method:\n\n```javascript\nimport { compose } from 'compose-record';\nimport { List, Map } from 'immutable';\n\nconst User = compose({\n    name: 'User',\n    properties: {\n        name: {\n            type: String,\n        },\n    },\n});\n\nconst Group = compose({\n    name: 'Group',\n    properties: {\n        users: {\n            type: List,\n            items: {\n                type: User,\n            },\n        },\n    },\n});\n\nconst desc = Group.getPropertyDescriptors();\nconst u = Group.createPropertyInstance\u003cUser\u003e(desc.users.items, {\n    name: 'Mike Wazowski',\n});\n\nconst g = new Group();\nconsole.log(g.users.push(u).toJS());\n\n/*\n *    {\n *        users: [\n *            { name: 'Mike Wazowski' },\n *        ]\n *     }\n */\n```\n\n## Enum and custom types\n\nSince version 1.3, it is possible to create a factory function type that is executed as a regular function in order to get a custom value (usually mixed).\n\nHere is an example:\n\n  ```typescript\n    import { Immutable, compose } from 'compose-record';\n\n    enum Role {\n        User,\n        Admin,\n        Owner,\n    }\n\n    interface User extends Immutable {\n        username: string;\n        role: Role;\n    }\n\n    const UserRecord = compose\u003cUser\u003e({\n        name: 'User',\n        properties: {\n            username: {\n                type: String,\n            },\n            role: {\n                type: compose.factory\u003cRole, string\u003e((value?: string) =\u003e {\n                    let result = Role.User;\n\n                    switch (value) {\n                    case 'user':\n                        result = Role.User;\n                        break;\n                    case 'admin':\n                        result = Role.Admin;\n                        break;\n                    case 'owner':\n                        result = Role.Owner;\n                        break;\n                    }\n\n                    return result;\n                }),\n            },\n        },\n    });\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fziflex%2Fcompose-record","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fziflex%2Fcompose-record","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fziflex%2Fcompose-record/lists"}