{"id":40961020,"url":"https://github.com/koldy/model","last_synced_at":"2026-01-22T05:43:29.468Z","repository":{"id":42849691,"uuid":"261892225","full_name":"koldy/model","owner":"koldy","description":"Koldy Model ensures strict data types in JS runtime.","archived":false,"fork":false,"pushed_at":"2025-10-21T23:09:19.000Z","size":2033,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-01T09:06:09.331Z","etag":null,"topics":["data-model","data-modelling","javascript","javascript-modelling","js-type"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/koldy.png","metadata":{"files":{"readme":"readme.md","changelog":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-05-06T22:26:23.000Z","updated_at":"2025-10-21T23:09:23.000Z","dependencies_parsed_at":"2024-03-11T21:34:43.366Z","dependency_job_id":"dec0b00b-f273-4e3e-9d7f-3dc31db16e56","html_url":"https://github.com/koldy/model","commit_stats":{"total_commits":26,"total_committers":2,"mean_commits":13.0,"dds":"0.34615384615384615","last_synced_commit":"d9fae66da51b0777c25654db2c177838e26ff821"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/koldy/model","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldy%2Fmodel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldy%2Fmodel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldy%2Fmodel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldy%2Fmodel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/koldy","download_url":"https://codeload.github.com/koldy/model/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koldy%2Fmodel/sbom","scorecard":{"id":566308,"data":{"date":"2025-08-11","repo":{"name":"github.com/koldy/model","commit":"9b6597997e9f599365c7b45d65518f59e15a4f3d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 11 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-xffm-g5w8-qvg7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T15:04:07.731Z","repository_id":42849691,"created_at":"2025-08-20T15:04:07.731Z","updated_at":"2025-08-20T15:04:07.731Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28656569,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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":["data-model","data-modelling","javascript","javascript-modelling","js-type"],"created_at":"2026-01-22T05:43:29.410Z","updated_at":"2026-01-22T05:43:29.462Z","avatar_url":"https://github.com/koldy.png","language":"JavaScript","readme":"# Koldy Model\n\nKoldy Model ensures correct and strict structure of Javascript object instances in runtime so you don't have to worry any more\ndoes it exist in data structure, is it a string or number, is it integer or float, is it undefined, null or something useful.\nIf you want to avoid errors such as `Uncaught TypeError: Cannot read property 'address' of undefined`, then you're in the right place.\n\nIt works best with ES6 classes and it supports data structures (objects called Models) and lists (arrays) of these data structures.\n\nIt can be used to \"parse\" JSON responses by initializing correct data structures, collect input from forms\nand still keep the correct data types or to ensure that you send correct JSON structure to your backend.\nIt is specially useful when you're dealing with a lot of different data structures that needs to be reused on a large-scale\nsingle page app.\n\nAll instances of `Model` and `List` are mutable, so to change the reference to initialized Model or List, simply call `clone()`\nmethod.\n\n## Installation\n\n```shell script\nnpm install koldy-model\nyarn add koldy-model\n```\n\n## Example (ES6)\n\n```ecmascript 6\nimport {Model, IntegerType, StringType} from 'koldy-model';\n\nclass User extends Model {\n  definition() {\n    return {\n      id: new IntegerType(),\n      firstName: new StringType(),\n      lastName: new StringType()\n    };\n  }\n}\n\nconst user = User.create();\nconsole.log(user instanceof User); // true\n\nuser.id = 5; // works\nuser.id = 'a'; // throws TypeError\nuser.id = '5'; // works, casts '5' to number 5\n\nuser.firstName = undefined;\nconsole.log(user.firstName); // null\n\nuser.age = 21; // throws TypeError telling that \"age\" is not defined and therefore can't be used\nconsole.log(user.fullName); // throws TypeError that fullName is not defined and can't be used because type is not defined\n```\n\n## Models\n\nModels are instances that behave the same as Javascript object. When defining a model, you should always return an object where every property of returned\nobject is instance of type or another Model or List.\n\nOnce initialized, you may use the following methods:\n\n- `displayName(): string` // returns name of the class - you can override this if needed\n- `getData(): object` // returns \"raw\" data from the instance\n- `setData(data: object): void` // sets new data in the instance\n- `toJSON(): object` // returns an object prepared for JSON serialization\n- `get(name: string): any` // gets the value of property\n- `set(name: string, value: any): void` // sets the value to the property\n- `keys(): array` // returns array of all keys defined in definition() method\n- `values(): array` // returns array of all values in instance as array (it's using getData() to get the array)\n- `hasProperty(name: string): boolean` // true if property with a name exists in the instance\n- `seal(): void` // seals the object instance\n- `isSealed(): boolean` // returns true if object is sealed\n- `freeze(): void` // freezes the object instance\n- `isFrozen(): boolean` // returns true if object is frozen\n- `clone(): new instance` // returns new instance with the same data\n\n## Anonymous models\n\nSometimes, you may not want to define the class Model. Usual use case for this are objects that are being used in just one place.\nTherefore, you may create the object by passing the definition as the second argument.\n\n```ecmascript 6\nconst user = Model.create({}, {\n  firstName: new StringType(),\n  age: new IntegerType(18)\n});\n\nconsole.log(user.firstName); // null\nconsole.log(user.age); // 18\n```\n\n## Model Nesting\n\nYou may go with the object structure as \"deep\" as you want. Here's an example:\n\n```ecmascript 6\nclass Driver extends Model {\n\tdefinition() {\n\t\treturn {\n\t\t\tfirstName: new StringType(),\n\t\t\tage: new IntegerType(),\n\t\t\taddress: {\n\t\t\t\tstreet: new StringType(),\n\t\t\t\tpostCode: new StringType(10000)\n\t\t\t}\n\t\t};\n\t}\n}\n\nclass Vehicle extends Model {\n\tdefinition() {\n\t\treturn {\n\t\t\tname: new StringType(),\n\t\t\twheels: new IntegerType(),\n\t\t\tdriver: Driver\n\t\t};\n\t}\n}\n\nconst car = Vehicle.create();\n\nconsole.log(car.driver.address.postCode); // returns string \"10000\"\nconsole.log(car.driver instanceof Driver); // returns true\n```\n\nIf you want to put another Model in model's definition, note that there's no `new` keyword.\n\n## Features in all types\n\n### Default value\n\nAll type constructors accept default value in its constructor.\n\n```ecmascript 6\nclass Car extends Model {\n    definition() {\n        return {\n            brand: new StringType('Acura'),\n            miles: new IntegerType(3),\n            isNew: new BooleanType(true),\n            features: new ArrayType(['aircon', 'entertainment software'])\n        };\n    }\n}\n\nconst car = Car.create();\nconsole.log(car.brand); // returns \"Acura\"\nconsole.log(car.miles); // returns 3\nconsole.log(car.isNew); // returns true\nconsole.log(car.features); // returns ['aircon', 'entertainment software']\n```\n\nYou may define a function for default value that will execute every time when lib requests for default value. In that case,\nthe function must return a valid value for that type where it's being used.\n\n```ecmascript 6\nclass Car extends Model {\n    definition() {\n        return {\n            brand: new StringType(() =\u003e 'Acura'),\n            miles: new IntegerType(() =\u003e 3),\n            isNew: new BooleanType(() =\u003e true),\n            features: new ArrayType(() =\u003e ['aircon', 'entertainment software'])\n        };\n    }\n}\n\nconst car = Car.create();\nconsole.log(car.brand); // returns \"Acura\"\nconsole.log(car.miles); // returns 3\nconsole.log(car.isNew); // returns true\nconsole.log(car.features); // returns ['aircon', 'entertainment software']\n```\n\n### Nullable / Not Nullable\n\nWhen some value is not set (in Javascript, set to `undefined`), Koldy Model will automatically set default value to `null`,\nbut sometimes, you don't want your properties to be nullable. In that case, simply call `notNull()` in definition chain and\nproperty will reject all null values. Remember that if you don't set default value and put `notNull()`, constructing model\nwithout not-null value will result in error.\n\n```ecmascript 6\nclass Car extends Model {\n    definition() {\n        return {\n            brand: new StringType().notNull()\n        };\n    }\n}\n\nconst car1 = Car.create(); // fails, because brand should be not-null\nconst car2 = Car.create({brand: 'Acura'}); // ok, because brand is not-null\n```\n\n### Custom validator\n\nAll types can be even more restrictive by setting your own data validator.\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            age: new IntegerType().notNull().withCustomValidator(function ({value}) {\n              if (value \u003e= 18 \u0026\u0026 value \u003c= 21) {\n                throw new TypeError('Age should be between 18 and 21');\n              }\n            })\n        };\n    }\n}\n\nconst user = User.create({age: 17}); // fails because of custom validator\n```\n\nIn the example above, we pass function to `withCustomValidator` that accepts object as argument. That object contains:\n\n- `value` - value that should be validated\n- `originalValue` - value that was actually given to the property (in case when original value is undefined, then default value will be given for value, while `undefined` will be given for original value)\n- `name` - the name of property\n- `target` - the instance of type\n\nIn the example above, since `notNull()` is used, you'll never get `null` for the value in custom validator.\n\n### Custom getter\n\nAll types can transform their output when requested through the getter. If set, getter function will be called on every\nrequest for the value of the property. Getter method can return anything and it doesn't need to be the same type as the\nproperty is defined - library won't check that, but we recommend that you keep the same or at least compatible type returned\nfrom the getter.\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            age: new IntegerType().notNull().withCustomGetter(function ({value}) {\n              if (value \u003e= 18 \u0026\u0026 value \u003c= 21) {\n                return -1;\n              }\n            })\n        };\n    }\n}\n\nconst user = User.create({age: 20});\nconsole.log(user.age); // returns -1\n```\n\nIn the example above, we pass function to `withCustomGetter` that accepts object as argument. That object contains:\n\n- `value` - that value that would be originally returned if there was no custom getter\n- `name` - the name of property\n- `target` - the instance of type\n\n---\n\n## Data Types\n\nAll methods listed in Types API are chainable.\n\n### AnyType\n\n`new AnyType(defaultValue?: any | function)` accepts anything for the value.\n\n- `notNull()` - makes value not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: any|null` - a value that should be validated\n        - `originalValue: any|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: any|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            age: new AnyType() // defines \"age\" property to be anything\n        };\n    }\n}\n\nconst user = User.create();\n\nuser.age = 5; // ok\nuser.age = 'above 18'; // ok\nuser.age = true; // ok'\n```\n\n### ArrayType\n\n`new ArrayType(defaultValue?: array|function)` accepts array.\n\n- `notNull()` - makes this property not-nullable - it always has to be an array\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: array|null` - a value that should be validated\n        - `originalValue: array|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: array|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            names: new ArrayType().notNull()\n        };\n    }\n}\n\nconst user = User.create();\n\nuser.names = ['First', 'Middle', 'Last']; // ok\nuser.names = null; // throws TypeError\n```\n\n### BooleanType\n\n`new BooleanType(defaultValue?: boolean|function)` accepts boolean.\n\n- `notNull()` - makes this property not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: boolean|null` - a value that should be validated\n        - `originalValue: boolean|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: boolean|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            isActive: new BooleanType().notNull()\n        };\n    }\n}\n```\n\n### DateType\n\n`new DateType(defaultValue?: Date|string|function)` accepts instance of `Date` or string. Anything you pass as a string will be accepted.\nHowever, after getting a property of this type, your string will be parsed using `Date.parse()` which could fail. Koldy Model relies\nentirely on browser's Date implementation, which could be different from browser to browser. \n\n- `notNull()` - makes this property not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: Date|string|null` - a value that should be validated\n        - `originalValue: Date|string|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n\n### FloatType\n\n`new FloatType(defaultValue?: number|function)` accepts numbers with decimals. Any string passed to this property\nwill be casted to number. Be aware that parsing can fail.\n\n- `notNull()` - makes this property not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: number|null` - a value that should be validated\n        - `originalValue: number|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `decimals(x: number)` - constraints the float type to this number of decimals; if you pass a number with more decimals, it will be cut off (not rounded)\n- `min(x: number)` - the minimum number accepted for this property\n- `max(x: number)` - the maximum number accepted for this property\n- `between(x: number, y: number)` - shorthand for combination of `min()` and `max()`\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: number|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            age: new FloatType()\n                .notNull()\n                .decimals(2)\n                .min(18.5)\n                .max(99.5)\n                .between(18.5, 99.5)\n        };\n    }\n}\n```\n\n### IntegerType\n\n`new IntegerType(defaultValue?: number|function)` accepts only integers. Any string passed to this property\nwill be casted to integer. If you pass a number with decimals, decimals will be cut off (integer won't be rounded).\n\n- `notNull()` - makes this property not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: number|null` - a value that should be validated\n        - `originalValue: number|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `min(x: number)` - the minimum number accepted for this property\n- `max(x: number)` - the maximum number accepted for this property\n- `between(x: number, y: number)` - shorthand for combination of `min()` and `max()`\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: number|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            age: new IntegerType()\n                .notNull()\n                .min(18)\n                .max(99)\n                .between(18, 99)\n        };\n    }\n}\n\nUser.create({age: 100}); // throws TypeError because 99 is the max allowed value\n```\n\n### ObjectType\n\n`new ObjectType(defaultValue?: object|function)` accepts JS objects.\n\n- `notNull()` - makes this property not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: object|null` - a value that should be validated\n        - `originalValue: object|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: object|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            address: new ObjectType().notNull()\n        };\n    }\n}\n\nconst user = User.create();\n\nuser.address = {\n  street: 'Big street',\n  number: 5\n}; // ok\n\nuser.address = null; // throws TypeError\n```\n\n### StringType\n\n`new StringType(defaultValue?: string|function)` accepts strings. If you pass a number, it'll be converted to string immediately.\n\nIf string property is set to be not null, then values like `undefined` or `null` will be always casted to empty string.\nIn other case, if property is nullable, then values like `undefined` and `null` will be `null`. Empty string value will\nbe converted to `null` as well.\n\n- `notNull()` - makes this property not-nullable\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: string|null` - a value that should be validated\n        - `originalValue: string|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called\n    - function gets object for first parameter with keys:\n        - `value: string|null` - a value that could be inspected\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n    - function can and should return something (anything)\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            firstName: new StringType().notNull()\n        };\n    }\n}\n\nconst user = User.create();\n\nuser.firstName = 'Vlatko'; // ok\nuser.firstName = 55; // ok, but converted to string \"55\"\n```\n\n### ConstantType\n\n`new ConstantType(defaultValue: string|number|object|boolean|null|function)` - note that default value is mandatory on this type and it can be almost anything. Setting a value will check the value with strict type and that rule also applies for comparing objects.\n\n- `withCustomValidator(fn: function)` - validates value after all internal checks\n    - function gets object for first parameter with keys:\n        - `value: string|number|object|boolean|null` - a value that should be validated\n        - `originalValue: string|number|object|boolean|null` - original value passed to setter - it could be different than value if not-null or defaultValue were applied on `value`\n        - `name: string` - name of the property\n        - `target: object` - the instance of object on which the setter function was called\n- `withCustomGetter(fn: function)` - optionally transforms value when getter is called - return value will not be checked against the constant\n\nExample:\n\n```ecmascript 6\nclass User extends Model {\n    definition() {\n        return {\n            role: new ConstantType('admin')\n        };\n    }\n}\n\nconst user = User.create();\n\nuser.role = 'admin'; // ok\nuser.role = 'user'; // throws TypeError\n```\n\nIf using Typescript, you can define a type of your constant:\n\n```typescript\nclass User extends Model {\n    definition() {\n        return {\n            role: new ConstantType\u003c'user'\u003e('user')\n        };\n    }\n}\n```\n\n---\n\n## Lists\n\nLists are nothing else than array of one type or array of initialized Model instances.\n\nTo have an array of string-only elements, you may do:\n\n```ecmascript 6\nclass Names extends List {\n  definition() {\n    return new StringType().notNull();\n  }\n}\n\nconst names = Names.create();\nnames.push('Vlatko'); // ok\nnames.push(null); // throws TypeError, not accepting null because type is not nullable\nnames[0] = 'John'; // ok\nnames[0] = null; // throws TypeError, not accepting null because type is not nullable\n```\n\nIf want to have an array of, let's say, users, then you may do it like this:\n\n```ecmascript 6\nclass User extends Model {\n  definition() {\n    return {\n      firstName: new StringType(),\n      age: new IntegerType(18)\n    };\n  }\n}\n\nclass Users extends List {\n  definition() {\n    return User;\n  }\n}\n\nconst users = Users.create();\n\nusers.push({firstName: 'Vlatko'}); // ok\nconsole.log(users.length); // returns 1\nconsole.log(users[0].firstName); // 'Vlatko'\nconsole.log(users[0].age); // returns 18 because users[0] is instance of User and \"age\" property has default value of 18\nconsole.log(users[0] instanceof User); // true\n\n// you can add an instance of User\nconst a = User.create({firstName: 'John', age: 30});\nusers.push(a); // ok\nconsole.log(users[1].age); // 30\n\nconst b = User.create({firstName: 'Sue', age: 22, address: 'Other road'});\nusers.push(b); // ok\nconsole.log(b[2].address); // throws an error because address is not defined in User model\n\nusers[1].age = []; // throws TypeError because \"age\" should be integer, not array\n```\n\nOnce initialized, you may use the following methods:\n\n- `toArray(): array` // returns array of all elements in the instance of List\n- `getData(): array` // same as `toArray()`\n- `toJSON(): array` // same as `getData()`, but will be automatically used if object is JSON serialized\n- `setData(data: array): void` // sets new array of elements as its data\n- `get(index: number): any` // gets the element from requested position in List\n- `set(index: number, value: any): void` // sets the element on targeted position in List\n- `reset(): void` // removes all elements from the List\n- `count(): number` // returns how many elements instance of List has; it's same as using the `.length` property on the instance\n- `clone(): new instance` // returns new instance of List with the same data (be aware that data is not \"deep cloned\")\n- `forEvery(n: number, fn: function, thisArg: obj): void` // iterates through array every Nth element\n- `mapEvery(n: number, fn: function, thisArg: obj): array` // same as Array.map, just goes for every Nth element \n\nAll other methods are standard Javascript methods you may use on the instance of List:\n\n- [entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries)\n- [every](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every)\n- [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)\n- [find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)\n- [findIndex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex)\n- [forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)\n- [includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)\n- [indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)\n- [join](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join)\n- [keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/keys)\n- [lastIndexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf)\n- [map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\n- [pop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop)\n- [push](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push)\n- [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)\n- [reduceRight](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight)\n- [reverse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)\n- [shift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)\n- [slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)\n- [some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)\n- [sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)\n- [splice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)\n- [toLocaleString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toLocaleString)\n- [toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString)\n- [unshift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)\n- [values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values)\n\n\n### Anonymous lists\n\nSometimes, you may not want to define the list of Models or types \"in the fly\". Check an example:\n\n```ecmascript 6\nconst list = List.create([], new BooleanType());\nlist.push(false);\nlist.push(true);\nconsole.log(list[1]); // returns true\n```\n\n## TypeScript\n\nThe TypeScript support is added from `1.2.0`. To define types in your models, do the following:\n\n```typescript\nclass User extends Model {\n    firstName: string;\n\t\n    definition() {\n        return {\n            firstName: new StringType().notNull()\n        };\n    }\n}\n```\n\nSince there's a limitation on TypeScript when creating a self-instanced models through static methods in class which prevents\nTypeScript from automatically detecting a correct type, you have to pass a User type to `create()` method yourself each time\nif you want to validate what's coming in:\n\n```typescript\nconst user = User.create\u003cUser\u003e({\n  firstName: 'Vlatko'\n});\n```\n\nTo use a list of models with TypeScript, you have to define a list like this:\n\n```typescript\nclass Users extends List\u003cUser\u003e {\n    definition() {\n        return User;\n    }\n}\n```\n\nThen, to create a new list of users, you'll have to pass both types to create method like this:\n\n```typescript\nconst users = Users.create\u003cUsers, User\u003e([\n\t{firstName: 'Vlatko'}\n]);\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoldy%2Fmodel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkoldy%2Fmodel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoldy%2Fmodel/lists"}