add ember-data typings

This commit is contained in:
Derek Wickern
2017-11-19 10:18:17 -08:00
parent 35272568c9
commit e133846d15
14 changed files with 2110 additions and 0 deletions

1684
types/ember-data/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
import Ember from 'ember';
import DS from 'ember-data';
const JsonApi = DS.JSONAPIAdapter.extend({
// Application specific overrides go here
});
const Customized = DS.JSONAPIAdapter.extend({
host: 'https://api.example.com',
namespace: 'api/v1',
headers: {
'API_KEY': 'secret key',
'ANOTHER_HEADER': 'Some header value'
}
});
const AuthTokenHeader = DS.JSONAPIAdapter.extend({
session: Ember.inject.service('session'),
headers: Ember.computed('session.authToken', function() {
return {
'API_KEY': this.get('session.authToken'),
'ANOTHER_HEADER': 'Some header value'
};
})
});

View File

@@ -0,0 +1,16 @@
import DS from 'ember-data';
import { assertType } from './lib/assert';
class Folder extends DS.Model {
name = DS.attr('string');
children = DS.hasMany<Folder>('folder', { inverse: 'parent' });
parent = DS.belongsTo<Folder>('folder', { inverse: 'children' });
}
const folder = Folder.create();
assertType<Folder>(folder.get('parent'));
assertType<string>(folder.get('parent').get('name'));
folder.get('parent').then(parent => {
assertType<Folder>(parent);
assertType<string>(parent.get('name'));
});

View File

@@ -0,0 +1,43 @@
import DS from 'ember-data';
import { assertType } from './lib/assert';
class Comment extends DS.Model {
text = DS.attr('string');
}
class BlogPost extends DS.Model {
title = DS.attr('string');
commentsAsync = DS.hasMany<Comment>('comment');
commentsSync = DS.hasMany<Comment>('comment', { async: false });
}
const post = BlogPost.create();
assertType<DS.PromiseArray<Comment>>(post.get('commentsSync').reload());
assertType<Comment>(post.get('commentsSync').createRecord());
const comment = post.get('commentsSync').get('firstObject');
assertType<Comment | undefined>(comment);
if (comment) {
assertType<string>(comment.get('text'));
}
assertType<DS.PromiseArray<Comment>>(post.get('commentsAsync').reload());
assertType<Comment>(post.get('commentsAsync').createRecord());
assertType<Comment | undefined>(post.get('commentsAsync').get('firstObject'));
const commentAsync = post.get('commentsAsync').get('firstObject');
assertType<Comment | undefined>(commentAsync);
if (commentAsync) {
assertType<string>(commentAsync.get('text'));
}
assertType<boolean>(post.get('commentsAsync').get('isFulfilled'));
post.get('commentsAsync').then(comments => {
assertType<Comment | undefined>(comments.get('firstObject'));
assertType<string>(comments.get('firstObject')!.get('text'));
});
class Polymorphic extends DS.Model {
paymentMethods = DS.hasMany('payment-method', { polymorphic: true });
}

View File

@@ -0,0 +1,22 @@
import Ember from 'ember';
import DS from 'ember-data';
Ember.Route.extend({
model(): any {
return this.store.findAll('my-model');
}
});
Ember.Controller.extend({
actions: {
create(): any {
return this.store.createRecord('my-model');
}
}
});
Ember.DataAdapter.extend({
test() {
this.store.findRecord('my-model', 123);
}
});

View File

@@ -0,0 +1,2 @@
/** Static assertion that `value` has type `T` */
export declare function assertType<T>(value: T): void;

View File

@@ -0,0 +1,29 @@
import Ember from 'ember';
import DS from 'ember-data';
import { assertType } from "./lib/assert";
const Person = DS.Model.extend({
firstName: DS.attr(),
lastName: DS.attr(),
title: DS.attr({ defaultValue: "The default" }),
title2: DS.attr({ defaultValue: () => "The default" }),
fullName: Ember.computed('firstName', 'lastName', function() {
return `${this.get('firstName')} ${this.get('lastName')}`;
})
});
const User = DS.Model.extend({
username: DS.attr('string'),
email: DS.attr('string'),
verified: DS.attr('boolean', { defaultValue: false }),
createdAt: DS.attr('date', {
defaultValue() { return new Date(); }
})
});
const user = User.create({ username: 'dwickern' });
assertType<string>(user.get('id'));
assertType<string>(user.get('username'));
assertType<boolean>(user.get('verified'));
assertType<Date>(user.get('createdAt'));

View File

@@ -0,0 +1,38 @@
import DS from 'ember-data';
import { assertType } from "./lib/assert";
declare const store: DS.Store;
class User extends DS.Model {
username = DS.attr('string');
}
let userRef = store.getReference<User>('user', 1);
// get the record of the reference (null if not yet available)
let user = userRef.value();
if (user !== null) {
assertType<User>(user);
}
// get the identifier of the reference
if (userRef.remoteType() === 'id') {
let id = userRef.id();
assertType<string>(id);
}
// load user (via store.find)
userRef.load().then(user => {
assertType<User>(user);
});
// or trigger a reload
userRef.reload().then(user => {
assertType<User>(user);
});
// provide data for reference
userRef.push({ id: 1, username: '@user' }).then(function(user) {
assertType<User>(user);
userRef.value() === user;
});

View File

