{"id":13516832,"url":"https://github.com/webiny/commodo","last_synced_at":"2025-04-12T23:32:23.401Z","repository":{"id":34731063,"uuid":"182967759","full_name":"webiny/commodo","owner":"webiny","description":"Commodo is a library of higher order functions (HOFs) that let you create and compose rich data models","archived":false,"fork":false,"pushed_at":"2023-01-06T01:48:39.000Z","size":3847,"stargazers_count":46,"open_issues_count":19,"forks_count":11,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-09T12:06:26.720Z","etag":null,"topics":["complex-models","composable","database","modelling","models","odm","orm","schema","validation"],"latest_commit_sha":null,"homepage":"https://www.github.com/webiny/commodo","language":"JavaScript","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/webiny.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-23T08:17:54.000Z","updated_at":"2022-06-04T09:25:27.000Z","dependencies_parsed_at":"2023-01-15T09:01:38.071Z","dependency_job_id":null,"html_url":"https://github.com/webiny/commodo","commit_stats":null,"previous_names":[],"tags_count":642,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2Fcommodo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2Fcommodo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2Fcommodo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webiny%2Fcommodo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webiny","download_url":"https://codeload.github.com/webiny/commodo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248647257,"owners_count":21139081,"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":["complex-models","composable","database","modelling","models","odm","orm","schema","validation"],"created_at":"2024-08-01T05:01:26.346Z","updated_at":"2025-04-12T23:32:20.332Z","avatar_url":"https://github.com/webiny.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/logo.png\" width=\"600\"\u003e\n\u003c/p\u003e\n\n[![Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io)\n[![license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/webiny/webiny-js/blob/master/LICENSE)\n[![SemVer](http://img.shields.io/:semver-2.0.0-brightgreen.svg)](http://semver.org)\n[![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![Gitter](https://img.shields.io/gitter/room/webiny/webiny-js.svg?style=flat-square)](https://gitter.im/webiny/webiny-js)\n\nCommodo is a library of [higher order functions (HOFs)](https://en.wikipedia.org/wiki/Higher-order_function) that let you create and compose rich data models.\n\n## 📹 Videos\nWanna get up to speed quickly? Check out the [Commodo videos here](https://www.youtube.com/watch?v=i9xRDdqCzjk\u0026list=PL9HlKSQaEuXRU5rPOlv3vPWeWew7-bMep)!\n\n## Quick example\n\n##### A simple model\nThe following example shows how to create a simple data model, which you can later use to validate data (e.g. data received as body of an HTTP request):\n\n```javascript\nimport { withFields, string, number, boolean } from \"@commodo/fields\";\n\nconst Animal = withFields({\n    name: string({\n        validation: value =\u003e {\n            if (!value) {\n                throw Error(\"A pet must have a name!\");\n            }\n        }\n    }),\n    age: number(),\n    isAwesome: boolean(),\n    about: fields({\n        value: {},\n        instanceOf: withFields({\n            type: string({ value: \"cat\" }),\n            dangerous: boolean({ value: true })\n        })()\n    })\n})();\n\nconst animal = new Animal();\nanimal.populate({ age: \"7\" }); // Throws data type error, cannot populate a string with number.\n\nanimal.populate({ age: 7 });\nawait animal.validate(); // Throws a validation error - name must be defined.\n\nanimal.name = \"Garfield\";\nawait animal.validate(); // All good.\n```\n\n##### More complex model\nUsing other HOFs, you can create more complex models, that have a name, attached hooks, and even storage layer, so that you can easily save the data to the database:\n\n```javascript\nimport { withFields, string, number, boolean, fields, onSet } from \"@commodo/fields\";\nimport { withName } from \"@commodo/name\";\nimport { withHooks } from \"@commodo/hooks\";\nimport { withStorage } from \"@commodo/fields-storage\";\nimport { MongoDbDriver, withId } from \"@commodo/fields-storage-mongodb\";\nimport { compose } from \"ramda\";\n\n// Define User and Verification models.\nconst Verification = compose(\n  withFields({\n    verified: boolean(),\n    verifiedOn: string()\n  })\n)();\n\nconst User = compose(\n  withFields({\n    firstName: string(),\n    lastName: string(),\n    email: compose(\n      onSet(value =\u003e value.toLowerCase())\n    )(string()),\n    age: number(),\n    scores: number({ list: true }),\n    enabled: boolean({ value: false }),\n    verification: fields({ instanceOf: Verification })\n  }),\n  withHooks({\n    async beforeCreate() {\n      if (await User.count({ query: { email: this.email } })) {\n        throw Error(\"User with same e-mail already exists.\");\n      }\n    }\n  }),\n  withName(\"User\"), // Utilized by storage layer, to determine collection / table name.\n  withId(),\n  withStorage({\n    driver: new MongoDbDriver({ database })\n  })\n)();\n\nconst user = new User();\nuser.populate({\n  firstName: \"Adrian\",\n  lastName: \"Smith\",\n  email: \"aDrIan@google.com\",\n  enabled: true,\n  scores: [34, 66, 99],\n  verification: {\n    verified: true,\n    verifiedOn: \"2019-01-01\"\n  }\n});\n\nawait user.save();\n```\n\n## Is Commodo an ORM/ODM?\nFundamentally, Commodo is not an ORM/ODM, but can very quickly become one, by utilizing an additional HOF. You can use the already provided [@commodo/fields-storage](https://github.com/webiny/commodo/tree/master/packages/fields-storage) or even create your own if you don't like the existing one.\n\nUsing HOFs is a very flexible approach for defining your data models, because you can append only the functionality you actually need and will use.\n\n## Core packages:\n\nThe following section shows all of the useful higher order functions that you can use right now.\n\n| Package | Short Description | Version |\n| :--- | :---: | :---: |\n| [@commodo/fields](./packages/fields) | The starting point of every model. Provides base `string`, `number`, `boolean` and `model` fields. | [![](https://img.shields.io/npm/v/@commodo/fields.svg)](https://www.npmjs.com/package/@commodo/fields) |\n| [@commodo/name](./packages/name) | Assign a name to your models. | [![](https://img.shields.io/npm/v/@commodo/name.svg)](https://www.npmjs.com/package/@commodo/name) |\n| [@commodo/hooks](./packages/hooks) | Provides methods for defining and triggering hooks on your models. | [![](https://img.shields.io/npm/v/@commodo/hooks.svg)](https://www.npmjs.com/package/@commodo/hooks) |\n| [@commodo/fields-storage](./packages/fields-storage) | Enables saving models to a database (with an appropriate driver, e.g. MySQL). | [![](https://img.shields.io/npm/v/@commodo/fields-storage.svg)](https://www.npmjs.com/package/@commodo/fields-storage) |\n\n## Additional packages:\n\n| Package | Short Description | Version |\n| :--- | :---: | :---: |\n| [@commodo/fields-storage-ref](./packages/fields-storage-ref) | Provides `ref` field, for saving references to other models saved in database. | [![](https://img.shields.io/npm/v/@commodo/fields-storage-ref.svg)](https://www.npmjs.com/package/repropose) |\n| [@commodo/fields-storage-mongodb](./packages/fields-storage-mongodb) | A MongoDB driver for @commodo/fields-storage package. | [![](https://img.shields.io/npm/v/@commodo/fields-storage-mongodb.svg)](https://www.npmjs.com/package/repropose) |\n| [@commodo/fields-storage-soft-delete](./packages/fields-storage-soft-delete) | Introduces deleted boolean field to mark whether a model was deleted or not, instead of physically deleting the entry in the storage. | [![](https://img.shields.io/npm/v/@commodo/fields-storage-soft-delete.svg)](https://www.npmjs.com/package/@commodo/fields-storage-soft-delete) |\n\n## Community packages:\n\n| Package | Short Description | Version |\n| :--- | :---: | :---: |\n| [commodo-fields-date](https://github.com/doitadrian/commodo-fields-date) | Provides `date` field, for saving dates. | [![](https://img.shields.io/npm/v/commodo-fields-date.svg)](https://www.npmjs.com/package/commodo-fields-date) |\n| [commodo-fields-object](https://github.com/doitadrian/commodo-fields-object) | Provides `object` field, for saving plain objects. | [![](https://img.shields.io/npm/v/commodo-fields-object.svg)](https://www.npmjs.com/package/commodo-fields-object) |\n| [commodo-fields-int](https://github.com/doitadrian/commodo-fields-int) | Provides `int` field, for saving integer numbers. | [![](https://img.shields.io/npm/v/commodo-fields-int.svg)](https://www.npmjs.com/package/commodo-fields-int) |\n| [commodo-fields-float](https://github.com/doitadrian/commodo-fields-float) | Provides `float` field, for saving float numbers. | [![](https://img.shields.io/npm/v/commodo-fields-float.svg)](https://www.npmjs.com/package/commodo-fields-float) |\n| [commodo-fields-storage-crud-logs](https://github.com/doitadrian/commodo-fields-storage-crud-logs) | Adds and automatically manages `createdOn`, `updatedOn`, `savedOn` fields. | [![](https://img.shields.io/npm/v/commodo-fields-storage-crud-logs.svg)](https://www.npmjs.com/package/commodo-fields-storage-crud-logs) |\n\n## Contributing\nPlease see our [Contributing Guideline](/CONTRIBUTING.md) which explains repo organization, linting, testing, and other steps.\n\n## License\nThis project is licensed under the terms of the [MIT license](/LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebiny%2Fcommodo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebiny%2Fcommodo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebiny%2Fcommodo/lists"}