Merge pull request #3755 from reppners/js-data

js-data typings including js-data-angular, js-data-http
This commit is contained in:
Masahiro Wakame
2015-03-05 22:53:53 +09:00
7 changed files with 1269 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
/// <reference path="js-data-angular.d.ts" />
interface IUser {
}
interface CustomScope extends ng.IScope {
comments: Array<any>;
user: IUser;
users: Array<IUser>;
}
angular.module('myApp')
.controller('commentsCtrl', function ($scope:CustomScope, store:JSData.DS, Comment:JSData.DSResourceDefinition<any>, User:JSData.DSResourceDefinition<any>) {
Comment.findAll().then(function (comments) {
$scope.comments = comments;
});
// shortest version
User.bindOne(1, $scope, 'user');
// short version
store.bindOne('user', 1, $scope, 'user');
// long version
$scope.$watch(function () {
return store.lastModified('user', 1);
}, function () {
$scope.user = store.get<IUser>('user', 1);
});
var params = {
where: {
age: {
'>': 30
}
}
};
// shortest verions
User.bindAll(params, $scope, 'users');
// short version
store.bindAll('user', params, $scope, 'users');
// long version
$scope.$watch(function () {
return store.lastModified('user');
}, function () {
$scope.users = store.filter('user', params);
});
});
angular.module('myApp')
.run(function (DS:JSData.DS) {
// We don't register the "User" resource
// as a service, so it can only be used
// via DS.<method>('user', ...)
// The advantage here is that this code
// is guaranteed to be executed, and you
// only ever have to inject "DS"
DS.defineResource('user');
})
.factory('Comment', function (DS:JSData.DS) {
// This code won't execute unless you actually
// inject "Comment" somewhere in your code.
// Thanks Angular...
// Some like injecting actual Resource
// definitions, instead of just "DS"
return DS.defineResource('comment');
});
angular.module('myApp')
.config(function (DSProvider:JSData.DSProvider) {
DSProvider.defaults.basePath = '/myApi'; // etc.
});
+30
View File
@@ -0,0 +1,30 @@
// Type definitions for JSDataAngular v2.1.0
// Project: https://github.com/js-data/js-data-angular
// Definitions by: Stefan Steinhart <https://github.com/reppners>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../js-data/js-data.d.ts" />
/// <reference path="../angularjs/angular.d.ts" />
declare module JSData {
interface DSProvider {
defaults:DSConfiguration;
}
interface DS {
bindAll<T>(resourceName:string, params:DSFilterParams, scope:ng.IScope, expr:string, cb?:(err:DSError, items:Array<T>)=>void):Function;
bindOne<T>(resourceName:string, id:string, scope:ng.IScope, expr:string, cb?:(err:DSError, item:T)=>void):Function;
bindOne<T>(resourceName:string, id:number, scope:ng.IScope, expr:string, cb?:(err:DSError, item:T)=>void):Function;
}
interface DSResourceDefinition<T> {
bindAll<T>(params:DSFilterParams, scope:ng.IScope, expr:string, cb?:(err:DSError, items:Array<T>)=>void):Function;
bindOne<T>(id:string, scope:ng.IScope, expr:string, cb?:(err:DSError, item:T)=>void):Function;
bindOne<T>(id:number, scope:ng.IScope, expr:string, cb?:(err:DSError, item:T)=>void):Function;
}
}
+167
View File
@@ -0,0 +1,167 @@
/// <reference path="js-data-http.d.ts" />
var adapter = new DSHttpAdapter();
var store = new JSData.DS();
store.registerAdapter('http', adapter, { default: true });
var ADocument:JSData.DSResourceDefinition<any> = store.defineResource<any>('document');
ADocument.inject({ id: 5, author: 'John' });
// bypass the data store
adapter.update(ADocument, 5, { author: 'Johnny' }).then(function (document:any) {
document; // { id: 5, author: 'Johnny' }
// The updated document has NOT been injected into the data store because we bypassed the data store
ADocument.get(document.id); // { id: 5, author: 'John' }
});
// Normally you would just go through the data store
ADocument.update(5, { author: 'Johnny' }).then(function (document:any) {
document; // { id: 5, author: 'Johnny' }
// the updated document has been injected into the data store
ADocument.get(document.id); // { id: 5, author: 'Johnny' }
});
ADocument.inject({ id: 5, author: 'John' });
ADocument.inject({ id: 6, author: 'John' });
// bypass the data store
adapter.updateAll(ADocument, { author: 'Johnny' }, { author: 'John' }).then(function (documents) {
documents[0]; // { id: 5, author: 'Johnny' }
// The updated documents have NOT been injected into the data store because we bypassed the data store
ADocument.filter({ author: 'John' }); // [{...}, {...}]
ADocument.filter({ author: 'Johnny' }); // []
});
// Normally you would just go through the data store
ADocument.updateAll({ author: 'Johnny' }, { author: 'John' }).then(function (documents) {
documents[0]; // { id: 5, author: 'Johnny' }
// the updated documents have been injected into the data store
ADocument.filter({ author: 'John' }); // []
ADocument.filter({ author: 'Johnny' }); // [{...}, {...}]
});
adapter.PUT('/user/1', { name: 'Johnny' }).then(function (data) {
data.data; // { id: 1, name: 'Johnny', ... }
data.headers; // {...}
data.status; // 200
data.config; //{...}
});
adapter.POST('/user/1', { name: 'John' }).then(function (data) {
data.data; // { id: 1, name: 'John', ... }
data.headers; // {...}
data.status; // 200
data.config; //{...}
});
adapter.HTTP({ url: '/user/1', method: 'put', data: { name: 'Johnny' }}).then(function (data) {
data.data; // { id: 1, name: 'Johnny', ... }
data.headers; // {...}
data.status; // 200
data.config; //{...}
});
adapter.GET('/user/1').then(function (data) {
data.data; // { id: 1, ... }
data.headers; // {...}
data.status; // 200
data.config; //{...}
});
var User:JSData.DSResourceDefinition<any> = store.defineResource('user');
var params:any = {
age: {
'>': 30
}
};
// bypass the data store
adapter.findAll(User, params).then(function (users) {
// users[0].age; 55 // etc., etc.
// the users have NOT been injected into the data store because we bypassed the data store
User.filter(params); // []
});
// normally you would go through the data store
User.findAll(params).then(function (users) {
// users[0].age; 55 // etc., etc.
// the users have been injected into the data store
User.filter(params); // [{...}, {...}, ...]
});
// bypass the data store
adapter.find(ADocument, 5).then(function (document:any) {
document; // { id: 5, author: 'John Anderson' }
// the document has NOT been injected into the data store because we bypassed the data store
ADocument.get(document.id); // undefined
});
// Normally you would just go through the data store
ADocument.find(5).then(function (document:any) {
document; // { id: 5, author: 'John Anderson' }
// the document has been injected into the data store
ADocument.get(document.id); // { id: 5, author: 'John Anderson' }
});
var params:any = {
author: 'John'
};
// bypass the data store
adapter.destroyAll(ADocument, params).then(function () {
// the documents have NOT been ejected from the data store because we bypassed the data store
ADocument.filter(params); // [{...}, {...}, ...]
});
// normally you would go through the data store
ADocument.destroyAll(params).then(function () {
// the documents have been ejected from the data store
ADocument.filter(params); // []
});
ADocument.inject({ id: 5, author: 'John' });
// bypass the data store
adapter.destroy(ADocument, 5).then(function () {
// the document is still in the data store because we bypassed the data store
//ADocument.get(document.id); // { id: 5, author: 'John' }
});
// Normally you would just go through the data store
ADocument.destroy(5).then(function () {
// the document has been ejected from the data store
//ADocument.get(document.id); // undefined
});
adapter.DEL('/user/1').then(function (data) {
data.data; // 1
data.headers; // {...}
data.status; // 204
data.config; //{...}
});
// bypass the data store
adapter.create(ADocument, { author: 'John' }).then(function (document:any) {
document; // { id: 5, author: 'John' }
// The new document has NOT been injected into the data store because we bypassed the data store
ADocument.get(document.id); // undefined
});
// Normally you would just go through the data store
ADocument.create({ author: 'John' }).then(function (document:any) {
document; // { id: 5, author: 'John' }
// the new document has been injected into the data store
ADocument.get(document.id); // { id: 5, author: 'John' }
});
+46
View File
@@ -0,0 +1,46 @@
// Type definitions for JSData Http Adapter v1.2.0
// Project: https://github.com/js-data/js-data-http
// Definitions by: Stefan Steinhart <https://github.com/reppners>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../js-data/js-data.d.ts" />
declare module JSData {
interface DSHttpAdapterOptions {
serialize?: (resourceName:string, data:any)=>any;
deserialize?: (resourceName:string, data:any)=>any;
queryTransform?: (resourceName:string, params:DSFilterParams)=>any;
httpConfig?: any;
forceTrailingSlash?: boolean;
log?: any;
// TODO wait for union types to be supported
// log: (message?: any, ...optionalParams: any[])=> void;
// log: boolean;
error?: any;
// TODO wait for union types to be supported
// error: (message?: any, ...optionalParams: any[])=> void;
// error: boolean;
}
interface DSHttpAdapterPromiseResolveType {
data: any;
headers: any;
status: number;
config: any;
}
interface DSHttpAdapter extends IDSAdapter {
new(options?:DSHttpAdapterOptions):DSHttpAdapter;
// DSHttpAdapter uses axios so options are axios config objects.
HTTP(options?:Object):JSDataPromise<DSHttpAdapterPromiseResolveType>;
DEL(url:string, data?:Object, options?:Object):JSDataPromise<DSHttpAdapterPromiseResolveType>;
GET(url:string, data?:Object, options?:Object):JSDataPromise<DSHttpAdapterPromiseResolveType>;
POST(url:string, data?:Object, options?:Object):JSDataPromise<DSHttpAdapterPromiseResolveType>;
PUT(url:string, data?:Object, options?:Object):JSDataPromise<DSHttpAdapterPromiseResolveType>;
}
}
declare var DSHttpAdapter:JSData.DSHttpAdapter;
+17
View File
@@ -0,0 +1,17 @@
/// <reference path="js-data.d.ts" />
import JSData = require('js-data');
//TODO
//import DSRedisAdapter = require('js-data-redis')
var store = new JSData.DS();
// register and use http by default for async operations
//TODO
//store.registerAdapter('redis', new DSRedisAdapter(), {default: true});
// simplest model definition
var User = store.defineResource('user');
User.find(1).then(function (user: any) {
user; // { id: 1, name: 'John' }
});
+524
View File
@@ -0,0 +1,524 @@
/// <reference path="js-data.d.ts" />
interface IUser {
id?: number;
name?: string;
age?: number;
first?: string;
last?: string;
comments?:Array<any>;
profile?:any;
}
interface IUserWithMethod extends IUser {
fullName?: () => string;
}
interface IUserWithComputedProperty extends IUser {
fullName?: string;
}
var store = new JSData.DS();
// register and use http by default for async operations
//TODO
//store.registerAdapter('http', new DSHttpAdapter(), {default: true});
// simplest model definition
var User = store.defineResource<IUser>('user');
User.find(1).then(function (user:IUser) {
user; // { id: 1, name: 'John' }
});
var user:IUser = User.createInstance<IUser>({name: 'John'});
var store = new JSData.DS();
var User = store.defineResource('user');
var user:IUser = User.inject<IUser>({id: 1, name: 'John'});
var user2:IUser = User.inject<IUser>({id: 1, age: 30});
user; // User { id: 1, name: 'John', age: 30 }
user2; // User { id: 1, name: 'John', age: 30 }
User.get(1); // User { id: 1, name: 'John', age: 30 }
user === user2; // true
user === User.get(1); // true
user2 === User.get(1); // true
var store = new JSData.DS({
// set a default lifecycle hook
afterCreate: function () {
}
});
var User = store.defineResource<IUser>({
name: 'user',
// override the hook for this resource
afterCreate: function () {
}
});
User.create({
name: 'john'
}, {
// override the hook just for this method call
afterCreate: function () {
}
}).then(()=> {
});
var store = new JSData.DS();
var UserWithMethod = store.defineResource<IUserWithMethod>({
name: 'user',
methods: {
fullName: function () {
return this.first + ' ' + this.last;
}
}
});
var userWithMethod = UserWithMethod.createInstance<IUserWithMethod>({first: 'John', last: 'Anderson'});
userWithMethod.fullName(); // "John Anderson"
var store = new JSData.DS();
var UserWithComputedProperty = store.defineResource<IUserWithComputedProperty>({
name: 'user',
computed: {
// each function's argument list defines the fields
// that the computed property depends on
fullName: ['first', 'last', function (first:string, last:string) {
return first + ' ' + last;
}],
// shortand, use the array syntax above if you want
// you computed properties to work after you've
// minified your code. Shorthand style won't work when minified
initials: function (first:string, last:string) {
return first.toUpperCase()[0] + '. ' + last.toUpperCase()[0] + '.';
}
}
});
var userWithComputedProperty:IUserWithComputedProperty = UserWithComputedProperty.inject<IUserWithComputedProperty>({
id: 1,
first: 'John',
last: 'Anderson'
});
userWithComputedProperty.fullName; // "John Anderson"
userWithComputedProperty.first = 'Fred';
// js-data relies on dirty-checking, so the
// computed property (probably) hasn't been updated yet
userWithComputedProperty.fullName; // "John Anderson"
// If your browser supports Object.observe this will have no effect
// otherwise it will trigger the dirty-checking
store.digest();
userWithComputedProperty.fullName; // "Fred Anderson"
interface IComment {
comments?: any;
profile?: any;
}
var aComment:JSData.DSResourceDefinition<IComment> = store.defineResource<IComment>('comment');
// Get all comments where comment.userId == 5
aComment.filter({
where: {
userId: {
'==': 5
}
}
});
// Get all comments where comment.userId == 5
aComment.filter({
userId: 5
});
// Get all comments where comment.userId === 5
aComment.filter({
where: {
userId: {
'===': 5
}
}
});
// Get all comments where comment.userId != 5
aComment.filter({
where: {
userId: {
'!=': 5
}
}
});
// Get all comments where comment.userId !== 5
aComment.filter({
where: {
userId: {
'!==': 5
}
}
});
// Get all users where user.age > 30
User.filter({
where: {
age: {
'>': 30
}
}
});
// Get all users where user.age >= 30
User.filter({
where: {
age: {
'>=': 30
}
}
});
// Get all users where user.age < 30
User.filter({
where: {
age: {
'<': 30
}
}
});
// Get all users where user.name is in "John Anderson"
User.filter({
where: {
name: {
'in': 'John Anderson'
}
}
});
// Get all users where user.role is in ["admin", "owner"]
User.filter({
where: {
role: {
'in': ['admin', 'owner']
}
}
});
// Get all users where user.name is NOT in "John Anderson"
User.filter({
where: {
name: {
'notIn': 'John Anderson'
}
}
});
// Get all users where user.role is NOT in ["admin", "owner"]
User.filter({
where: {
role: {
'notIn': ['admin', 'owner']
}
}
});
// Get all users where user.name contains "John"
User.filter({
where: {
name: {
'contains': 'John'
}
}
});
// Get all users where user.roles contains "admin"
User.filter({
where: {
roles: {
'contains': 'admin'
}
}
});
// Sorts users by age in ascending order
User.filter({
orderBy: 'age'
});
// Sorts users by age in descending order
User.filter({
orderBy: ['age', 'DESC']
});
// Sorts users by age in descending order and then sort by name in ascending order to break a tie
User.filter({
orderBy: [
['age', 'DESC'],
['name', 'ASC']
]
});
var PAGE_SIZE = 20;
var currentPage = 1;
interface IPost {
}
var Post:JSData.DSResourceDefinition<IPost>;
// Grab the first "page" of posts
Post.filter({
offset: PAGE_SIZE * (currentPage - 1),
limit: PAGE_SIZE
});
var User = store.defineResource({
name: 'user',
relations: {
hasMany: {
comment: {
localField: 'comments',
foreignKey: 'userId'
}
},
hasOne: {
profile: {
localField: 'profile',
foreignKey: 'userId'
}
},
belongsTo: {
organization: {
localKey: 'organizationId',
localField: 'organization',
// if you add this to a belongsTo relation
// then js-data will attempt to use
// a nested url structure, e.g. /organization/15/user/4
parent: true
}
}
}
});
var Organization = store.defineResource({
name: 'organization',
relations: {
hasMany: {
// this is an example of multiple relations
// of the same type to the same resource
user: [
{
localField: 'users',
foreignKey: 'organizationId'
},
{
localField: 'owners',
foreignKey: 'organizationId'
}
]
}
}
});
var Profile = store.defineResource({
name: 'profile',
relations: {
belongsTo: {
user: {
localField: 'user',
localKey: 'userId'
}
}
}
});
var OtherComment = store.defineResource<IComment>({
name: 'comment',
relations: {
belongsTo: {
user: {
localField: 'user',
localKey: 'userId'
}
}
}
});
User.find(10).then(function (user:IUser) {
// let's assume the server only returned the user
user.comments; // undefined
user.profile; // undefined
User.loadRelations(user, ['comment', 'profile']).then(function (user:IUser) {
user.comments; // array
user.profile; // object
});
});
var OtherOtherComment = store.defineResource<IComment>({
name: 'comment',
relations: {
belongsTo: {
post: {
parent: true,
localKey: 'postId',
localField: 'post'
}
}
}
});
// The comment isn't in the data store yet, so js-data wouldn't know
// what the id of the parent "post" would be, so we pass it in manually
OtherOtherComment.find(5, {params: {postId: 4}}); // GET /post/4/comment/5
// vs
var promise = OtherOtherComment.find(5); // GET /comment/5
promise.then().catch().finally();
OtherOtherComment.inject({id: 1, postId: 2});
// We don't have to provide the parentKey here
// because js-data found it in the comment
OtherOtherComment.update(1, {content: 'stuff'}); // PUT /post/2/comment/1
// If you don't want the nested for just one of the calls then
// you can do the following:
OtherOtherComment.update(1, {content: 'stuff'}, {params: {postId: false}}); // PUT /comment/1
var store = new JSData.DS({
// set the default
beforeCreate: function (resource, data, cb) {
// do something general
cb(null, data);
}
});
var User = store.defineResource({
name: 'user',
// set just for this resource
beforeCreate: function (resource, data, cb) {
// do something more specific to "users"
cb(null, data);
}
});
User.create({name: 'John'}, {
// set just for this method call
beforeCreate: function (resource, data, cb) {
// do something specific for this method call
cb(null, data);
}
});
module CustomAdapterTest {
class MyCustomAdapter implements JSData.IDSAdapter {
// All of the methods shown here must return a promise
// "definition" is a resource defintion that would
// be returned by DS#defineResource
// "options" would be the options argument that
// was passed into the DS method that is calling
// the adapter method
create(definition:JSData.DSResourceDefinition<any>, attrs:Object, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must resolve the promise with the created item
var promise:JSData.JSDataPromise<any>;
return promise;
}
find(definition:JSData.DSResourceDefinition<any>, id:any, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must resolve the promise with the found item
var promise:JSData.JSDataPromise<any>;
return promise;
}
findAll(definition:JSData.DSResourceDefinition<any>, params:JSData.DSFilterParams, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must resolve the promise with the found items
var promise:JSData.JSDataPromise<any>;
return promise;
}
update(definition:JSData.DSResourceDefinition<any>, id:any, attrs:Object, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must resolve the promise with the updated items
var promise:JSData.JSDataPromise<any>;
return promise;
}
updateAll(definition:JSData.DSResourceDefinition<any>, attrs:Object, params:JSData.DSFilterParams, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must resolve the promise with the updated items
var promise:JSData.JSDataPromise<any>;
return promise;
}
destroy(definition:JSData.DSResourceDefinition<any>, id:any, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must return a promise
var promise:JSData.JSDataPromise<any>;
return promise;
}
destroyAll(definition:JSData.DSResourceDefinition<any>, params:JSData.DSFilterParams, options:JSData.DSConfiguration):JSData.JSDataPromise<any> {
// Must return a promise
var promise:JSData.JSDataPromise<any>;
return promise;
}
}
var store = new JSData.DS();
store.registerAdapter('mca', new MyCustomAdapter(), {default: true});
// the data store will now use your custom adapter by default
}
/**
* showing the use of open ended interface to realize typings
* on the Datastore.definitions object where all resource definitions
* are saved.
*/
interface MyCustomDataStore {
myResource: JSData.DSResourceDefinition<MyResourceDefinition>
}
interface MyResourceDefinition {
}
module JSData {
interface DS {
definitions: MyCustomDataStore;
}
}
var store = new JSData.DS();
var myResourceDefinition = store.defineResource<MyResourceDefinition>('myResource');
myResourceDefinition = store.definitions.myResource;
+407
View File
@@ -0,0 +1,407 @@
// Type definitions for JSData v1.3.0
// Project: https://github.com/js-data/js-data
// Definitions by: Stefan Steinhart <https://github.com/reppners>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
///////////////////////////////////////////////////////////////////////////////
// js-data module (js-data.js)
///////////////////////////////////////////////////////////////////////////////
// defining what exists in JSData and how it looks
declare module JSData {
interface JSDataPromise<R> {
then<U>(onFulfilled?: (value: R) => U | JSDataPromise<U>, onRejected?: (error: any) => U | JSDataPromise<U>): JSDataPromise<U>;
catch<U>(onRejected?: (error: any) => U | JSDataPromise<U>): JSDataPromise<U>;
// enhanced with finally
finally<U>(finallyCb?:() => U):JSDataPromise<U>;
}
//TODO switch to class again when typescript supports open ended class declaration
interface DS {
new(config?:DSConfiguration):DS;
// rather undocumented
errors:DSErrors;
// those are objects containing the defined resources and adapters
definitions:any;
adapters:any;
defaults:DSConfiguration;
changeHistory(resourceName:string, id?:string):Array<Object>;
changeHistory(resourceName:string, id?:number):Array<Object>;
changes(resourceName:string, id:string):Object;
changes(resourceName:string, id:number):Object;
compute<T>(resourceName:string, id:number):T;
compute<T>(resourceName:string, id:string):T;
compute<T>(resourceName:string, instance:Object):T;
create<T>(resourceName:string, attrs:any, options?:DSConfiguration):JSDataPromise<T>;
createInstance<T>(resourceName:string, attrs?:T, options?:DSAdapterOperationConfiguration):T;
defineResource<T>(resourceName:string):DSResourceDefinition<T>;
defineResource<T>(definition:DSResourceDefinitionConfiguration):DSResourceDefinition<T>;
destroy(resourceName:string, id:string, options?:DSAdapterOperationConfiguration):JSDataPromise<any>;
destroy(resourceName:string, id:number, options?:DSAdapterOperationConfiguration):JSDataPromise<any>;
destroyAll(resourceName:string, params?:DSFilterParams, options?:DSAdapterOperationConfiguration):JSDataPromise<any>;
digest():void;
eject<T>(resourceName:string, id:string, options?:DSConfiguration):T;
eject<T>(resourceName:string, id:number, options?:DSConfiguration):T;
ejectAll<T>(resourceName:string, params:DSFilterParams, options?:DSConfiguration):Array<T>;
filter<T>(resourceName:string, params:DSFilterParams, options?:DSConfiguration):Array<T>;
find<T>(resourceName:string, id:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
find<T>(resourceName:string, id:number, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
findAll<T>(resourceName:string, params?:DSFilterParams, options?:DSAdapterOperationConfiguration):JSDataPromise<Array<T>>;
get<T>(resourceName:string, id:string, options?:DSConfiguration):T;
get<T>(resourceName:string, id:number, options?:DSConfiguration):T;
getAll<T>(resourceName:string, ids?:Array<string>):Array<T>;
getAll<T>(resourceName:string, ids?:Array<number>):Array<T>;
hasChanges(resourceName:string, id:string):boolean;
hasChanges(resourceName:string, id:number):boolean;
inject<T>(resourceName:string, attrs:T, options?:DSConfiguration):T;
inject<T>(resourceName:string, items:Array<T>, options?:DSConfiguration):Array<T>;
is(resourceName:string, object:Object): boolean;
lastModified(resourceName:string, id?:string):number; // timestamp
lastModified(resourceName:string, id?:number):number; // timestamp
lastSaved(resourceName:string, id?:string):number; // timestamp
lastSaved(resourceName:string, id?:number):number; // timestamp
link<T>(resourceName:string, id:string, relations?:Array<string>):T;
link<T>(resourceName:string, id:number, relations?:Array<string>):T;
linkAll<T>(resourceName:string, params:DSFilterParams, relations?:Array<string>):T;
linkInverse<T>(resourceName:string, id:string, relations?:Array<string>):T;
linkInverse<T>(resourceName:string, id:number, relations?:Array<string>):T;
loadRelations<T>(resourceName:string, id:string, relations:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(resourceName:string, id:number, relations:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(resourceName:string, instance:Object, relations:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(resourceName:string, id:string, relations:Array<string>, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(resourceName:string, id:number, relations:Array<string>, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(resourceName:string, instance:Object, relations:Array<string>, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
previous<T>(resourceName:string, id:string):T;
previous<T>(resourceName:string, id:number):T;
reap(resourceName:string, options?:DSConfiguration):JSDataPromise<any>;
refresh<T>(resourceName:string, id:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
refresh<T>(resourceName:string, id:number, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
registerAdapter(adapterId:string, adapter:IDSAdapter, options?:{default: boolean}):void;
save<T>(resourceName:string, id:string, options?:DSSaveConfiguration):JSDataPromise<T>;
save<T>(resourceName:string, id:number, options?:DSSaveConfiguration):JSDataPromise<T>;
unlinkInverse<T>(resourceName:string, id:string, relations?:Array<string>):T;
unlinkInverse<T>(resourceName:string, id:number, relations?:Array<string>):T;
update<T>(resourceName:string, id:string, attrs:any, options?:DSSaveConfiguration):JSDataPromise<T>;
update<T>(resourceName:string, id:number, attrs:any, options?:DSSaveConfiguration):JSDataPromise<T>;
updateAll<T>(resourceName:string, attrs:any, params?:DSFilterParams, options?:DSAdapterOperationConfiguration):JSDataPromise<Array<T>>;
}
interface DSConfiguration extends IDSResourceLifecycleEventHandlers {
actions?: Object;
allowSimpleWhere?: boolean;
basePath?: string;
bypassCache?: boolean;
cacheResponse?: boolean;
defaultAdapter?: string;
defaultFilter?: (collection:Array<any>, resourceName:string, params:DSFilterParams, options:DSConfiguration)=>Array<any>;
eagerEject?: boolean;
// TODO enable when eagerInject in DS#create is implemented
//eagerInject?: boolean;
endpoint?: string;
error?: (message?:any, ...optionalParams:any[])=> void;
fallbackAdapters?: Array<string>;
findAllFallbackAdapters?: Array<string>;
findAllStrategy?: string;
findBelongsTo?: boolean;
findFallbackAdapters?: Array<string>;
findHasOne?: boolean;
findHasMany?: boolean;
findInverseLinks?: boolean;
findStrategy?: string
idAttribute?: string;
ignoredChanges?: Array<any>;
// TODO ignoreMissing is undocumented
//ignoreMissing: boolean;
keepChangeHistory?: boolean;
loadFromServer?: boolean;
log?: any;
// TODO wait for union types to be supported
// log: (message?: any, ...optionalParams: any[])=> void;
// log: boolean;
maxAge?: number;
notify?: boolean;
reapAction?: string;
reapInterval?: number;
resetHistoryOnInject?: boolean;
strategy?: string;
upsert?: boolean;
useClass?: boolean;
useFilter?: boolean;
}
interface DSAdapterOperationConfiguration extends DSConfiguration {
adapter?: string
}
interface DSSaveConfiguration extends DSAdapterOperationConfiguration {
changesOnly?: boolean;
}
interface DSResourceDefinitionConfiguration extends DSConfiguration {
name: string;
computed?: any;
methods?: any;
relations?: {
hasMany?: Object;
hasOne?: Object;
belongsTo?: Object;
};
}
interface DSResourceDefinition<T> extends DSResourceDefinitionConfiguration {
changeHistory(id?:string):Array<Object>;
changeHistory(id?:number):Array<Object>;
changes(id:string):Object;
changes(id:number):Object;
compute<T>(id:number):T;
compute<T>(id:string):T;
compute<T>(instance:Object):T;
create<T>(attrs:any, options?:DSConfiguration):JSDataPromise<T>;
createInstance<T>(attrs?:T, options?:DSAdapterOperationConfiguration):T;
defineResource<T>(resourceName:string):DSResourceDefinition<T>;
defineResource<T>(definition:DSResourceDefinitionConfiguration):DSResourceDefinition<T>;
destroy(id:string, options?:DSAdapterOperationConfiguration):JSDataPromise<any>;
destroy(id:number, options?:DSAdapterOperationConfiguration):JSDataPromise<any>;
destroyAll(params?:DSFilterParams, options?:DSAdapterOperationConfiguration):JSDataPromise<any>;
digest():void;
eject<T>(id:string, options?:DSConfiguration):T;
eject<T>(id:number, options?:DSConfiguration):T;
ejectAll<T>(params:DSFilterParams, options?:DSConfiguration):Array<T>;
filter<T>(params:DSFilterParams, options?:DSConfiguration):Array<T>;
find<T>(id:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
find<T>(id:number, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
findAll<T>(params?:DSFilterParams, options?:DSAdapterOperationConfiguration):JSDataPromise<Array<T>>;
get<T>(id:string, options?:DSConfiguration):T;
get<T>(id:number, options?:DSConfiguration):T;
getAll<T>(ids?:Array<string>):Array<T>;
getAll<T>(ids?:Array<number>):Array<T>;
hasChanges(id:string):boolean;
hasChanges(id:number):boolean;
inject<T>(attrs:T, options?:DSConfiguration):T;
inject<T>(items:Array<T>, options?:DSConfiguration):Array<T>;
is(object:Object): boolean;
lastModified(id?:string):number; // timestamp
lastModified(id?:number):number; // timestamp
lastSaved(id?:string):number; // timestamp
lastSaved(id?:number):number; // timestamp
link<T>(id:string, relations?:Array<string>):T;
link<T>(id:number, relations?:Array<string>):T;
linkAll<T>(params:DSFilterParams, relations?:Array<string>):T;
linkInverse<T>(id:string, relations?:Array<string>):T;
linkInverse<T>(id:number, relations?:Array<string>):T;
loadRelations<T>(id:string, relations:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(id:number, relations:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(instance:T, relations:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(id:string, relations:Array<string>, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(id:number, relations:Array<string>, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
loadRelations<T>(instance:T, relations:Array<string>, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
previous<T>(id:string):T;
previous<T>(id:number):T;
reap(options?:DSConfiguration):JSDataPromise<any>;
refresh<T>(id:string, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
refresh<T>(id:number, options?:DSAdapterOperationConfiguration):JSDataPromise<T>;
save<T>(id:string, options?:DSSaveConfiguration):JSDataPromise<T>;
save<T>(id:number, options?:DSSaveConfiguration):JSDataPromise<T>;
unlinkInverse<T>(id:string, relations?:Array<string>):T;
unlinkInverse<T>(id:number, relations?:Array<string>):T;
update<T>(id:string, attrs:any, options?:DSSaveConfiguration):JSDataPromise<T>;
update<T>(id:number, attrs:any, options?:DSSaveConfiguration):JSDataPromise<T>;
updateAll<T>(attrs:any, params?:DSFilterParams, options?:DSAdapterOperationConfiguration):JSDataPromise<Array<T>>;
}
interface DSFilterParams {
where?: Object;
limit?: number;
skip?: number;
offset?: number;
orderBy?: any;
// TODO wait for union types to be supported
//orderBy?: Array<Array<string>>;
//orderBy?: Array<string>;
//orderBy?: string;
sort?: any;
// TODO wait for union types to be supported
//sort?: string;
//sort?: Array<string>;
//sort?: Array<Array<string>>;
}
interface IDSResourceLifecycleValidateEventHandlers {
beforeValidate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
validate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
afterValidate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
}
interface IDSResourceLifecycleCreateEventHandlers {
beforeCreate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
afterCreate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
}
interface IDSResourceLifecycleCreateInstanceEventHandlers {
beforeCreateInstance?: (resourceName:string, data:any)=>void;
afterCreateInstance?: (resourceName:string, data:any)=>void;
}
interface IDSResourceLifecycleUpdateEventHandlers {
beforeUpdate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
afterUpdate?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
}
interface IDSResourceLifecycleDestroyEventHandlers {
beforeDestroy?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
afterDestroy?: (resourceName:string, data:any, cb:(err:any, data?:any)=>void)=>void;
}
interface IDSResourceLifecycleInjectEventHandlers {
beforeInject?: (resourceName:string, data:any)=>void;
afterInject?: (resourceName:string, data:any)=>void;
}
interface IDSResourceLifecycleEjectEventHandlers {
beforeEject?: (resourceName:string, data:any)=>void;
afterEject?: (resourceName:string, data:any)=>void;
}
interface IDSResourceLifecycleReapEventHandlers {
beforeReap?: (resourceName:string, data:any)=>void;
afterReap?: (resourceName:string, data:any)=>void;
}
interface IDSResourceLifecycleEventHandlers extends IDSResourceLifecycleCreateEventHandlers,
IDSResourceLifecycleCreateInstanceEventHandlers,
IDSResourceLifecycleValidateEventHandlers,
IDSResourceLifecycleUpdateEventHandlers,
IDSResourceLifecycleDestroyEventHandlers,
IDSResourceLifecycleInjectEventHandlers,
IDSResourceLifecycleEjectEventHandlers,
IDSResourceLifecycleReapEventHandlers {
}
// errors
interface DSErrors {
// types
IllegalArgumentError:DSError;
IA:DSError;
RuntimeError:DSError;
R:DSError;
NonexistentResourceError:DSError;
NER:DSError;
}
interface DSError extends Error {
new (message?:string):DSError;
message: string;
type: string;
}
// DSAdapter interface
interface IDSAdapter {
create<T>(config:DSResourceDefinition<T>, attrs:any, options?:DSConfiguration):JSDataPromise<T>;
destroy<T>(config:DSResourceDefinition<T>, id:string, options?:DSConfiguration):JSDataPromise<any>;
destroy<T>(config:DSResourceDefinition<T>, id:number, options?:DSConfiguration):JSDataPromise<any>;
destroyAll<T>(config:DSResourceDefinition<T>, params:DSFilterParams, options?:DSConfiguration):JSDataPromise<any>;
find<T>(config:DSResourceDefinition<T>, id:string, options?:DSConfiguration):JSDataPromise<T>;
find<T>(config:DSResourceDefinition<T>, id:number, options?:DSConfiguration):JSDataPromise<T>;
findAll<T>(config:DSResourceDefinition<T>, params?:DSFilterParams, options?:DSConfiguration):JSDataPromise<T>;
update<T>(config:DSResourceDefinition<T>, id:string, attrs:any, options?:DSConfiguration):JSDataPromise<T>;
update<T>(config:DSResourceDefinition<T>, id:number, attrs:any, options?:DSConfiguration):JSDataPromise<T>;
updateAll<T>(config:DSResourceDefinition<T>, attrs:any, params?:DSFilterParams, options?:DSConfiguration):JSDataPromise<T>;
}
}
// declaring the existing global js object
declare var JSData:{
DS: JSData.DS;
DSErrors: JSData.DSErrors;
};
//Support node require
declare module 'js-data' {
export = JSData;
}