Skip to content
This repository has been archived by the owner on Jul 6, 2018. It is now read-only.

ember-data typings #9

Merged
merged 26 commits into from
Sep 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7dad800
generate ember-data typings
dwickern Aug 13, 2017
649f521
wrap ember types in ambient module declaration
dwickern Aug 13, 2017
b9e3332
extract ember-data module augmentations to ember
dwickern Aug 13, 2017
165ac8e
fix errors
dwickern Aug 13, 2017
2e35e84
add tests from ember guides
dwickern Aug 14, 2017
a380cba
Merge branch 'master' into ember-data
dwickern Aug 28, 2017
daad167
fix test failures
dwickern Aug 28, 2017
5943cbf
Merge branch 'master' into ember-data
dwickern Sep 4, 2017
5a72e15
update ember-data project url
dwickern Sep 4, 2017
1370cab
remove ember-inflector from ember-data typings
dwickern Sep 4, 2017
3db4d8d
add array type param
dwickern Sep 4, 2017
34d5246
update ember-data tslint config
dwickern Sep 4, 2017
7e7bcd3
update DS.Transform typings
dwickern Sep 4, 2017
3bf0234
implement type-safe DS.attr()
dwickern Sep 4, 2017
892f12e
remove private class RecordArrayManager
dwickern Sep 4, 2017
6a9bdfa
add typings for PromiseProxyMixin
dwickern Sep 4, 2017
0100a8b
implement DS.belongsTo/hasMany
dwickern Sep 4, 2017
26634d5
fix tslint errors
dwickern Sep 4, 2017
434e456
implement DS.Store methods
dwickern Sep 5, 2017
846a882
Merge branch 'master' into ember-data
dwickern Sep 9, 2017
d195aec
add ComputedProperty<T> type parameter
dwickern Sep 9, 2017
10328bd
swap order of merged types to work around Microsoft/TypeScript#18354
dwickern Sep 9, 2017
e225411
Merge branch 'master' into ember-data
dwickern Sep 10, 2017
427c4ea
remove inflector typings from ember-data
dwickern Sep 10, 2017
8b1f139
add ember-data typings for computed properties
dwickern Sep 10, 2017
0c8235b
fix test failure
dwickern Sep 16, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,705 changes: 1,705 additions & 0 deletions types/ember-data/index.d.ts

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions types/ember-data/test/adapter.ts
Original file line number Diff line number Diff line change
@@ -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'
};
})
});
16 changes: 16 additions & 0 deletions types/ember-data/test/belongs-to.ts
Original file line number Diff line number Diff line change
@@ -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'));
});
34 changes: 34 additions & 0 deletions types/ember-data/test/has-many.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
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());
assertType<Comment>(post.get('commentsSync').get('firstObject'));
assertType<string>(post.get('commentsSync').get('firstObject').get('text'));

assertType<DS.PromiseArray<Comment>>(post.get('commentsAsync').reload());
assertType<Comment>(post.get('commentsAsync').createRecord());
assertType<Comment>(post.get('commentsAsync').get('firstObject'));
assertType<string>(post.get('commentsAsync').get('firstObject').get('text'));
assertType<boolean>(post.get('commentsAsync').get('isFulfilled'));

post.get('commentsAsync').then(comments => {
assertType<Comment>(comments.get('firstObject'));
assertType<string>(comments.get('firstObject').get('text'));
});

class Polymorphic extends DS.Model {
paymentMethods = DS.hasMany('payment-method', { polymorphic: true });
}
2 changes: 2 additions & 0 deletions types/ember-data/test/lib/assert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** Static assertion that `value` has type `T` */
export declare function assertType<T>(value: T): void;
29 changes: 29 additions & 0 deletions types/ember-data/test/model.ts
Original file line number Diff line number Diff line change
@@ -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'));
38 changes: 38 additions & 0 deletions types/ember-data/test/record-reference.ts
Original file line number Diff line number Diff line change
@@ -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;
});
24 changes: 24 additions & 0 deletions types/ember-data/test/relationships.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Ember from 'ember';
import DS from 'ember-data';

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 })
});

const BlogPost = DS.Model.extend({
title: DS.attr('string'),
tag: DS.attr('string'),
comments: DS.hasMany('comment', { async: true }),
relatedPosts: DS.hasMany('post')
});

let blogPost = this.get('store').peekRecord('blog-post', 1);

blogPost.get('comments').then((comments: any[]) => {
// now we can work with the comments
});
38 changes: 38 additions & 0 deletions types/ember-data/test/serializer.ts
Original file line number Diff line number Diff line change
@@ -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 = 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'
}
}
});
119 changes: 119 additions & 0 deletions types/ember-data/test/store.ts
Original file line number Diff line number Diff line change
@@ -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) {
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'));
16 changes: 16 additions & 0 deletions types/ember-data/test/transform.ts
Original file line number Diff line number Diff line change
@@ -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] });
}
});
28 changes: 28 additions & 0 deletions types/ember-data/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6",
"dom"
],
"noImplicitAny": true,
"noImplicitThis": false,
"strictNullChecks": true,
"baseUrl": "../",
"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"
]
}
15 changes: 15 additions & 0 deletions types/ember-data/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"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
}
}
Loading