ember-data: improve snapshot typings and add test

This commit is contained in:
Derek Wickern
2018-02-19 10:39:28 -08:00
parent 7e6d2ba328
commit 3e54d1924e
2 changed files with 93 additions and 27 deletions
+37 -27
View File
@@ -13,6 +13,32 @@ declare module 'ember-data' {
export interface ModelRegistry {}
export interface AdapterRegistry {}
export interface SerializerRegistry {}
export interface TransformRegistry {
'string': string;
'boolean': boolean;
'number': number;
'date': Date;
}
type AttributesFor<Model> = keyof Model; // TODO: filter to attr properties only (TS 2.8)
type RelationshipsFor<Model> = keyof Model; // TODO: filter to hasMany/belongsTo properties only (TS 2.8)
interface AttributeMeta<Model extends DS.Model> {
type: keyof TransformRegistry;
options: object;
name: AttributesFor<Model>;
parentType: Model;
isAttribute: true;
}
interface RelationshipMeta<Model extends DS.Model> {
key: RelationshipsFor<Model>;
kind: 'belongsTo' | 'hasMany';
type: keyof ModelRegistry;
options: object;
name: string;
parentType: Model;
isRelationship: true;
}
namespace DS {
/**
@@ -82,27 +108,11 @@ declare module 'ember-data' {
* `boolean` and `date`. You can define your own transforms by subclassing
* [DS.Transform](/api/data/classes/DS.Transform.html).
*/
function attr(
type: 'string',
options?: AttrOptions<string>
): Ember.ComputedProperty<string>;
function attr(
type: 'boolean',
options?: AttrOptions<boolean>
): Ember.ComputedProperty<boolean>;
function attr(
type: 'number',
options?: AttrOptions<number>
): Ember.ComputedProperty<number>;
function attr(
type: 'date',
options?: AttrOptions<Date>
): Ember.ComputedProperty<Date>;
function attr<T>(
type: string,
options?: AttrOptions<T>
): Ember.ComputedProperty<T>;
function attr<T>(options?: AttrOptions<T>): Ember.ComputedProperty<T>;
function attr<K extends keyof TransformRegistry>(
type: K,
options?: AttrOptions<TransformRegistry[K]>
): Ember.ComputedProperty<TransformRegistry[K]>;
function attr(options?: AttrOptions): Ember.ComputedProperty<any>;
/**
* WARNING: This interface is likely to change in order to accomodate https://github.com/emberjs/rfcs/pull/4
* ## Using BuildURLMixin
@@ -942,7 +952,7 @@ declare module 'ember-data' {
/**
* Returns the value of an attribute.
*/
attr<L extends keyof ModelRegistry[K]>(keyName: L): ModelRegistry[K][L];
attr<L extends AttributesFor<ModelRegistry[K]>>(keyName: L): ModelRegistry[K][L];
/**
* Returns all attributes and their corresponding values.
*/
@@ -954,18 +964,18 @@ declare module 'ember-data' {
/**
* Returns the current value of a belongsTo relationship.
*/
belongsTo<L extends keyof ModelRegistry[K]>(
belongsTo<L extends RelationshipsFor<ModelRegistry[K]>>(
keyName: L,
options?: {}
): Snapshot<K>['record'][L] | string | null | undefined;
/**
* Returns the current value of a hasMany relationship.
*/
hasMany<L extends keyof ModelRegistry[K]>(
hasMany<L extends RelationshipsFor<ModelRegistry[K]>>(
keyName: L,
options?: { ids: false }
): Array<Snapshot<K>['record'][L]> | undefined;
hasMany<L extends keyof ModelRegistry[K]>(
hasMany<L extends RelationshipsFor<ModelRegistry[K]>>(
keyName: L,
options: { ids: true }
): string[] | undefined;
@@ -973,12 +983,12 @@ declare module 'ember-data' {
* Iterates through all the attributes of the model, calling the passed
* function on each attribute.
*/
eachAttribute(callback: Function, binding: {}): any;
eachAttribute<M extends ModelRegistry[K]>(callback: (key: keyof M, meta: AttributeMeta<M>) => void, binding?: {}): any;
/**
* Iterates through all the relationships of the model, calling the passed
* function on each relationship.
*/
eachRelationship(callback: Function, binding: {}): any;
eachRelationship<M extends ModelRegistry[K]>(callback: (key: keyof M, meta: RelationshipMeta<M>) => void, binding?: {}): any;
/**
* Serializes the snapshot using the serializer for the model.
*/
+56
View File
@@ -37,3 +37,59 @@ const EmbeddedRecordMixin = DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, {
}
}
});
class Message extends DS.Model.extend({
title: DS.attr(),
body: DS.attr(),
author: DS.belongsTo('user'),
comments: DS.belongsTo('comment')
}) {}
declare module 'ember-data' {
interface ModelRegistry {
'message-for-serializer': Message;
}
}
interface CustomSerializerOptions {
includeId: boolean;
}
const SerializerUsingSnapshots = DS.RESTSerializer.extend({
serialize(snapshot: DS.Snapshot<'message-for-serializer'>, options: CustomSerializerOptions) {
let json: any = {
POST_TTL: snapshot.attr('title'),
POST_BDY: snapshot.attr('body'),
POST_CMS: snapshot.hasMany('comments', { ids: true })
};
if (options.includeId) {
json.POST_ID_ = snapshot.id;
}
return json;
}
});
DS.Serializer.extend({
serialize(snapshot: DS.Snapshot<'message-for-serializer'>, options: {}) {
let json: any = {
id: snapshot.id
};
snapshot.eachAttribute((key, attribute) => {
json[key] = snapshot.attr(key);
});
snapshot.eachRelationship((key, relationship) => {
if (relationship.kind === 'belongsTo') {
json[key] = snapshot.belongsTo(key, { id: true });
} else if (relationship.kind === 'hasMany') {
json[key] = snapshot.hasMany(key, { ids: true });
}
});
return json;
},
});