data_source v4.0.8
DataSource
This is a module for interfacing with data coming from any source in uniform way. A data source is a client side key-value store that exposes promised based async methods for working with data.
DataSource uses the Adapter pattern. By default the adapter uses the data sources in-memory key-value store as the source of truth and implements all of its methods(detailed below) with sensible defaults. If you need a custom implementation for things like getting data from a server via http or websockets or using localStorage, you would override the corresponding method in the adapter instance you provide to support reading / writing data to your custom location or dealing with custom queries or actions.
A simple example:
var userDataSource = new DataSource<User>(new UserAdapter());
userDataSource.setRecord('recordId', new User()).then((user : User) => {
user.someMethod();
return user;
}).then((user : User) => {
//do stuff
});
userDataSource.getRecord('recordId').then((user : User) => {
//do stuff
});
userDataSource.addRecord('recordId2', someUser);
Data Source API
Adapter Source Interface
Adapters don't have direct references to the data source they work with. Instead they use an instance a DataSourceInterface.
This interface provides a synchronous api into the data source.
DataSourceInterface
get(id : string) : Tget a record by idadd(record : T) : Tadd a recordset(id : string, record : T) : Tupdate / change / remove (if record is null)remove(id : string) : Tremoe a recordclear() : voidnuke the data source record storeid(record : T) : stringget an id for a given recordrecords() : Array<T>get all the local records in the data source in an array. This is internally cached is relatively performant so calling this many times is fine.
DataSource Methods
on(eventName : string, callback : (record : T) => void) : voidDataSource is an event emitter that will emit the following eventsrecordAdded--(record : T, id : string) => void-- when new records are addedrecordChanged--(record : T, oldRecord : T, id : string) => voidwhen existing records change (viasetRecord, not when properties change)recordRemoved--(record : T, id : string) => voidwhen records are removed
loadRecords() : Array<T>-- Loads all records form the backing storeloadRecordsOnce() : Array<T>IfloadRecords()has not been called on the data source, it will callloadRecords()on the adapter and return the results otherwise it will just return what is stored locally and will not execute the adapter'sloadRecords()a second time. A use case for this method might be to load a bunch of records from the server, but be sure to only ever do it once since loading things from a server is slow.addRecord(record : T) : Promise<T>Adds a record to the data source, returns a promise that resolves the record that was addedgetRecord(id : string) : Promise<T>Gets a record and returns a promise resolving that record or null if no record was found.setRecord(id : string, record : T) : Promise<T>writes an update into the data source. if no record exists for the given id, the record will be added. if a record is prexisting for that id, it will be updated with the new record value. ifrecord === nullthat record will be removed.updateRecord(record : T) : Promise<T>the same assetRecordbut computes the id of the record by callingadapter.getRecordId(record)removeRecord(recordOrId : T|string) : Promise<T>Takes a record to remove or an Id of a record to remove and removes it from the data source. Returns a promise that resolves the removed record or null if no record was removed.addRecordCollection(records : Array<T>|IRecordStore<T>) : Promise<T[]>Adds every record in therecordsargument to the data source.getRecordCollection(ids : Array<string>) : Promise<T[]>Gets all records in the data source that have an id in theidsargument.removeRecordCollection(records : Array<T>|IRecordStore<T>) : Promise<T[]>Removes allrecordsfrom the data sourceupdateRecordCollection(records : Array<T>|IRecordStore<T>) : Promise<T[]>Updates each record in therecordsargumentgetRecordPage(pageSize : number, pageNumber : number, optionalArgs : ...args) : Promise<T[]>this is used for paging, you can supply anything you want in theoptionalArgsparameter and that will be passed on to the adaptergetRecordCount() : Promise<number>returns the total number of records in the data source, this is used in conjuction withgetRecordPageto accurately show how many pages of records there might be on your server / whatever you are pagingquery(...args : any[]) : Promise<any>This is a way for you to define functionality outside of the normal data source methods, for instance finding all users with the name 'Matt' is not something any of the other data source methods know how to handle. It is up to you to define the behavior of this function in your adapter.action(...args : any[]) : Promise<any>Identical toquerybut sometimes makes more semantic senseclearLocalRecordStore() : voidClears the entire local record set and emitsrecordRemovedevents for each recordcreateManagedCollection(options? : ICollectionOptions) : Collectioncreates and manages a collection. Whenever a record is added / updated / removed from the data source that change will be automatically reflected in the collection that is returned. If anoptionsparameter is supplied it will be passed through to the collection.manageCollection(collection : Collection) : Collectionequivalent tocreateManagedCollectionbut you supply the collection to be managed instead of DataSource creating one for youawaitRecord(id : string) : Promise<T>Resolves when a record withidis added to the data source, or immediately if it is already there. This will not issue a call togetRecordfor you.awaitRecords(ids : Array<string>) : Promise<T[]>The same asawaitRecordbut will resolve when allidsare present in the data source or immediately if they are all there already.observeRecord(id : string, callback : (record : T) => void) : CancelFunctionthis is a more performant way to listen for changes on a specific record. This is far preferable to listening torecordChangedand checking if the id that changed is the id you are watchingobserveRecords(ids : Array<string>, callback : (record : T) => void) : CancelFunctionSame asobserveRecordbut for many records at once. The callback is invoked for each record change.reset() : voidresets the data source, removing all records and observers and event listeners. UnlikeclearLocalRecordStore()this will not emitrecordRemovedevents
Adapter Methods To Override
initialize()This function runs when the Adapter'sconfigpromise has resolved.loadRecords(localRecords : IRecordStore<T>)By default returns all records stored locally in the DataSource. ThelocalRecordsparameter is an object keyed by Id that contains all the records currently in the data source.addRecord(id : string, localRecord : T) : T|Promise<T>By default just adds the record to the data sourceremoveRecord(record : T, id : string) : T|Promise<T>By default removed the record from the data sourcegetRecord(id : string, localRecord : T) : T|Promise<T>Gets a record, by default returnslocalRecordsetRecord(id : string, newRecord : T, localRecord :T) : T|Promise<T>updates a record, returnsnewRecordby defaultaddRecordCollection(records : Array<T>|IRecordStore<T>) : T[]|Promise<T[]>callsadapter.addRecord()for each record in arraygetRecordCollection(ids : Array<string>) : T[]|Promise<T[]>callsadapter.getRecord(id)for each record in arrayremoveRecordCollection(collection : T[]|IRecordStore<T>) : T[]|Promise<T[]>callsadapter.removeRecord()for each record in arrayupdateRecordCollection(collection : T[]|IRecordStore<T>) : T[]|Promise<T[]>callsadapter.setRecord()from each record in arraygetRecordPage(pageSize : number, pageNumber : number, optionalArgs : any) : T[]|Promise<T[]>by default returns a subsection of the local data source recordsgetRecordCount() : number|Promise<number>getRecordId() : stringrecordsEqual(a : T, b : T) : booleanaction(actionName : string, ...args : any[]) : anyquery(queryName : string, ...args : any[]) : any
Collection
Collections are 'smart' arrays of things (doesnt have to be object types). They are sortable, filterable, pageable and groupable.
Interfaces
IRecordStore<T> {[id : string, record :T }
Note that because of the adapter pattern use METHODS DEFINED ON THE DATA SOURCE ARE NOT THE SAME AS THE METHODS DEFINED IN THE ADAPTER.
Adapter methods often have different signatures than the correspondingly named method on the DataSource itself. For example,
when calling dataSource.loadRecords() no parameters are expected, but when the data source invokes the adapter's version
of loadRecords, it also passes along a copy of the local store.
Defining a method on the adapter DOES NOT expose it to the data source.
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago