{"id":24247111,"url":"https://github.com/manifestwebdesign/dabl-js","last_synced_at":"2025-09-02T23:33:30.527Z","repository":{"id":1712570,"uuid":"2442182","full_name":"ManifestWebDesign/DABL-JS","owner":"ManifestWebDesign","description":"JavaScript ORM","archived":false,"fork":false,"pushed_at":"2017-05-25T05:59:42.000Z","size":1541,"stargazers_count":4,"open_issues_count":6,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-10T15:35:00.989Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/ManifestWebDesign.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}},"created_at":"2011-09-23T05:39:09.000Z","updated_at":"2023-10-18T15:17:14.000Z","dependencies_parsed_at":"2022-08-22T22:31:17.012Z","dependency_job_id":null,"html_url":"https://github.com/ManifestWebDesign/DABL-JS","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2FDABL-JS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2FDABL-JS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2FDABL-JS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ManifestWebDesign%2FDABL-JS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ManifestWebDesign","download_url":"https://codeload.github.com/ManifestWebDesign/DABL-JS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233971464,"owners_count":18759223,"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-01-14T23:18:13.804Z","updated_at":"2025-01-14T23:18:14.565Z","avatar_url":"https://github.com/ManifestWebDesign.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"DABL-JS\n=======\n\nDABL JS is a JavaScript ORM inspired by the likes of:\n* JayData (http://jaydata.org/)\n* Breeze (http://breezejs.com/)\n* Persistence.js (https://github.com/coresmart/persistencejs)\n* Angular Resource (https://docs.angularjs.org/api/ngResource/service/$resource)\n\nThe primary goals of DABL JS are:\n* To create a generic interface/ORM for JavaScript models\n* Keep a smaller codebase than JayData and Breeze\n* Run on older browsers, such as IE 8, unlike Persistence.js and others\n* Avoid getter and setter methods for records, for compatibility with frameworks like Angular JS\n* Provide the same routing templates, but features that Angular Resource does not, such as:\n\t* Model subclassing\n\t* Promises\n\t* \"Strong\" Field data types\n\t* Foreign keys\n\t* Adapters for CRUD that aren't necessarily HTTP REST, such as SQLite databases\n* Work as a standalone ORM or integrate with frameworks Angular JS, tying into the Angular scope lifecycle\n\n## Installation\n```\nbower install dabl\n```\n\nor\n\n```\ngit clone git@github.com:ManifestWebDesign/DABL-JS.git\n```\n\n## Usage\nInclude the DABL base and any adapters required for your project:\n\n```html\n\u003cscript src=\"js/dabl.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"js/dabl.adapter.rest.min.js\"\u003e\u003c/script\u003e \u003c!-- AngularRESTAdapter --\u003e\n\u003cscript src=\"js/dabl.adapter.rest.angular.min.js\"\u003e\u003c/script\u003e \u003c!-- AngularRESTAdapter extends RESTAdapter --\u003e\n```\n\n\n## Defining a Model\n```javascript\nvar MyClass = dabl.Model.extend('MyClass', {\n\tadapter: adapter,\n\turl: 'my-class-records/:id.json',\n\tfields: {\n\t\tid: { type: 'int', key: true, computed: true }, // primary key\n\t\tmoneys: Number, // number\n\t\totherModel: OtherModel, // instance of another model class\n\t\tlistOfModels: { type: Array, elementType: OtherModel }, // if you use instance.listOfModels.push({ }), the object will be cast to an instance of OtherModel\n\t\tlistOfDates: { type: Array, elementType: Date },\n\t\tlist: Array, // generic array with no type specified\n\t\thash: Object, // Object in memory and an Object when saved\n\t\tjsonString: JSON, // Object in memory, but a JSON string when saved\n\t\tcreated: Date // Date in memory, ISO string like 2014-07-11T06:23:28.894Z when saved\n\t},\n\tprototype: {\n\t\tinit: function(){}, // optional override of constructor.  Call this._super() to call parent constructor,\n\t\tcustomMethod: function(){} // any other methods you want...\n\t}\n});\n```\n\n\n## Model Instance Methods\n\n* `init(values)` - Constructor with object hash of field values\n* `toString()`\n* `copy()` - Returns a new instance with the same values, minus the primary keys\n* `isModified()` - Returns true if any field values have been modified\n* `isModified(field)` - Returns true if the given field has been modified\n* `getModified()` - Returns a hash of modified field names, keyed by the field names with the value true.\n* `resetModified()` - Consider the current state to be unmodified\n* `revert()` - Revert all field values to the last known saved state\n* `fromJSON(values)` - Update this object with the values\n* `toJSON()` - Returns a plain object with the object's values\n* `hasKeyValues()` - Returns true if all primary key fields are not null\n* `getKeyValues()` - Returns a hash of key field names and their values\n* `isNew()` - Returns true if this object has not been saved\n* `setNew()` - Consider this object new\n* `validate()` - Returns true if all required fields have a truthy value\n* `getValidationErrors()` - Returns an array of the validation errors from the last validation run\n* `save()` - Save this object to the adapter's datasource.  Returns a promise.\n* `remove()` - Delete this object from the adapter's datasource.  Returns a promise.\n\n\n## Model Class Methods\n\n* `isFieldType(type)` - Returns true if `type` is a valid field type.\n* `isTemporalType(type)` - Returns true if `type` is a time based type: Date or 'TIME'\n* `isTextType(type)` - Returns true if `type` is a text based type: String or 'TEXT'\n* `isNumericType(type)` - Returns true if `type` is a numeric type: Number or 'int'\n* `isIntegerType(type)` - Returns true if `type` is an integer type: 'int'\n* `isObjectType(type)` - Returns true if `type` is an object of some sort: JSON, Array, Object or a function (assumed to be a constructor)\n* `coerceValue(value, field)` - Attempts to \"cast\" or convert the given `value` to the field type specified in `field`.\n* `coerceValues(values)` - Takes an object of `values`, keyed by field name, and attemps to coerce the values to the field types.\n* `convertArray(values, elementType)` - Takes an array of `values` and attemps to convert them to the given `elementType`.\n* `getAdapter()` - Returns the adapter that is used for actions like find, remove, save, etc.\n* `setAdapter(adapter)` - Sets the adapter that is used for actions like find, remove, save, etc.\n* `inflate(object)` - Converts a normal `object` into an instance of this class and returns that new isntance.\n* `inflateArray(array)` - Inflates the values of `array` in place, unless `array` is not an instanceof Array.  If it is not, then a new Array will be created and populated with the values of `array`.\n* `getTableName()` - Get the \"table\" name of this class' dataset.\n* `getFields()` - Returns a hash of this class' field definitions, keyed by field name.\n* `getField(fieldName)` - Returns the field definition for the given `fieldName`.\n* `getFieldType(fieldName)` - Returns the type part of the field definition for the given `fieldName`.\n* `hasField(fieldName)` - Returns true if a field definition exists for the given `fieldName`.\n* `getKeys()` - Returns an Array of field names that are primary keys.\n* `addField(fieldName, field)` - Adds a `field` definition for the given `fieldName`.  `field` may be just a type like `Date` or an object like `{ type: 'int', key: true, computed: true, required: true }`.\n* `extend(table, options)` - Creates a subclass of this.  `table` is the table/dataset name.  `options` is a model definition (see the defining a model section above).\n* `toString()` - Retuns the table/dataset name.\n* `countAll([query arguments])` - Returns a count of the objects that match the given query.  This call is passed through to the adapter.\n* `findAll([query arguments])` - Returns an Array of objects that match the given query.  This call is passed through to the adapter.\n* `removeAll([query arguments])` - Removes the objects that match the given query.  This call is passed through to the adapter.\n* `find([query arguments])` - Returns a single object that matches the given query.  This call is passed through to the adapter.\n* `findBy(fieldName, value)` - Alias of find, indended to be a key value lookup.\n\n\n## Angular App Example\n\n```javascript\n\nangular.module('app', ['dabl'])\n\n// setup 'db' service with models\n.service('db', ['dabl', function(dabl) {\n\tvar adapter = new dabl.AngularRESTAdapter('rest/'),\n\t\tModel = dabl.Model,\n\t\tdb = {};\n\n  // base model is the parent class for models with id, created, and updated fields\n\tvar BaseModel = Model.extend('base_model', {\n\t\tadapter: adapter,\n\t\tfields: {\n\t\t\tid: { type: 'int', key: true, computed: true },\n\t\t\tcreated: Date,\n\t\t\tupdated: Date\n\t\t}\n\t});\n\n\tdb.Author = BaseModel.extend('author', {\n\t\turl: 'authors/:id.json',\n\t\tfields: {\n\t\t\t// id, created, updated\n\t\t\tname: String\n\t\t},\n\t\tprototype: {\n\t\t\ttoString: function() {\n\t\t\t\treturn this.name;\n\t\t\t}\n\t\t}\n\t});\n\n\tdb.Post = BaseModel.extend('post', {\n\t\turl: 'posts/:id.json',\n\t\tfields: {\n\t\t\t// id, created, updated\n\t\t\tcontent: String,\n\t\t\tauthor: db.Author\n\t\t}\n\t});\n\n  // circular foreign keys require a separate addField call\n\tdb.Author.addField('posts', { type: Array, elementType: db.Post });\n\n\treturn db;\n}])\n\n.controller('MainCtrl', ['$scope', 'db', function($scope, db) {\n\n\t$scope.data = [];\n\n\tvar search = {\n\t\tlimit: 10000,\n\t\torder_by: 'id'\n\t};\n\n\tvar doSearch = function() {\n\t\tdb.Author.findAll(search).then(function(r){\n\t\t\t$scope.authors = r;\n\t\t});\n\t};\n\tdoSearch();\n\t\n\t$scope.deleteAuthor = function (author) {\n\t  if (author.isModified() \u0026\u0026 !confirm(\"This is author has been modified.  Are you sure?\")) {\n\t    return;\n\t  }\n\t  author.remove().then(function(){\n\t    // success\n\t  }, function(){\n\t    // error\n\t  });\n\t};\n\t\n\t$scope.getAuthorById = function (id) {\n\t  return db.Author.find(id).then(function(){\n\t    // success\n\t  }, function(){\n\t    // error\n\t  });\n\t};\n\n}]);\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanifestwebdesign%2Fdabl-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanifestwebdesign%2Fdabl-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanifestwebdesign%2Fdabl-js/lists"}