{"id":25231639,"url":"https://github.com/thinknimble/tn-models","last_synced_at":"2025-06-17T01:03:15.318Z","repository":{"id":42938081,"uuid":"413488186","full_name":"thinknimble/tn-models","owner":"thinknimble","description":"Pure JavaScript library for creating data model and API services to support front end applications.","archived":false,"fork":false,"pushed_at":"2025-02-25T19:32:58.000Z","size":669,"stargazers_count":7,"open_issues_count":4,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-02T00:35:40.955Z","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/thinknimble.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.TXT","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":"2021-10-04T15:50:51.000Z","updated_at":"2025-02-25T19:33:01.000Z","dependencies_parsed_at":"2025-02-11T12:34:07.190Z","dependency_job_id":"e1be48bf-761f-4589-a0e6-04b28e1fb887","html_url":"https://github.com/thinknimble/tn-models","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thinknimble/tn-models","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thinknimble%2Ftn-models","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thinknimble%2Ftn-models/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thinknimble%2Ftn-models/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thinknimble%2Ftn-models/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thinknimble","download_url":"https://codeload.github.com/thinknimble/tn-models/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thinknimble%2Ftn-models/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260269322,"owners_count":22983640,"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":"2025-02-11T12:29:23.846Z","updated_at":"2025-06-17T01:03:15.249Z","avatar_url":"https://github.com/thinknimble.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DEPRECATED: ThinkNimble Models for Client-Side Apps\n\n![No Maintenance Intended](https://img.shields.io/maintenance/no/2024.svg)\n\n## ⚠️ Development of this version of tn-models has been discontinued. See new version here: https://github.com/thinknimble/tn-models-fp\n\n## Installation\n\n```bash\nnpm install @thinknimble/tn-models\n```\n\n### Model Class\n\nThe Model class is the main class that data models are built out of they contain all the logic for a class instance and usually will wrap the api class to provide a full structure for use across the project.\n\nTo define a model simply extend the base Model Class adding in fields as static arguments to the model. Behind the scenes the constructor will pick up properties defined as fields and inject them into the class as internal properties. Only fields defined here will be collected and injected other static methods, getters and properties can be included and will override the defaults if they are already defined.\n\n**_Simple Model_**\n\n```\nclass UserModel extends Model {\n\n    static id = new fields.CharField({readOnly:true})\n    static firstName = new fields.CharField()\n    static lastName = new fields.CharField()\n    static age = new fields.IntegerField()\n}\n\n```\n\n**_Recommended Model_**\n\n```\nclass UserModel extends Model {\n\n    static api = UserAPI.create(UserModel)\n\n    static id = new fields.CharField({readOnly:true})\n    static firstName = new fields.CharField()\n    static lastName = new fields.CharField()\n    static age = new fields.IntegerField()\n}\n\n```\n\nAbove is the recommended structure to follow when creating a model for a service. Injecting the api class directly in your model results in a single datastructure to work with api calls from django. The api mehtod (see bellow) is statically defined from an api class that extends the ModelAPI structure. It has built in methods for common api calls made. To over ride these methods just re-define them\n\n### ModelAPI\n\n**Basic Usage**\n\n```\nClass UserAPI extends ModelAPI{\n\n    static ENDPOINT = '/user/'\n\n    get client(){\n        return \u003caxiosClient\u003e\n    }\n\n}\n\n```\n\nThis is all that is required to set up an api class, the client to use and the static endpoint\n\n**Additional set up**\n\n```\nClass UserAPI extends ModelAPI{\n\n    static ENDPOINT = '/user/'\n\n    // extend additional filters using the ApiFilter class\n\n    static FILTER_MAP = {...UserAPI.FILTER_MAP, organization: ApiFilter.create({key:'organization'})}\n\n    get client(){\n        return \u003caxiosClient\u003e\n    }\n\n    // override existing method retrieve\n\n    retrieve(id){\n        //content\n    }\n\n\n\n}\n\n```\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003eMethod/Property\u003c/th\u003e\n\u003cth\u003efn call\u003c/th\u003e\n\u003cth\u003eArgs\u003c/th\u003e\n\n\u003cth\u003edescription\u003c/th\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003egetFields()\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nthis.constructor.getFields()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003ctd\u003eIterates over static properties and extracts the ones that use the Field Class. This will return a list of fields that can be retrieved directly as properties of the class and stores them in a private property called _fields **Note this method is used internally and should be considered private**\n\u003cbr /\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003egetReadOnlyFields\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nthis.constructor.getReadOnlyFields()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\n\u003ctd\u003eIterates over static properties and extracts the ones that use the Field Class and are defined as readOnly. This will return a list of fields that can be retrieved directly as properties of the class and stores them in a private property called _fields. \n\u003cbr /\u003e\n**Note this method is used internally and should be considered private**\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003efromAPI\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModelClass.fromAPI()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003ejson={}\u003c/td\u003e\n\u003ctd\u003eIterates over provided object and calls the ModelClass.create() method with the objectToCamelCase method applied to it return an instance of the ModelClass. \n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003etoAPI\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModelClass.toAPI()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003eobj,fields=[],excludeFields=[]\u003c/td\u003e\n\u003ctd\u003eIterates over provided object and calls the objectToSnakeCase method, this will also remove the _fields and any readonly or exclude fields, if fields argument is passed will only include specified fields (still removing all readOnly or excluded fields, useful for partial updates. \n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003etoAPI\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModelClass.toAPI()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003eobj,fields=[],excludeFields=[]\u003c/td\u003e\n\u003ctd\u003eIterates over provided object and calls the objectToSnakeCase method, this will also remove the _fields and any readonly or exclude fields, if fields argument is passed will only include specified fields (still removing all readOnly or excluded fields, useful for partial updates. \n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003ecreateCollection\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModelClass.createCollection()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003eopts\u003c/td\u003e\n\u003ctd\u003eHelper method to create a collectionManager instance of a class (instead of manually doing so by importing the CollectionManager) by default the ModelClass is set to this and will override the model class passed in through opts if one is present\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\n\u003c/table\u003e\n\n### ApiFilter Class\n\nThis class creates filters for requests in a consistent structure, to define a new filter add it to the filter maps and declare it with a new ApiFilter class. This filter class will only add filters if there are values and will ommit them by default if they do not. This removes the need to add additional if else checks\\*.\n\n_Note this is a default behavior if you need null as a value you will need to manually define a filter on the method_\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003eMethod/Property\u003c/th\u003e\n\u003cth\u003efn call\u003c/th\u003e\n\u003cth\u003eArgs\u003c/th\u003e\n\n\u003cth\u003edescription\u003c/th\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003estatic create\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModelClass.create()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003ecls\u003c/td\u003e\n\u003ctd\u003eFactory function that creates a wrapper for ModelClass when called from ModelClass (static api = ModelAPI.create(cls))\nMost built in methods require the presence of a class which include the to and from api methods\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003eFILTERS_MAP\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModelAPI.FILTERS_MAPS\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003ctd\u003e\nCreates a filters object, by default page, pageSize and ordering are included using the ApiFilter Class. To add additional opts spread the object static FILTERS_MAP ={...ModelAPI.FILTERS_MAP}\n\u003c/td\u003e\n\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eclient\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nget Client()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\n\u003ctd\u003eThis getter supplies the client to be used for requests and is required if none is provided an error will be thrown\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003elist\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModeClass.api.list()\n\u003cbr /\u003e\nModelAPI.list()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003efilters={}, pagination={}\u003c/td\u003e\n\u003ctd\u003eCalls the list method to the api (if this does not exist this will fail) and calls the fromAPI method from the inheriting class\n\u003cbr /\u003e\n***Note the buil in method requires use of the recommended strucutre and calls this.cls.fromAPI() which refers to the model class \n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003ecreate\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModeClass.api.create()\n\u003cbr /\u003e\nModelAPI.create()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003eobj,fields=[],excludeFields=[]\u003c/td\u003e\n\u003ctd\u003eCalls the create method to the api (if this does not exist this will fail) and calls the fromAPI method from the inheriting class\n\u003cbr /\u003e\n***Note this is different from the static create (factory function)\n***Note the buil in method requires use of the recommended strucutre and calls this.cls.fromAPI() which refers to the model class \n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\u003ctd\u003eretrieve\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nModeClass.api.retrieve()\n\u003cbr /\u003e\nModelAPI.retrieve()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003eid\u003c/td\u003e\n\u003ctd\u003eCalls the retrieve endpoint of a view\n\u003cbr /\u003e\n***Note the buil in method requires use of the recommended strucutre and calls this.cls.fromAPI() which refers to the model class \n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003ctr\u003e\n\n\u003c/table\u003e\n\n### Collection Manager\n\nThe Collection Manager creates a list collection of a model and is included by default as part of the list method in the ModelAPI, this creates a consistent model for listing resources from the api. It includes default handling for pagination and creates a model out of the results.\n\n### Pagination Class\n\nThe pagination class is modeled of the expected django drf paginated queryset but can be easily adpated to work with any (page pagination). This class is automatically applied to the default list method in the ModelAPI class through the collection manager and is applied as filters by default in the FILTER_MAPS\n\n### Fields Class\n\nAll field types extend the base Field class, they inherit the methods clean(value) (which type casts the value if it is not null/undefined) and getDefaultVal(value) which returns the default value provided (also accepts a function)\n\n**Custom Classes can be created on the fly by extending the Field class**\n\n**_NB_** ArrayField requires type to be of class Field and initialized as it calls the clean method (it can also be of any other class interface as long as it has the clean method)\n\n**_NB_** ModelField requires ModelClass to be a (defined) Class (uninitialized) and should use the Model Class but can be any class which calls toAPI\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003efield\u003c/th\u003e\n\u003cth\u003eclass\u003c/th\u003e\n\u003cth\u003eparameters\u003c/th\u003e\n\u003cth\u003edescription\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eCharField\u003c/td\u003e\n\u003ctd\u003e \n\u003ccode\u003e\nnew CharField()\n\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd\u003ereadOnly\u003c/td\u003e\n\u003ctd\u003ecreates a new char field, properties are optional ( defaults: false)\u003c/td\u003e\n\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eIdField\u003c/td\u003e\n\u003ctd\u003e\n\u003ccode\u003e new IdField() \u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003edefaultVal, readOnly\u003c/td\u003e\n\u003ctd\u003ecreates a new id field, properties are optional ( defaults: random generated id, false)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eBooleanField\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003enew BooleanField()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003edefaultVal, readOnly\u003c/td\u003e\n\u003ctd\u003ecreates a new Boolean field, properties are optional \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eIntegerField\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003enew IntegerField()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003edefaultVal, readOnly\u003c/td\u003e\n\u003ctd\u003ecreates a new Integer field (accepts floats as well), properties are optional\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eArrayField\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e new ArrayField({type: new IntegerField()})\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003edefaultVal, readOnly, type*\u003c/td\u003e\n\u003ctd\u003ecreates a new Array field, properties defaultVal and readOnly are optional ( defaults: null, false) type is required and must be a initiated Field Class (new IntegerField() ) type \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eModelField\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003enew ModelField({ModelClass: SomeTnModel })\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003edefaultVal, readOnly, many, ModelClass*\u003c/td\u003e\n\u003ctd\u003ecreates a new Model field, properties defaultVal and readOnly are optional ( defaults: null, false, false) Model Class is required and must Class Tpye (Not a class Insance), many here will map and call the fromAPI method \u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthinknimble%2Ftn-models","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthinknimble%2Ftn-models","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthinknimble%2Ftn-models/lists"}