{"id":16844813,"url":"https://github.com/stephanhoyer/modelz","last_synced_at":"2025-08-26T09:14:41.109Z","repository":{"id":22317257,"uuid":"25652523","full_name":"StephanHoyer/modelz","owner":"StephanHoyer","description":"Simple model scheme helper","archived":false,"fork":false,"pushed_at":"2024-04-12T11:30:22.000Z","size":431,"stargazers_count":4,"open_issues_count":13,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-13T17:52:13.695Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/StephanHoyer.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2014-10-23T18:46:00.000Z","updated_at":"2024-04-15T10:41:15.650Z","dependencies_parsed_at":"2024-02-15T07:33:09.134Z","dependency_job_id":"b3d405b2-c09a-4f71-8f36-0a20875620d1","html_url":"https://github.com/StephanHoyer/modelz","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StephanHoyer%2Fmodelz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StephanHoyer%2Fmodelz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StephanHoyer%2Fmodelz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StephanHoyer%2Fmodelz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StephanHoyer","download_url":"https://codeload.github.com/StephanHoyer/modelz/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244912800,"owners_count":20530764,"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":[],"created_at":"2024-10-13T12:56:44.106Z","updated_at":"2025-08-26T09:14:41.090Z","avatar_url":"https://github.com/StephanHoyer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build status](https://github.com/StephanHoyer/modelz/actions/workflows/node.js.yml/badge.svg)](https://github.com/StephanHoyer/modelz/actions/workflows/node.js.yml)\n[![rethink.js](https://img.shields.io/badge/rethink-js-yellow.svg)](https://github.com/rethinkjs/manifest)\n![](http://img.badgesize.io/StephanHoyer/modelz/master/modelz.js.svg?compression=brotli)\n\n# modelz\n\nSimple model schema helper\n\nWith _modelz_, we try to build a `backbone/ampersand`-Model in a new way. No prototypes involved here.\n\nCurrently it's a minimal approach to have properties with getter/setter, automatic children construction and change-events.\n\n## how to install?\n\n```shell\nnpm install modelz\n```\n\n## how to use?\n\n```javascript\n// load function and set global config for it\nimport models from 'modelz'\n\nconst Schema = models() // \u003c-- potential global module config goes here\n\nconst dogSchema = Schema({\n  breed: breedModel,\n  name: ['string', true],\n  color: color,\n  friends: [dogModel],\n})\n```\n\nThis creates a Schema for a model `dogModel`. `dogModel` then will have four properties.\n\nTo create the model simply do:\n\n```javascript\nfunction dogModel(dog) {\n  dog = dogSchema(dog)\n\n  dog.bark = function () {\n    console.log(dog.name + ' barks!')\n  }\n\n  return dog\n}\n```\n\nand then create an instance with:\n\n```javascript\nconst lassie = dogModel({\n  name: 'Lassie',\n  breed: { name: 'Collie' },\n  color: 'pied',\n  friends: [{ name: 'Tommy' }],\n})\n\nlassie.bark() // console.logs 'Lassie barks!'\n```\n\n## So how does this help me?\n\n- It validates the input data\n- It sets defaults if given\n- It constructs sub-models (breed)\n- It removes data that is not specified in schema\n- It allows for (cacheable) computed properties\n\n## detail usage\n\n### defining properties\n\n```javascript\nimport models from 'modelz'\n\nconst Schema = models()\n\nconst dogSchema = Schema({\n  name: ['string', true], //property definition\n})\n```\n\nThere a different ways to define a property:\n\n#### type as string\n\nExample: `name: 'string'`\n\nProperty is optional and has no default value. Types can be\n\n- `string`\n- `number`\n- `date`\n\n#### Array without default\n\nExample: `name: ['string', true]`\n\nProperty is a string, required and has no default value. This is also possible\nwith constructor function.\n\n#### Array with default\n\nExample: `name: ['string', true, 'no name']`\n\nProperty is a string, required and has `'no name'` as default value. This is\nalso possible with constructor function.\n\n#### default single value\n\nExample: `name: 'no name'`\n\nProperty is a string, required and has `'no name'` as default value. This is\nonly possible with primitive types (`string`, `number`, `date`).\n\n#### detailed description via object\n\nExample: `name: { type: 'string', required: true, default: 'no name' }`\n\nPossible config properties are\n\n##### type\n\nCan be `string`, `number` or `date`\n\n##### construct\n\nInit function that is called, with the given value as parameter. The return-value it then set as the value of this field\n\n##### get\n\nFunction that gets called when you access the property, it gets the instance as only parameter. The return-value is then return as value of the field.\nSee `computed properties`\n\n##### set\n\nFunction that gets called when you set the property, it gets the new value as only parameter. See `computed properties`\n\n##### cacheKey\n\nThis can either be a function or a list of property names.\n\nIf a function is set it gets called when accessing the property before the `get`-function itself is called. If this returns the same value for subsequent accesses to the property, the same value is returned without calling `get`-function itself again.\n\nIf this is a list of property names, the sting-representations of those properties is used as the cache key.\n\n##### enumerable\n\nDefines if this property is serialized or not\n\n##### required\n\nDefines if this property is required or not\n\n##### default\n\nDefines the default value if no initial value for the property is given. This can be either a value or a callback function. If it's a function and no initial value was giving during construct the `default`-callback is called with the initial values of the instance as parameter.\n\n### init-Hooks\n\nExample:\n\n```javascript\nconst userSchema = Schema({\n  // fields definition\n}, {\n  preInit: function(user) {\n    // do some stuff before getter/setter are applied\n    user.onChange = new Signal();\n    return user; // always return the instance!!\n  },\n  postInit: function(user) {\n    // do some stuff after getter/setter are applied\n    return user; // always return the instance!!\n  }\n}\n```\n\nThis can be used to e. G. add a change listeners to all instances upon\nconstruction (see `test.js`).\n\n### onChangeListener-Hook\n\n```javascript\nconst userSchema = Schema(\n  {\n    // fields definition\n  },\n  {\n    onChangeListener: function (user) {\n      return user.onChange.dispatch\n    },\n  }\n)\n```\n\nThe listener should return a function that will be called, when an attribute on\nthe instance changes for whatever reason. The signature of this function is\n\n```javascript\nfunction(attributeKey, newValue, oldValue) {\n  // do, what's required to do here.\n}\n```\n\nsee `test.js`\n\n### children models\n\nExample: `user: createUser`\n\nProperty is an object. All data that is passed under the users key on\ninitialization is passed to the `createUser` function. The result is returned\nand stored at the key `user` of the instance.\n\n### computed properties\n\n```javascript\nconst schema = Schema({\n  a: 'string',\n  b: 'string',\n  ab: {\n    get: function (testObj) {\n      return testObj.a + '|' + testObj.b\n    },\n    set: function (testObj, value) {\n      value = value.split('|')\n      testObj.a = value[0]\n      testObj.b = value[1]\n    },\n  },\n})\n\nconst test = schema({\n  a: 'foo',\n  b: 'bar',\n})\n\nassert(test.ab, 'foo|bar')\n```\n\nComputed properties can be cached too. There are two possibilities:\n\n- Define the properties the cached prop depends on (see `ab`)\n- or roll your own (see `x`)\n\n```javascript\nconst schema = Schema({\n  a: 'string',\n  b: 'string',\n  ab: {\n    get: function (testObj) {\n      return testObj.a + '|' + testObj.b\n    },\n    cacheKey: ['a', 'b'],\n  },\n  x: {\n    get: function (testObj) {\n      return heavyComputationToGetX(testObj)\n    },\n    cacheKey: function getCacheKey(testObj) {\n      return someSimplerFunctionToComputeCacheKey(testObj)\n    },\n  },\n})\n```\n\n### parse/format\n\nWith those two config values you can interfere the getting and setting of a normal prop. `parse` is called on setting the prop,\nit must be a function that returns the final value to set. The result of `format`-fn is return when getting a value.\nBoth get the value as first argument, the obj as second argument and the field-config as the third argument.\n\n```javascript\nconst model = Schema({\n  a: {\n    type: 'string',\n    format: (value) =\u003e `get(${value})`,\n    parse: (value, obj) =\u003e `set(${value}) objX(${obj.x})`,\n  },\n  x: 'string',\n})\nconst testObj = model({ a: 'a', x: 'x' })\n\n// initial set of a where x is not set yet\ntestObj.a // 'get(set(a) objX(undefined))'\n\ntestObj.a = 'b'\ntestObj.a // 'get(set(b) objX(x))')\n```\n\n## Road map\n\nRefer to the issues.\n\n```\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephanhoyer%2Fmodelz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstephanhoyer%2Fmodelz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephanhoyer%2Fmodelz/lists"}