{"id":13742735,"url":"https://github.com/danschultz/mesh","last_synced_at":"2026-03-15T15:32:40.797Z","repository":{"id":1131863,"uuid":"1008244","full_name":"danschultz/mesh","owner":"danschultz","description":"A model centric persistence framework for Flex.","archived":false,"fork":false,"pushed_at":"2012-04-16T08:01:43.000Z","size":4977,"stargazers_count":17,"open_issues_count":5,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-15T13:39:37.360Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/danschultz/mesh/wiki","language":"ActionScript","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/danschultz.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":"2010-10-20T06:04:59.000Z","updated_at":"2019-11-29T20:29:35.000Z","dependencies_parsed_at":"2022-08-16T12:10:37.267Z","dependency_job_id":null,"html_url":"https://github.com/danschultz/mesh","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danschultz%2Fmesh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danschultz%2Fmesh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danschultz%2Fmesh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danschultz%2Fmesh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danschultz","download_url":"https://codeload.github.com/danschultz/mesh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253170993,"owners_count":21865274,"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-08-03T05:00:35.583Z","updated_at":"2025-12-24T11:22:32.189Z","avatar_url":"https://github.com/danschultz.png","language":"ActionScript","readme":"# Mesh - v0.3.0\nMesh is an open-source persistence framework for [Adobe Flex](http://www.adobe.com/products/flex/). Its aim is to make the retrieval and persistence of your application's model as transparent as possible.\n\nMesh provides the mechanisms for defining the associations between your models, tracking which objects need to be saved, validating the integrity of your data, and mapping your models to backend services. In addition, Mesh is completely agnostic to the backend service that you use. It can be used with any existing AMF, REST, SOAP service, and hypothetically an AIR application running a SQLite database.\n\nMesh follows the guidelines of [semantic versioning](http://www.semver.org).\n\n## Store\nThe store is what your application interacts with to load, query, and persist data changes. Any records that are retrieved from your backend are stored here for your application to use.\n\n### Queries\nQueries are used to find data within the store. You can search for a single record, or many records.\n\n\t// Creating queries\n\tvar person:Person = store.query(Person).find(1);\n\tvar people:ResultsList = store.query(Person).findAll();\n\nSometimes the data for the query hasn't been loaded yet. Calling `load()` will load the data for the query. The `load()` method will only load the data if it hasn't been loaded yet. Call `refresh()` if you want to force a reload of the data.\n\n\t// Load a query from the data source\n\tvar guys:ResultsList = store.query(Person).where({sex:\"m\"}).load();\n\n\t// Reload the query\n\tguys.refresh();\n\nThe load operation for each query can be used to lnow when the data has finished loading. Add the event listener before calling `load()`. This ensures the listener exists for synchronous data calls.\n\n\t// Listening for loaded data\n\tperson = store.query(Person).find(1);\n\tperson.loadOperation.addEventListener(FinishedOperationEvent.FINISHED, function(event:FinishedOperationEvent):void\n\t{\n\t\ttrace(\"loaded \" + person)\n\t});\n\tperson.load();\n\nFiltered queries can be used for returning records that match certain criteria.\n\n\t// Filtered queries\n\tvar guys:ResultsList = store.query(Person).where({sex:\"male\"});\n\nQuery results automatically update whenever the store is updated. For result sets, you cannot add or remove elements directly from the result list. These operations must happen through the store.\n\n\t// Query for everyone\n\tvar people:ResultsList = store.query(Person).findAll();\n\ttrace(people.length); // 5\n\n\t// Remove a person from the store\n\tvar person:Person = store.query(Person).find(1);\n\tperson.remove();\n\ttrace(people.length); // 4\n\n## Records\nModel classes in Mesh are sub-classes of `Record`. They define the relationships with other records, and watch how you application modifies them. They detect when their properties change, when their destroyed, and when their data is persisted to the backend. All records that are created and retrieved from your backend are kept in the store.\n\n**Example:** A simple model.\n\n\tpackage myapp\n\t{\n\t\t[Bindable]\n\t\tpublic class Person extends Record\n\t\t{\n\t\t\tpublic var name:String;\n\t\t\tpublic var age:int;\n\t\t}\n\t}\n\n### Associations\nRecords can have has-one and has-many relationships with other records. These relationships automatically update when the store changes.\n\nWhen a record is associated, the necessary foreign keys are automatically populated, and the record is inserted into the store that contains the association.\n\n**Example:** Definining Associations\n\n\tpackage myapp\n\t{\n\t\t[Bindable]\n\t\tpublic class Customer extends Record\n\t\t{\n\t\t\tpublic var name:String;\n\t\t\tpublic var age:int;\n\n\t\t\tpublic var accountId:int;\n\n\t\t\t[HasOne]\n\t\t\tpublic var account:Account;\n\n\t\t\t[HasMany(inverse=\"customer\", recordType=\"myapp.Order\")]\n\t\t\tpublic var orders:HasManyAssociation;\n\n\t\t\tpublic function Customer()\n\t\t\t{\n\t\t\t\tsuper();\n\t\t\t}\n\t\t}\n\t}\n\n#### Has-one Associations\nHas-one relationships are populated when the record's foreign keys change. If the associated record has not been loaded, an empty record will be created with its ID populated with the foreign key. The has-one association can then be loaded like so: `customer.account.load();`.\n\n**Example:** Associating has-one relationships\n\n\tvar customer:Customer = store.query(Customer).find(1);\n\tvar account:Account = store.query(Account).find(2);\n\tcustomer.account = account;\n\ttrace(account.customerId); // 1\n\ttrace(customer.accountId); // 2\n\n#### Has-many Associations\nHas-many associations are populated through a call to load, like so: `customer.orders.load();`.\n\n**Example:** Associating has-many relationships\n\n\tvar order:Order = store.query(Order).find(3);\n\tcustomer.orders.add(order);\n\ttrace(order.customerId); // 1\n\n### Creating Records\nThe store is responsbile for creating new records in your application. These records will be persisted to the backend on the store's next save.\n\n\tvar customer:Customer = store.create(Customer);\n\n### Destroying Records\nYou can destroy records in the store by calling `Record.destroy()`. This method will remove the record from any associations, or any result lists that it belongs to. The record is also marked for removal from the backend.\n\n**Example:** Destroying records\n\n\tvar order:Order = customer.orders.at(0);\n\torder.destroy();\n\ttrace(customer.orders.contains(order)); // false\n\ttrace(order.state.willBeDestroyed); // true\n\n### Persisting Records\nRecords are persistable by calling the record's `persist()` method. Depending on the current state of the record, it will either be created, updated or destroyed on the backend.\n\n**Example:** Persisting individual records\n\n\tperson.name = \"Jimmy Page\";\n\tperson.persist();\n\n**Example:** Persisting has-many associations\n\n\tvar order1:Order = new Order();\n\torder1.total = 9.99;\n\tcustomer.orders.add(order1);\n\n\tvar order2:Order = new Order();\n\torder2.total = 4.99;\n\tcustomer.orders.add(order2);\n\n\tcustomer.orders.persist();\n\n**Example:** Listening for persistence callbacks\n\n\tcustomer.orders.persist(new PersistenceResponder(function(fault:Object):void\n\t{\n\t\tif (fault) {\n\n\t\t}\n\t}));\n\n## Data Source\nThe data source is used to connect your records to your backend. It defines a set of methods that must be implemented in order to create, retrieve, delete, and update data on the server.\n\n**Example:** A sample data source.\n\n\tpackage myapp\n\t{\n\t\tpublic class MyDataSource extends AMFDataSource\n\t\t{\n\t\t\tpublic function MyDataSource()\n\t\t\t{\n\t\t\t\tsuper();\n\t\t\t}\n\n\t\t\tpublic function retrieve(responder:IRetrieveResponder, record:Record):void\n\t\t\t{\n\t\t\t\tvar operation:Operation = createOperation(\"retrieve\", id);\n\t\t\t\toperation.addEventListener(ResultOperationEvent.RESULT, function(event:ResultOperationEvent):void\n\t\t\t\t{\n\t\t\t\t\tresponder.loaded(event.data);\n\t\t\t\t});\n\t\t\t\toperation.addEventListener(FaultOperationEvent.FAULT, function(event:FaultOperationEvent):void\n\t\t\t\t{\n\t\t\t\t\tresponder.failed();\n\t\t\t\t});\n\t\t\t\toperation.execute();\n\t\t\t}\n\n\t\t\tpublic function create(responder:IPersistenceResponder, snapshot:Snapshot):void\n\t\t\t{\n\t\t\t\tvar operation:Operation = createOperation(\"create\", snapshot.data);\n\t\t\t\toperation.addEventListener(ResultOperationEvent.RESULT, function(event:ResultOperationEvent):void\n\t\t\t\t{\n\t\t\t\t\tresponder.saved(snapshot, event.data.id);\n\t\t\t\t});\n\t\t\t\toperation.addEventListener(FaultOperationEvent.FAULT, function(event:FaultOperationEvent):void\n\t\t\t\t{\n\t\t\t\t\tresponder.failed(snapshot);\n\t\t\t\t});\n\t\t\t\toperation.execute();\n\t\t\t}\n\t\t}\n\t}\n\nIt's likely that an application will have many types of model classes, each with their own service endpoints. In these scenarios, a `MultiDataSource` can be used to map a record type to its own data source.\n\n\t// Map a data source to each type of record.\n\tvar dataSource:MultiDataSource = new MultiDataSource();\n\tdataSource.map(Customer, new CustomerDataSource());\n\tdataSource.map(Account, new AccountDataSource());\n\tdataSource.map(Order, new OrderDataSource()); \n\n\tvar store:Store = new Store(dataSource);\n","funding_links":[],"categories":["User Interface"],"sub_categories":["Flex Components"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanschultz%2Fmesh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanschultz%2Fmesh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanschultz%2Fmesh/lists"}