@@ -0,0 +1,30 @@
import Ember from 'ember';
import DS from 'ember-data';
declare const store: DS.Store;
const Person = DS.Model.extend({
children: DS.hasMany('folder', { inverse: 'parent' }),
parent: DS.belongsTo('folder', { inverse: 'children' })
});
const Polymorphic = DS.Model.extend({
paymentMethods: DS.hasMany('payment-method', { polymorphic: true })
});
class Comment extends DS.Model {
author = DS.attr('string');
}
class BlogPost extends DS.Model {
title = DS.attr('string');
tag = DS.attr('string');
comments = DS.hasMany<Comment>('comment', { async: true });
relatedPosts = DS.hasMany('post');
}
let blogPost = store.peekRecord<BlogPost>('blog-post', 1);
blogPost!.get('comments').then((comments) => {
// now we can work with the comments
let author: string = comments.get('firstObject')!.get('author');
});

View File

@@ -0,0 +1,38 @@
import Ember from 'ember';
import DS from 'ember-data';
const JsonApi = DS.JSONAPISerializer.extend({});
const Customized = DS.JSONAPISerializer.extend({
serialize(snapshot: DS.Snapshot, options: {}) {
let json: any = this._super(...Array.from(arguments));
json.data.attributes.cost = {
amount: json.data.attributes.amount,
currency: json.data.attributes.currency
};
return json;
},
normalizeResponse(store: DS.Store, primaryModelClass: DS.Model, payload: any, id: string|number, requestType: string) {
payload.data.attributes.amount = payload.data.attributes.cost.amount;
payload.data.attributes.currency = payload.data.attributes.cost.currency;
delete payload.data.attributes.cost;
return this._super(...Array.from(arguments));
}
});
const EmbeddedRecordMixin = DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
author: {
serialize: false,
deserialize: 'records'
},
comments: {
deserialize: 'records',
serialize: 'ids'
}
}
});

View File

@@ -0,0 +1,119 @@
import Ember from 'ember';
import DS from 'ember-data';
import { assertType } from "./lib/assert";
declare const store: DS.Store;
class Post extends DS.Model {
title = DS.attr('string');
}
let post = store.createRecord<Post>('post', {
title: 'Rails is Omakase',
body: 'Lorem ipsum'
});
post.save(); // => POST to '/posts'
post.save().then((saved) => {
assertType<Post>(saved);
});
store.findRecord<Post>('post', 1).then(function(post) {
post.get('title'); // => "Rails is Omakase"
post.set('title', 'A new post');
post.save(); // => PATCH to '/posts/1'
});
class User extends DS.Model {
username = DS.attr('string');
}
store.queryRecord<User>('user', {}).then(function(user) {
let username = user.get('username');
console.log(`Currently logged in as ${username}`);
});
store.findAll('blog-post'); // => GET /blog-posts
store.findAll('author', { reload: true }).then(function(authors) {
authors.getEach('id'); // ['first', 'second']
});
store.findAll('post', {
adapterOptions: { subscribe: false }
});
store.findAll('post', { include: 'comments,comments.author' });
store.peekAll('blog-post'); // => no network request
if (store.hasRecordForId('post', 1)) {
let maybePost = store.peekRecord('post', 1);
if (maybePost) {
maybePost.get('id'); // 1
}
}
class Message extends DS.Model {
hasBeenSeen = DS.attr('boolean');
}
const messages = store.peekAll<Message>('message');
messages.forEach(function(message) {
message.set('hasBeenSeen', true);
});
messages.save();
const people = store.peekAll('person');
people.get('isUpdating'); // false
people.update().then(function() {
people.get('isUpdating'); // false
});
people.get('isUpdating'); // true
const MyRoute = Ember.Route.extend({
model(params: any): any {
return this.store.findRecord('post', params.post_id, {include: 'comments,comments.author'});
}
});
// GET to /users?filter[email]=tomster@example.com
const tom = store.query('user', {
filter: {
email: 'tomster@example.com'
}
}).then(function(users) {
return users.get("firstObject");
});
// GET /users?isAdmin=true
const admins = store.query('user', { isAdmin: true });
admins.then(function() {
console.log(admins.get("length")); // 42
});
admins.update().then(function() {
admins.get('isUpdating'); // false
console.log(admins.get("length")); // 123
});
store.push({
data: [{
id: 1,
type: 'album',
attributes: {
title: 'Fewer Moving Parts',
artist: 'David Bazan',
songCount: 10
},
relationships: {}
}, {
id: 2,
type: 'album',
attributes: {
title: 'Calgary b/w I Can\'t Make You Love Me/Nick Of Time',
artist: 'Bon Iver',
songCount: 2
},
relationships: {}
}]
});
assertType<DS.Adapter>(store.adapterFor('person'));
assertType<DS.Serializer>(store.serializerFor('person'));

View File

@@ -0,0 +1,16 @@
import Ember from 'ember';
import DS from 'ember-data';
class Point extends Ember.Object {
x: number;
y: number;
}
const PointTransform = DS.Transform.extend({
serialize(value: Point): number[] {
return [value.get('x'), value.get('y')];
},
deserialize(value: [ number, number ]): Point {
return Point.create({ x: value[0], y: value[1] });
}
});

View File

@@ -0,0 +1,32 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6",
"dom"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": false,
"baseUrl": "../",
"typeRoots": ["../"],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
"test/lib/assert.ts",
"test/model.ts",
"test/adapter.ts",
"test/serializer.ts",
"test/transform.ts",
"test/relationships.ts",
"test/store.ts",
"test/has-many.ts",
"test/belongs-to.ts",
"test/record-reference.ts",
"test/injections.ts"
]
}

View File

@@ -0,0 +1,16 @@
{
"extends": "dtslint/dt.json",
"rules": {
// Heavy use of Function type in this older package.
"ban-types": false,
"jsdoc-format": false,
"no-misused-new": false,
// not sure what this means
"no-single-declare-module": false,
"object-literal-key-quotes": false,
"only-arrow-functions": false,
"no-empty-interface": false,
"prefer-const": false,
"no-unnecessary-generics": false
}
}