diff --git a/types/ember-data/index.d.ts b/types/ember-data/index.d.ts index a59ab4de97..3a44b2905e 100644 --- a/types/ember-data/index.d.ts +++ b/types/ember-data/index.d.ts @@ -2,12 +2,18 @@ // Project: https://github.com/emberjs/data // Definitions by: Derek Wickern // Mike North +// Chris Krycho // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.4 -declare module "ember-data" { - import Ember from "ember"; +declare module 'ember-data' { + import Ember from 'ember'; import RSVP from 'rsvp'; + + export interface ModelRegistry {} + export interface AdapterRegistry {} + export interface SerializerRegistry {} + namespace DS { /** * Convert an hash of errors into an array with errors in JSON-API format. @@ -21,47 +27,47 @@ declare module "ember-data" { * `DS.belongsTo` is used to define One-To-One and One-To-Many * relationships on a [DS.Model](/api/data/classes/DS.Model.html). */ - function belongsTo( - modelName: string, + function belongsTo( + modelName: K, options: { async: false; inverse?: string | null; polymorphic?: boolean; } - ): Ember.ComputedProperty; - function belongsTo( - modelName: string, + ): Ember.ComputedProperty; + function belongsTo( + modelName: K, options?: { async?: true; inverse?: string | null; polymorphic?: boolean; } - ): Ember.ComputedProperty>; + ): Ember.ComputedProperty>; /** * `DS.hasMany` is used to define One-To-Many and Many-To-Many * relationships on a [DS.Model](/api/data/classes/DS.Model.html). */ - function hasMany( - type: string, + function hasMany( + type: K, options: { async: false; inverse?: string | null; polymorphic?: boolean; } - ): Ember.ComputedProperty>; - function hasMany( - type: string, + ): Ember.ComputedProperty>; + function hasMany( + type: K, options?: { async?: true; inverse?: string | null; polymorphic?: boolean; } - ): Ember.ComputedProperty>; + ): Ember.ComputedProperty>; /** * This method normalizes a modelName into the format Ember Data uses * internally. */ - function normalizeModelName(modelName: string): string; + function normalizeModelName(modelName: K): string; const VERSION: string; interface AttrOptions { @@ -77,19 +83,19 @@ declare module "ember-data" { * [DS.Transform](/api/data/classes/DS.Transform.html). */ function attr( - type: "string", + type: 'string', options?: AttrOptions ): Ember.ComputedProperty; function attr( - type: "boolean", + type: 'boolean', options?: AttrOptions ): Ember.ComputedProperty; function attr( - type: "number", + type: 'number', options?: AttrOptions ): Ember.ComputedProperty; function attr( - type: "date", + type: 'date', options?: AttrOptions ): Ember.ComputedProperty; function attr( @@ -118,89 +124,89 @@ declare module "ember-data" { /** * Builds a URL for a given type and optional ID. */ - buildURL( - modelName?: string, + buildURL( + modelName?: K, id?: string | any[] | {} | null, - snapshot?: Snapshot | any[] | null, + snapshot?: Snapshot | any[] | null, requestType?: string, query?: {} ): string; /** * Builds a URL for a `store.findRecord(type, id)` call. */ - urlForFindRecord( + urlForFindRecord( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for a `store.findAll(type)` call. */ - urlForFindAll( - modelName: string, - snapshot: SnapshotRecordArray + urlForFindAll( + modelName: K, + snapshot: SnapshotRecordArray ): string; /** * Builds a URL for a `store.query(type, query)` call. */ - urlForQuery(query: {}, modelName: string): string; + urlForQuery(query: {}, modelName: K): string; /** * Builds a URL for a `store.queryRecord(type, query)` call. */ - urlForQueryRecord(query: {}, modelName: string): string; + urlForQueryRecord(query: {}, modelName: K): string; /** * Builds a URL for coalesceing multiple `store.findRecord(type, id)` * records into 1 request when the adapter's `coalesceFindRequests` * property is true. */ - urlForFindMany( + urlForFindMany( ids: any[], - modelName: string, + modelName: K, snapshots: any[] ): string; /** * Builds a URL for fetching a async hasMany relationship when a url * is not provided by the server. */ - urlForFindHasMany( + urlForFindHasMany( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for fetching a async belongsTo relationship when a url * is not provided by the server. */ - urlForFindBelongsTo( + urlForFindBelongsTo( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for a `record.save()` call when the record was created * locally using `store.createRecord()`. */ - urlForCreateRecord(modelName: string, snapshot: Snapshot): string; + urlForCreateRecord(modelName: K, snapshot: Snapshot): string; /** * Builds a URL for a `record.save()` call when the record has been update locally. */ - urlForUpdateRecord( + urlForUpdateRecord( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for a `record.save()` call when the record has been deleted locally. */ - urlForDeleteRecord( + urlForDeleteRecord( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Determines the pathname for a given type. */ - pathForType(modelName: string): string; + pathForType(modelName: K): string; } /** * A `DS.AdapterError` is used by an adapter to signal that an error occurred @@ -502,11 +508,11 @@ declare module "ember-data" { /** * Get the reference for the specified belongsTo relationship. */ - belongsTo(name: string): BelongsToReference; + belongsTo(name: keyof ModelRegistry): BelongsToReference; /** * Get the reference for the specified hasMany relationship. */ - hasMany(name: string): HasManyReference; + hasMany(name: keyof ModelRegistry): HasManyReference; /** * Given a callback, iterates over each of the relationships in the model, * invoking the callback with the name of each relationship and its relationship @@ -517,15 +523,15 @@ declare module "ember-data" { * Represents the model's class name as a string. This can be used to look up the model's class name through * `DS.Store`'s modelFor method. */ - static modelName: string; + static modelName: keyof ModelRegistry; /** * For a given relationship name, returns the model type of the relationship. */ - static typeForRelationship(name: string, store: Store): Model; + static typeForRelationship(name: K, store: Store): ModelRegistry[K]; /** * Find the relationship which is the inverse of the one asked for. */ - static inverseFor(name: string, store: Store): {}; + static inverseFor(name: K, store: Store): {}; /** * The model's relationships as a map, keyed on the type of the * relationship. The value of each entry is an array containing a descriptor @@ -854,7 +860,7 @@ declare module "ember-data" { */ interface PromiseArray extends Ember.ArrayProxy, - Ember.PromiseProxyMixin> {} + Ember.PromiseProxyMixin> {} class PromiseArray {} /** * A `PromiseObject` is an object that acts like both an `Ember.Object` @@ -865,7 +871,7 @@ declare module "ember-data" { */ interface PromiseObject extends Ember.ObjectProxy, - Ember.PromiseProxyMixin> {} + Ember.PromiseProxyMixin> {} class PromiseObject {} /** * A PromiseManyArray is a PromiseArray that also proxies certain method calls @@ -885,7 +891,7 @@ declare module "ember-data" { */ createRecord(inputProperties?: {}): T; } - class SnapshotRecordArray { + class SnapshotRecordArray { /** * Number of records in the array */ @@ -905,18 +911,18 @@ declare module "ember-data" { /** * The type of the underlying records for the snapshots in the array, as a DS.Model */ - type: Model; + type: ModelRegistry[K]; /** * Get snapshots of the underlying record array */ snapshots(): any[]; } - class Snapshot { + class Snapshot { /** * The underlying record for this snapshot. Can be used to access methods and * properties defined on the record. */ - record: Model; + record: ModelRegistry[K]; /** * The id of the snapshot's underlying record */ @@ -928,15 +934,15 @@ declare module "ember-data" { /** * The name of the type of the underlying record for this snapshot, as a string. */ - modelName: string; + modelName: K; /** * The type of the underlying record for this snapshot, as a DS.Model. */ - type: Model; + type: ModelRegistry[K]; /** * Returns the value of an attribute. */ - attr(keyName: string): {}; + attr(keyName: L): {}; /** * Returns all attributes and their corresponding values. */ @@ -948,14 +954,14 @@ declare module "ember-data" { /** * Returns the current value of a belongsTo relationship. */ - belongsTo( - keyName: string, + belongsTo( + keyName: L, options?: {} - ): Snapshot | string | null | undefined; + ): Snapshot | string | null | undefined; /** * Returns the current value of a hasMany relationship. */ - hasMany(keyName: string, options?: {}): any[] | undefined; + hasMany(keyName: L, options?: {}): any[] | undefined; /** * Iterates through all the attributes of the model, calling the passed * function on each attribute. @@ -971,6 +977,7 @@ declare module "ember-data" { */ serialize(options: {}): {}; } + /** * The store contains all of the data for records loaded from the server. * It is also responsible for creating instances of `DS.Model` that wrap @@ -988,10 +995,10 @@ declare module "ember-data" { * Create a new record in the current store. The properties passed * to this method are set on the newly created record. */ - createRecord( - modelName: string, + createRecord( + modelName: K, inputProperties?: {} - ): T; + ): ModelRegistry[K]; /** * For symmetry, a record can be deleted via the store. */ @@ -1004,83 +1011,86 @@ declare module "ember-data" { /** * This method returns a record for a given type and id combination. */ - findRecord( - modelName: string, + findRecord( + modelName: K, id: string | number, options?: {} - ): PromiseObject & T; + ): PromiseObject & ModelRegistry[K]; /** * Get the reference for the specified record. */ - getReference( - modelName: string, + getReference( + modelName: K, id: string | number - ): RecordReference; + ): RecordReference; /** * Get a record by a given type and ID without triggering a fetch. */ - peekRecord( - modelName: string, + peekRecord( + modelName: K, id: string | number - ): T | null; + ): ModelRegistry[K] | null; /** * This method returns true if a record for a given modelName and id is already * loaded in the store. Use this function to know beforehand if a findRecord() * will result in a request or that it will be a cache hit. */ - hasRecordForId(modelName: string, id: string | number): boolean; + hasRecordForId( + modelName: K, + id: string | number + ): boolean; /** * This method delegates a query to the adapter. This is the one place where * adapter-level semantics are exposed to the application. */ - query( - modelName: string, + query( + modelName: K, query: any - ): AdapterPopulatedRecordArray & PromiseArray; + ): AdapterPopulatedRecordArray & PromiseArray; /** * This method makes a request for one record, where the `id` is not known * beforehand (if the `id` is known, use [`findRecord`](#method_findRecord) * instead). */ - queryRecord( - modelName: string, + queryRecord( + modelName: K, query: any - ): RSVP.Promise; + ): RSVP.Promise; /** * `findAll` asks the adapter's `findAll` method to find the records for the * given type, and returns a promise which will resolve with all records of * this type present in the store, even if the adapter only returns a subset * of them. */ - findAll( - modelName: string, + findAll( + modelName: K, options?: { reload?: boolean; backgroundReload?: boolean; include?: string; adapterOptions?: any; } - ): PromiseArray; + ): PromiseArray; /** * This method returns a filtered array that contains all of the * known records for a given type in the store. */ - peekAll(modelName: string): RecordArray; + peekAll(modelName: K): RecordArray; /** * This method unloads all records in the store. * It schedules unloading to happen during the next run loop. */ - unloadAll(modelName: string): void; + unloadAll(modelName: K): void; /** * DEPRECATED: * This method has been deprecated and is an alias for store.hasRecordForId, which should * be used instead. */ - recordIsLoaded(modelName: string, id: string): boolean; + recordIsLoaded(modelName: K, id: string): boolean; /** * Returns the model class for the particular `modelName`. */ - modelFor(modelName: string): M; + modelFor(modelName: K): ModelRegistry[K]; /** * Push some data for a given type into the store. */ @@ -1088,25 +1098,25 @@ declare module "ember-data" { /** * Push some raw data into the store. */ - pushPayload(modelName: string, inputPayload: {}): any; + pushPayload(modelName: K, inputPayload: {}): any; pushPayload(inputPayload: {}): any; /** * `normalize` converts a json payload into the normalized form that * [push](#method_push) expects. */ - normalize(modelName: string, payload: {}): {}; + normalize(modelName: K, payload: {}): {}; /** * Returns an instance of the adapter for a given type. For * example, `adapterFor('person')` will return an instance of * `App.PersonAdapter`. */ - adapterFor(modelName: string): A; + adapterFor(modelName: K): AdapterRegistry[K]; /** * Returns an instance of the serializer for a given type. For * example, `serializerFor('person')` will return an instance of * `App.PersonSerializer`. */ - serializerFor(modelName: string): S; + serializerFor(modelName: K): SerializerRegistry[K]; } /** * The `JSONAPIAdapter` is the default adapter used by Ember Data. It @@ -1132,7 +1142,11 @@ declare module "ember-data" { /** * Takes a URL, an HTTP method and a hash of data, and makes an HTTP request. */ - ajax(url: string, type: string, options?: object): RSVP.Promise; + ajax( + url: string, + type: string, + options?: object + ): RSVP.Promise; /** * Generate ajax options */ @@ -1170,38 +1184,42 @@ declare module "ember-data" { * Called by the store in order to fetch the JSON for a given * type and ID. */ - findRecord( + findRecord( store: Store, - type: Model, + type: ModelRegistry[K], id: string, - snapshot: Snapshot + snapshot: Snapshot ): RSVP.Promise; /** * Called by the store in order to fetch a JSON array for all * of the records for a given type. */ - findAll( + findAll( store: Store, - type: Model, + type: ModelRegistry[K], sinceToken: string, - snapshotRecordArray: SnapshotRecordArray + snapshotRecordArray: SnapshotRecordArray ): RSVP.Promise; /** * Called by the store in order to fetch a JSON array for * the records that match a particular query. */ - query(store: Store, type: Model, query: {}): RSVP.Promise; + query(store: Store, type: ModelRegistry[K], query: {}): RSVP.Promise; /** * Called by the store in order to fetch a JSON object for * the record that matches a particular query. */ - queryRecord(store: Store, type: Model, query: {}): RSVP.Promise; + queryRecord( + store: Store, + type: ModelRegistry[K], + query: {} + ): RSVP.Promise; /** * Called by the store in order to fetch several records together if `coalesceFindRequests` is true */ - findMany( + findMany( store: Store, - type: Model, + type: ModelRegistry[K], ids: any[], snapshots: any[] ): RSVP.Promise; @@ -1210,9 +1228,9 @@ declare module "ember-data" { * the unloaded records in a has-many relationship that were originally * specified as a URL (inside of `links`). */ - findHasMany( + findHasMany( store: Store, - snapshot: Snapshot, + snapshot: Snapshot, url: string, relationship: {} ): RSVP.Promise; @@ -1221,36 +1239,36 @@ declare module "ember-data" { * belongs-to relationship that was originally specified as a URL (inside of * `links`). */ - findBelongsTo( + findBelongsTo( store: Store, - snapshot: Snapshot, + snapshot: Snapshot, url: string ): RSVP.Promise; /** * Called by the store when a newly created record is * saved via the `save` method on a model record instance. */ - createRecord( + createRecord( store: Store, - type: Model, - snapshot: Snapshot + type: ModelRegistry[K], + snapshot: Snapshot ): RSVP.Promise; /** * Called by the store when an existing record is saved * via the `save` method on a model record instance. */ - updateRecord( + updateRecord( store: Store, - type: Model, - snapshot: Snapshot + type: ModelRegistry[K], + snapshot: Snapshot ): RSVP.Promise; /** * Called by the store when a record is deleted. */ - deleteRecord( + deleteRecord( store: Store, - type: Model, - snapshot: Snapshot + type: ModelRegistry[K], + snapshot: Snapshot ): RSVP.Promise; /** * Organize records into groups, each of which is to be passed to separate @@ -1295,89 +1313,89 @@ declare module "ember-data" { /** * Builds a URL for a given type and optional ID. */ - buildURL( - modelName?: string, + buildURL( + modelName?: K, id?: string | any[] | {} | null, - snapshot?: Snapshot | any[] | null, + snapshot?: Snapshot | any[] | null, requestType?: string, query?: {} ): string; /** * Builds a URL for a `store.findRecord(type, id)` call. */ - urlForFindRecord( + urlForFindRecord( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for a `store.findAll(type)` call. */ - urlForFindAll( - modelName: string, - snapshot: SnapshotRecordArray + urlForFindAll( + modelName: K, + snapshot: SnapshotRecordArray ): string; /** * Builds a URL for a `store.query(type, query)` call. */ - urlForQuery(query: {}, modelName: string): string; + urlForQuery(query: {}, modelName: K): string; /** * Builds a URL for a `store.queryRecord(type, query)` call. */ - urlForQueryRecord(query: {}, modelName: string): string; + urlForQueryRecord(query: {}, modelName: K): string; /** * Builds a URL for coalesceing multiple `store.findRecord(type, id)` * records into 1 request when the adapter's `coalesceFindRequests` * property is true. */ - urlForFindMany( + urlForFindMany( ids: any[], - modelName: string, + modelName: K, snapshots: any[] ): string; /** * Builds a URL for fetching a async hasMany relationship when a url * is not provided by the server. */ - urlForFindHasMany( + urlForFindHasMany( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for fetching a async belongsTo relationship when a url * is not provided by the server. */ - urlForFindBelongsTo( + urlForFindBelongsTo( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for a `record.save()` call when the record was created * locally using `store.createRecord()`. */ - urlForCreateRecord(modelName: string, snapshot: Snapshot): string; + urlForCreateRecord(modelName: K, snapshot: Snapshot): string; /** * Builds a URL for a `record.save()` call when the record has been update locally. */ - urlForUpdateRecord( + urlForUpdateRecord( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Builds a URL for a `record.save()` call when the record has been deleted locally. */ - urlForDeleteRecord( + urlForDeleteRecord( id: string, - modelName: string, - snapshot: Snapshot + modelName: K, + snapshot: Snapshot ): string; /** * Determines the pathname for a given type. */ - pathForType(modelName: string): string; + pathForType(modelName: K): string; } /** * ## Using Embedded Records @@ -1391,16 +1409,16 @@ declare module "ember-data" { /** * Serialize `belongsTo` relationship when it is configured as an embedded object. */ - serializeBelongsTo( - snapshot: Snapshot, + serializeBelongsTo( + snapshot: Snapshot, json: {}, relationship: {} ): any; /** * Serializes `hasMany` relationships when it is configured as embedded objects. */ - serializeHasMany( - snapshot: Snapshot, + serializeHasMany( + snapshot: Snapshot, json: {}, relationship: {} ): any; @@ -1408,9 +1426,9 @@ declare module "ember-data" { * When serializing an embedded record, modify the property (in the json payload) * that refers to the parent record (foreign key for relationship). */ - removeEmbeddedForeignKey( - snapshot: Snapshot, - embeddedSnapshot: Snapshot, + removeEmbeddedForeignKey( + snapshot: Snapshot, + embeddedSnapshot: Snapshot, relationship: {}, json: {} ): any; @@ -1428,7 +1446,7 @@ declare module "ember-data" { /** * Converts the model name to a pluralized version of the model name. */ - payloadKeyFromModelName(modelName: string): string; + payloadKeyFromModelName(modelName: K): string; /** * `keyForAttribute` can be used to define rules for how to convert an * attribute name in your model to a key in your JSON. @@ -1458,7 +1476,7 @@ declare module "ember-data" { * `payloadTypeFromModelName` can be used to change the mapping for the type in * the payload, taken from the model name. */ - payloadTypeFromModelName(modelname: string): string; + payloadTypeFromModelName(modelName: K): string; } /** * Ember Data 2.0 Serializer: @@ -1620,8 +1638,8 @@ declare module "ember-data" { /** * Check if the given hasMany relationship should be serialized */ - shouldSerializeHasMany( - snapshot: Snapshot, + shouldSerializeHasMany( + snapshot: Snapshot, key: string, relationshipType: string ): boolean; @@ -1629,7 +1647,7 @@ declare module "ember-data" { * Called when a record is saved in order to convert the * record into JSON. */ - serialize(snapshot: Snapshot, options: {}): {}; + serialize(snapshot: Snapshot, options: {}): {}; /** * You can use this method to customize how a serialized record is added to the complete * JSON hash to be sent to the server. By default the JSON Serializer does not namespace @@ -1638,18 +1656,18 @@ declare module "ember-data" { * Otherwise you can override this method to customize how the record is added to the hash. * The hash property should be modified by reference. */ - serializeIntoHash( + serializeIntoHash( hash: {}, - typeClass: Model, - snapshot: Snapshot, + typeClass: ModelRegistry[K], + snapshot: Snapshot, options?: {} ): any; /** * `serializeAttribute` can be used to customize how `DS.attr` * properties are serialized */ - serializeAttribute( - snapshot: Snapshot, + serializeAttribute( + snapshot: Snapshot, json: {}, key: string, attribute: {} @@ -1658,8 +1676,8 @@ declare module "ember-data" { * `serializeBelongsTo` can be used to customize how `DS.belongsTo` * properties are serialized. */ - serializeBelongsTo( - snapshot: Snapshot, + serializeBelongsTo( + snapshot: Snapshot, json: {}, relationship: {} ): any; @@ -1667,8 +1685,8 @@ declare module "ember-data" { * `serializeHasMany` can be used to customize how `DS.hasMany` * properties are serialized. */ - serializeHasMany( - snapshot: Snapshot, + serializeHasMany( + snapshot: Snapshot, json: {}, relationship: {} ): any; @@ -1678,8 +1696,8 @@ declare module "ember-data" { * `{ polymorphic: true }` is pass as the second argument to the * `DS.belongsTo` function. */ - serializePolymorphicType( - snapshot: Snapshot, + serializePolymorphicType( + snapshot: Snapshot, json: {}, relationship: {} ): any; @@ -1726,7 +1744,7 @@ declare module "ember-data" { * serializeId can be used to customize how id is serialized * For example, your server may expect integer datatype of id */ - serializeId(snapshot: Snapshot, json: {}, primaryKey: string): any; + serializeId(snapshot: Snapshot, json: {}, primaryKey: string): any; } /** * Normally, applications will use the `RESTSerializer` by implementing @@ -1764,17 +1782,17 @@ declare module "ember-data" { * Called when a record is saved in order to convert the * record into JSON. */ - serialize(snapshot: Snapshot, options: {}): {}; + serialize(snapshot: Snapshot, options: {}): {}; /** * You can use this method to customize the root keys serialized into the JSON. * The hash property should be modified by reference (possibly using something like _.extend) * By default the REST Serializer sends the modelName of a model, which is a camelized * version of the name. */ - serializeIntoHash( + serializeIntoHash( hash: {}, typeClass: Model, - snapshot: Snapshot, + snapshot: Snapshot, options?: {} ): any; /** @@ -1782,14 +1800,14 @@ declare module "ember-data" { * request. By default, the RESTSerializer returns a camelized version of the * model's name. */ - payloadKeyFromModelName(modelName: string): string; + payloadKeyFromModelName(modelName: K): string; /** * You can use this method to customize how polymorphic objects are serialized. * By default the REST Serializer creates the key by appending `Type` to * the attribute and value from the model's camelcased model name. */ - serializePolymorphicType( - snapshot: Snapshot, + serializePolymorphicType( + snapshot: Snapshot, json: {}, relationship: {} ): any; @@ -1811,7 +1829,7 @@ declare module "ember-data" { * `payloadTypeFromModelName` can be used to change the mapping for the type in * the payload, taken from the model name. */ - payloadTypeFromModelName(modelName: string): string; + payloadTypeFromModelName(modelName: K): string; } /** * The `DS.BooleanTransform` class is used to serialize and deserialize @@ -1883,27 +1901,27 @@ declare module "ember-data" { * method should return a promise that will resolve to a JavaScript object that will be * normalized by the serializer. */ - findRecord( + findRecord( store: Store, - type: Model, + type: ModelRegistry[K], id: string, - snapshot: Snapshot + snapshot: Snapshot ): RSVP.Promise; /** * The `findAll()` method is used to retrieve all records for a given type. */ - findAll( + findAll( store: Store, - type: Model, + type: ModelRegistry[K], sinceToken: string, - snapshotRecordArray: SnapshotRecordArray + snapshotRecordArray: SnapshotRecordArray ): RSVP.Promise; /** * This method is called when you call `query` on the store. */ - query( + query( store: Store, - type: Model, + type: ModelRegistry[K], query: {}, recordArray: AdapterPopulatedRecordArray ): RSVP.Promise; @@ -1911,48 +1929,52 @@ declare module "ember-data" { * The `queryRecord()` method is invoked when the store is asked for a single * record through a query object. */ - queryRecord(store: Store, type: Model, query: {}): RSVP.Promise; + queryRecord( + store: Store, + type: ModelRegistry[K], + query: {} + ): RSVP.Promise; /** * If the globally unique IDs for your records should be generated on the client, * implement the `generateIdForRecord()` method. This method will be invoked * each time you create a new record, and the value returned from it will be * assigned to the record's `primaryKey`. */ - generateIdForRecord( + generateIdForRecord( store: Store, - type: Model, + type: ModelRegistry[K], inputProperties: {} ): string | number; /** * Proxies to the serializer's `serialize` method. */ - serialize(snapshot: Snapshot, options: {}): {}; + serialize(snapshot: Snapshot, options: {}): {}; /** * Implement this method in a subclass to handle the creation of * new records. */ - createRecord( + createRecord( store: Store, - type: Model, - snapshot: Snapshot + type: ModelRegistry[K], + snapshot: Snapshot ): RSVP.Promise; /** * Implement this method in a subclass to handle the updating of * a record. */ - updateRecord( + updateRecord( store: Store, - type: Model, - snapshot: Snapshot + type: ModelRegistry[K], + snapshot: Snapshot ): RSVP.Promise; /** * Implement this method in a subclass to handle the deletion of * a record. */ - deleteRecord( + deleteRecord( store: Store, - type: Model, - snapshot: Snapshot + type: ModelRegistry[K], + snapshot: Snapshot ): RSVP.Promise; /** * By default the store will try to coalesce all `fetchRecord` calls within the same runloop @@ -1966,9 +1988,9 @@ declare module "ember-data" { * requests to find multiple records at once if coalesceFindRequests * is true. */ - findMany( + findMany( store: Store, - type: Model, + type: ModelRegistry[K], ids: any[], snapshots: any[] ): RSVP.Promise; @@ -1982,33 +2004,33 @@ declare module "ember-data" { * reload a record from the adapter when a record is requested by * `store.findRecord`. */ - shouldReloadRecord(store: Store, snapshot: Snapshot): boolean; + shouldReloadRecord(store: Store, snapshot: Snapshot): boolean; /** * This method is used by the store to determine if the store should * reload all records from the adapter when records are requested by * `store.findAll`. */ - shouldReloadAll( + shouldReloadAll( store: Store, - snapshotRecordArray: SnapshotRecordArray + snapshotRecordArray: SnapshotRecordArray ): boolean; /** * This method is used by the store to determine if the store should * reload a record after the `store.findRecord` method resolves a * cached record. */ - shouldBackgroundReloadRecord( + shouldBackgroundReloadRecord( store: Store, - snapshot: Snapshot + snapshot: Snapshot ): boolean; /** * This method is used by the store to determine if the store should * reload a record array after the `store.findAll` method resolves * with a cached record array. */ - shouldBackgroundReloadAll( + shouldBackgroundReloadAll( store: Store, - snapshotRecordArray: SnapshotRecordArray + snapshotRecordArray: SnapshotRecordArray ): boolean; } /** @@ -2038,7 +2060,7 @@ declare module "ember-data" { * The `serialize` method is used when a record is saved in order to convert * the record into the form that your external data source expects. */ - serialize(snapshot: Snapshot, options: {}): {}; + serialize(snapshot: Snapshot, options: {}): {}; /** * The `normalize` method is used to convert a payload received from your * external data source into the normalized form `store.push()` expects. You @@ -2048,11 +2070,12 @@ declare module "ember-data" { normalize(typeClass: Model, hash: {}): {}; } } + export default DS; } -declare module "ember" { - import DS from "ember-data"; +declare module 'ember' { + import DS from 'ember-data'; namespace Ember { /* * The store is automatically injected into these objects @@ -2069,91 +2092,101 @@ declare module "ember" { store: DS.Store; } } + + // It is also available to inject anywhere + module '@ember/service' { + interface Registry { + 'store': DS.Store; + } + } } declare module 'ember-data/adapter' { - import DS from 'ember-data'; - export default DS.Adapter; + import DS from 'ember-data'; + export default DS.Adapter; + export { AdapterRegistry } from 'ember-data'; } declare module 'ember-data/adapters/errors' { - import DS from 'ember-data'; - const AdapterError: typeof DS.AdapterError; - const InvalidError: typeof DS.InvalidError; - const UnauthorizedError: typeof DS.UnauthorizedError; - const ForbiddenError: typeof DS.ForbiddenError; - const NotFoundError: typeof DS.NotFoundError; - const ConflictError: typeof DS.ConflictError; - const ServerError: typeof DS.ServerError; - const TimeoutError: typeof DS.TimeoutError; - const AbortError: typeof DS.AbortError; - const errorsHashToArray: typeof DS.errorsHashToArray; - const errorsArrayToHash: typeof DS.errorsArrayToHash; + import DS from 'ember-data'; + const AdapterError: typeof DS.AdapterError; + const InvalidError: typeof DS.InvalidError; + const UnauthorizedError: typeof DS.UnauthorizedError; + const ForbiddenError: typeof DS.ForbiddenError; + const NotFoundError: typeof DS.NotFoundError; + const ConflictError: typeof DS.ConflictError; + const ServerError: typeof DS.ServerError; + const TimeoutError: typeof DS.TimeoutError; + const AbortError: typeof DS.AbortError; + const errorsHashToArray: typeof DS.errorsHashToArray; + const errorsArrayToHash: typeof DS.errorsArrayToHash; } declare module 'ember-data/adapters/json-api' { - import DS from 'ember-data'; - export default DS.JSONAPIAdapter; + import DS from 'ember-data'; + export default DS.JSONAPIAdapter; } declare module 'ember-data/adapters/rest' { - import DS from 'ember-data'; - export default DS.RESTAdapter; + import DS from 'ember-data'; + export default DS.RESTAdapter; } declare module 'ember-data/attr' { - import DS from 'ember-data'; - export default DS.attr; + import DS from 'ember-data'; + export default DS.attr; } declare module 'ember-data/model' { - import DS from 'ember-data'; - export default DS.Model; + import DS from 'ember-data'; + export default DS.Model; + export { ModelRegistry } from 'ember-data'; } declare module 'ember-data/relationships' { - import DS from 'ember-data'; - const hasMany: typeof DS.hasMany; - const belongsTo: typeof DS.belongsTo; + import DS from 'ember-data'; + const hasMany: typeof DS.hasMany; + const belongsTo: typeof DS.belongsTo; } declare module 'ember-data/serializer' { - import DS from 'ember-data'; - export default DS.Serializer; + import DS from 'ember-data'; + export default DS.Serializer; + export { SerializerRegistry } from 'ember-data'; } declare module 'ember-data/serializers/embedded-records-mixin' { - import DS from 'ember-data'; - export default DS.EmbeddedRecordsMixin; + import DS from 'ember-data'; + export default DS.EmbeddedRecordsMixin; } declare module 'ember-data/serializers/json-api' { - import DS from 'ember-data'; - export default DS.JSONAPISerializer; + import DS from 'ember-data'; + export default DS.JSONAPISerializer; } declare module 'ember-data/serializers/json' { - import DS from 'ember-data'; - export default DS.JSONSerializer; + import DS from 'ember-data'; + export default DS.JSONSerializer; } declare module 'ember-data/serializers/rest' { - import DS from 'ember-data'; - export default DS.RESTSerializer; + import DS from 'ember-data'; + export default DS.RESTSerializer; } -declare module "ember-data/store" { - import DS from "ember-data"; +declare module 'ember-data/store' { + import DS from 'ember-data'; export default DS.Store; } -declare module "ember-data/transform" { - import DS from "ember-data"; +declare module 'ember-data/transform' { + import DS from 'ember-data'; export default DS.Transform; } -declare module "ember-data/transforms/boolean" { - import DS from "ember-data"; +declare module 'ember-data/transforms/boolean' { + import DS from 'ember-data'; export default DS.BooleanTransform; } -declare module "ember-data/transforms/date" { - import DS from "ember-data"; +declare module 'ember-data/transforms/date' { + import DS from 'ember-data'; export default DS.DateTransform; } -declare module "ember-data/transforms/number" { - import DS from "ember-data"; +declare module 'ember-data/transforms/number' { + import DS from 'ember-data'; export default DS.NumberTransform; } -declare module "ember-data/transforms/string" { - import DS from "ember-data"; +declare module 'ember-data/transforms/string' { + import DS from 'ember-data'; export default DS.StringTransform; } -declare module "ember-data/transforms/transform" { - import DS from "ember-data"; +declare module 'ember-data/transforms/transform' { + import DS from 'ember-data'; export default DS.Transform; } diff --git a/types/ember-data/test/adapter.ts b/types/ember-data/test/adapter.ts index 17f69bcd9c..101ac3e42f 100644 --- a/types/ember-data/test/adapter.ts +++ b/types/ember-data/test/adapter.ts @@ -1,6 +1,11 @@ import Ember from 'ember'; import DS from 'ember-data'; +class Session extends Ember.Service {} +declare module '@ember/service' { + interface Registry { 'session': Session; } +} + const JsonApi = DS.JSONAPIAdapter.extend({ // Application specific overrides go here }); @@ -55,6 +60,13 @@ const UseAjaxOptionsWithOptionalThirdParams = DS.JSONAPIAdapter.extend({ } }); +declare module 'ember-data' { + interface ModelRegistry { + 'rootModel': any; + 'super-user': any; + } +} + // https://github.com/emberjs/data/blob/c9d8212c857ca78218ad98d11621819b38dba98f/tests/unit/adapters/build-url-mixin/build-url-test.js const BuildURLAdapter = DS.RESTAdapter.extend({ worksWithOnlyModelNameAndId() { diff --git a/types/ember-data/test/belongs-to.ts b/types/ember-data/test/belongs-to.ts index 9e59aa6128..bd1037a65e 100644 --- a/types/ember-data/test/belongs-to.ts +++ b/types/ember-data/test/belongs-to.ts @@ -3,8 +3,14 @@ import { assertType } from './lib/assert'; class Folder extends DS.Model { name = DS.attr('string'); - children = DS.hasMany('folder', { inverse: 'parent' }); - parent = DS.belongsTo('folder', { inverse: 'children' }); + children = DS.hasMany('folder', { inverse: 'parent' }); + parent = DS.belongsTo('folder', { inverse: 'children' }); +} + +declare module 'ember-data' { + interface ModelRegistry { + folder: Folder; + } } const folder = Folder.create(); diff --git a/types/ember-data/test/has-many.ts b/types/ember-data/test/has-many.ts index 7fb586ff4a..e24fb1b814 100644 --- a/types/ember-data/test/has-many.ts +++ b/types/ember-data/test/has-many.ts @@ -1,43 +1,56 @@ import DS from 'ember-data'; import { assertType } from './lib/assert'; -class Comment extends DS.Model { +class BlogComment extends DS.Model { text = DS.attr('string'); } +declare module 'ember-data' { + interface ModelRegistry { + 'blog-comment': BlogComment; + } +} + class BlogPost extends DS.Model { title = DS.attr('string'); - commentsAsync = DS.hasMany('comment'); - commentsSync = DS.hasMany('comment', { async: false }); + commentsAsync = DS.hasMany('blog-comment'); + commentsSync = DS.hasMany('blog-comment', { async: false }); } -const post = BlogPost.create(); +const blogPost = BlogPost.create(); -assertType>(post.get('commentsSync').reload()); -assertType(post.get('commentsSync').createRecord()); +assertType>(blogPost.get('commentsSync').reload()); +assertType(blogPost.get('commentsSync').createRecord()); -const comment = post.get('commentsSync').get('firstObject'); -assertType(comment); +const comment = blogPost.get('commentsSync').get('firstObject'); +assertType(comment); if (comment) { assertType(comment.get('text')); } -assertType>(post.get('commentsAsync').reload()); -assertType(post.get('commentsAsync').createRecord()); -assertType(post.get('commentsAsync').get('firstObject')); +assertType>(blogPost.get('commentsAsync').reload()); +assertType(blogPost.get('commentsAsync').createRecord()); +assertType(blogPost.get('commentsAsync').get('firstObject')); -const commentAsync = post.get('commentsAsync').get('firstObject'); -assertType(commentAsync); +const commentAsync = blogPost.get('commentsAsync').get('firstObject'); +assertType(commentAsync); if (commentAsync) { assertType(commentAsync.get('text')); } -assertType(post.get('commentsAsync').get('isFulfilled')); +assertType(blogPost.get('commentsAsync').get('isFulfilled')); -post.get('commentsAsync').then(comments => { - assertType(comments.get('firstObject')); +blogPost.get('commentsAsync').then(comments => { + assertType(comments.get('firstObject')); assertType(comments.get('firstObject')!.get('text')); }); +class PaymentMethod extends DS.Model {} +declare module 'ember-data' { + interface ModelRegistry { + 'payment-method': PaymentMethod; + } +} + class Polymorphic extends DS.Model { paymentMethods = DS.hasMany('payment-method', { polymorphic: true }); } diff --git a/types/ember-data/test/injections.ts b/types/ember-data/test/injections.ts index 4c0a6e4e6b..3e32a2b805 100644 --- a/types/ember-data/test/injections.ts +++ b/types/ember-data/test/injections.ts @@ -1,6 +1,14 @@ import Ember from 'ember'; import DS from 'ember-data'; +class MyModel extends DS.Model {} + +declare module 'ember-data' { + interface ModelRegistry { + 'my-model': MyModel; + } +} + Ember.Route.extend({ model(): any { return this.store.findAll('my-model'); diff --git a/types/ember-data/test/record-reference.ts b/types/ember-data/test/record-reference.ts index bb4fda42d4..f5bf973402 100644 --- a/types/ember-data/test/record-reference.ts +++ b/types/ember-data/test/record-reference.ts @@ -7,7 +7,13 @@ class User extends DS.Model { username = DS.attr('string'); } -let userRef = store.getReference('user', 1); +declare module 'ember-data' { + interface ModelRegistry { + user: User; + } +} + +let userRef = store.getReference('user', 1); // get the record of the reference (null if not yet available) let user = userRef.value(); diff --git a/types/ember-data/test/relationships.ts b/types/ember-data/test/relationships.ts index a878428bc4..fb89d4410c 100644 --- a/types/ember-data/test/relationships.ts +++ b/types/ember-data/test/relationships.ts @@ -16,14 +16,21 @@ class Comment extends DS.Model { author = DS.attr('string'); } -class BlogPost extends DS.Model { +class RelationalPost extends DS.Model { title = DS.attr('string'); tag = DS.attr('string'); - comments = DS.hasMany('comment', { async: true }); + comments = DS.hasMany('comment', { async: true }); relatedPosts = DS.hasMany('post'); } -let blogPost = store.peekRecord('blog-post', 1); +declare module 'ember-data' { + interface ModelRegistry { + 'relational-post': RelationalPost; + comment: Comment; + } +} + +let blogPost = store.peekRecord('relational-post', 1); blogPost!.get('comments').then((comments) => { // now we can work with the comments let author: string = comments.get('firstObject')!.get('author'); diff --git a/types/ember-data/test/serializer.ts b/types/ember-data/test/serializer.ts index 986020144f..baaa65ae9e 100644 --- a/types/ember-data/test/serializer.ts +++ b/types/ember-data/test/serializer.ts @@ -4,7 +4,8 @@ import DS from 'ember-data'; const JsonApi = DS.JSONAPISerializer.extend({}); const Customized = DS.JSONAPISerializer.extend({ - serialize(snapshot: DS.Snapshot, options: {}) { + serialize(snapshot: DS.Snapshot<'user'>, options: {}) { + const lookup = snapshot.belongsTo('username'); let json: any = this._super(...Array.from(arguments)); json.data.attributes.cost = { diff --git a/types/ember-data/test/store.ts b/types/ember-data/test/store.ts index 46b0987981..0a9a615d27 100644 --- a/types/ember-data/test/store.ts +++ b/types/ember-data/test/store.ts @@ -1,24 +1,30 @@ import Ember from 'ember'; import DS from 'ember-data'; -import { assertType } from "./lib/assert"; +import { assertType } from './lib/assert'; declare const store: DS.Store; class Post extends DS.Model { - title = DS.attr('string'); + title = DS.attr('string'); } -let post = store.createRecord('post', { +declare module 'ember-data' { + interface ModelRegistry { + post: Post; + } +} + +let post = store.createRecord('post', { title: 'Rails is Omakase', - body: 'Lorem ipsum' + body: 'Lorem ipsum', }); post.save(); // => POST to '/posts' -post.save().then((saved) => { +post.save().then(saved => { assertType(saved); }); -store.findRecord('post', 1).then(function(post) { +store.findRecord('post', 1).then(function(post) { post.get('title'); // => "Rails is Omakase" post.set('title', 'A new post'); post.save(); // => PATCH to '/posts/1' @@ -28,21 +34,30 @@ class User extends DS.Model { username = DS.attr('string'); } -store.queryRecord('user', {}).then(function(user) { +class Author extends User {} + +declare module 'ember-data' { + interface ModelRegistry { + 'user': User; + 'author': Author; + } +} + +store.queryRecord('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('post'); // => GET /blog-posts store.findAll('author', { reload: true }).then(function(authors) { authors.getEach('id'); // ['first', 'second'] }); store.findAll('post', { - adapterOptions: { subscribe: false } + adapterOptions: { subscribe: false }, }); store.findAll('post', { include: 'comments,comments.author' }); -store.peekAll('blog-post'); // => no network request +store.peekAll('post'); // => no network request if (store.hasRecordForId('post', 1)) { let maybePost = store.peekRecord('post', 1); @@ -52,16 +67,22 @@ if (store.hasRecordForId('post', 1)) { } class Message extends DS.Model { - hasBeenSeen = DS.attr('boolean'); + hasBeenSeen = DS.attr('boolean'); } -const messages = store.peekAll('message'); +declare module 'ember-data' { + interface ModelRegistry { + message: Message; + } +} + +const messages = store.peekAll('message'); messages.forEach(function(message) { message.set('hasBeenSeen', true); }); messages.save(); -const people = store.peekAll('person'); +const people = store.peekAll('user'); people.get('isUpdating'); // false people.update().then(function() { people.get('isUpdating'); // false @@ -70,53 +91,84 @@ 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'}); + return this.store.findRecord('post', params.post_id, { + include: 'comments,comments.author', + }); + }, +}); + +// Store is injectable via `inject` and resolves to `DS.Store`. +const SomeComponent = Ember.Component.extend({ + store: Ember.inject.service('store'), + + lookUpUsers() { + assertType(this.get('store').findRecord('user', 123)); + assertType>(this.get('store').findAll('user')); } }); // 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"); -}); +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 + console.log(admins.get('length')); // 42 }); admins.update().then(function() { admins.get('isUpdating'); // false - console.log(admins.get("length")); // 123 + console.log(admins.get('length')); // 123 }); store.push({ - data: [{ - id: 1, - type: 'album', - attributes: { - title: 'Fewer Moving Parts', - artist: 'David Bazan', - songCount: 10 + data: [ + { + id: 1, + type: 'album', + attributes: { + title: 'Fewer Moving Parts', + artist: 'David Bazan', + songCount: 10, + }, + relationships: {}, }, - 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 + { + 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: {}, }, - relationships: {} - }] + ], }); -class UserAdapter extends DS.Adapter { } -class UserSerializer extends DS.Serializer { } +class UserAdapter extends DS.Adapter { + thisAdapterOnlyMethod(): void {} +} +class UserSerializer extends DS.Serializer { + thisSerializerOnlyMethod(): void {} +} -assertType(store.adapterFor('user')); -assertType(store.serializerFor('user')); +declare module 'ember-data' { + interface AdapterRegistry { + user: UserAdapter; + } + + interface SerializerRegistry { + user: UserSerializer; + } +} + +assertType(store.adapterFor('user')); +assertType(store.serializerFor('user')); diff --git a/types/ember-data/tslint.json b/types/ember-data/tslint.json index 6d765664cf..2389d09a3b 100644 --- a/types/ember-data/tslint.json +++ b/types/ember-data/tslint.json @@ -1,6 +1,7 @@ { "extends": "dtslint/dt.json", "rules": { + "strict-export-declare-modifiers": false, // Heavy use of Function type in this older package. "ban-types": false, "jsdoc-format": false, diff --git a/types/ember/index.d.ts b/types/ember/index.d.ts index 22ff839774..26a664450f 100755 --- a/types/ember/index.d.ts +++ b/types/ember/index.d.ts @@ -18,6 +18,9 @@ declare module 'ember' { import Rsvp from 'rsvp'; import { TemplateFactory } from 'htmlbars-inline-precompile'; + import { Registry as ServiceRegistry } from '@ember/service'; + import { Registry as ControllerRegistry } from '@ember/controller'; + // Get an alias to the global Array type to use in inner scope below. type GlobalArray = T[]; @@ -2303,12 +2306,18 @@ declare module 'ember' { * Creates a property that lazily looks up another controller in the container. * Can only be used when defining another controller. */ - function controller(name?: string): ComputedProperty; + function controller(): ComputedProperty; + function controller( + name: K + ): ComputedProperty; /** * Creates a property that lazily looks up a service in the container. There * are no restrictions as to what objects a service can be injected into. */ - function service(name?: string): ComputedProperty; + function service(): ComputedProperty; + function service( + name: K + ): ComputedProperty; } namespace ENV { const EXTEND_PROTOTYPES: typeof Ember.EXTEND_PROTOTYPES; @@ -3279,6 +3288,84 @@ declare module 'ember' { function expandProperties(pattern: string, callback: (expanded: string) => void): void; } + type RouteModel = object | string | number; + // https://emberjs.com/api/ember/2.18/classes/RouterService + /** + * The Router service is the public API that provides component/view layer access to the router. + */ + class RouterService extends Ember.Service { + // + /** + * Determines whether a route is active. + * + * @param routeName the name of the route + * @param models the model(s) or identifier(s) to be used while + * transitioning to the route + * @param options optional hash with a queryParams property containing a + * mapping of query parameters + */ + isActive(routeName: string, models: RouteModel, options?: { queryParams: object }): boolean; + isActive(routeName: string, modelsA: RouteModel, modelsB: RouteModel, options?: { queryParams: object }): boolean; + isActive(routeName: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, options?: { queryParams: object }): boolean; + isActive(routeName: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, modelsD: RouteModel, options?: { queryParams: object }): boolean; + + // https://emberjs.com/api/ember/2.18/classes/RouterService/methods/isActive?anchor=replaceWith + /** + * Transition into another route while replacing the current URL, if + * possible. The route may be either a single route or route path. + * + * @param routeNameOrUrl the name of the route or a URL + * @param models the model(s) or identifier(s) to be used while + * transitioning to the route. + * @param options optional hash with a queryParams property + * containing a mapping of query parameters + * @returns the Transition object associated with this attempted transition + */ + replaceWith(routeNameOrUrl: string, models: RouteModel, options?: { queryParams: object }): Ember.Transition; + replaceWith(routeNameOrUrl: string, modelsA: RouteModel, modelsB: RouteModel, options?: { queryParams: object }): Ember.Transition; + replaceWith(routeNameOrUrl: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, options?: { queryParams: object }): Ember.Transition; + replaceWith(routeNameOrUrl: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, modelsD: RouteModel, options?: { queryParams: object }): Ember.Transition; + + // https://emberjs.com/api/ember/2.18/classes/RouterService/methods/isActive?anchor=transitionTo + /** + * Transition the application into another route. The route may be + * either a single route or route path + * + * @param routeNameOrUrl the name of the route or a URL + * @param models the model(s) or identifier(s) to be used while + * transitioning to the route. + * @param options optional hash with a queryParams property + * containing a mapping of query parameters + * @returns the Transition object associated with this attempted transition + */ + transitionTo(routeNameOrUrl: string, models: RouteModel, options?: { queryParams: object }): Ember.Transition; + transitionTo(routeNameOrUrl: string, modelsA: RouteModel, modelsB: RouteModel, options?: { queryParams: object }): Ember.Transition; + transitionTo(routeNameOrUrl: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, options?: { queryParams: object }): Ember.Transition; + transitionTo(routeNameOrUrl: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, modelsD: RouteModel, options?: { queryParams: object }): Ember.Transition; + + // https://emberjs.com/api/ember/2.18/classes/RouterService/methods/isActive?anchor=urlFor + /** + * Generate a URL based on the supplied route name. + * + * @param routeName the name of the route or a URL + * @param models the model(s) or identifier(s) to be used while + * transitioning to the route. + * @param options optional hash with a queryParams property containing + * a mapping of query parameters + * @returns the string representing the generated URL + */ + urlFor(routeName: string, models: RouteModel, options?: { queryParams: object }): string; + urlFor(routeName: string, modelsA: RouteModel, modelsB: RouteModel, options?: { queryParams: object }): string; + urlFor(routeName: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, options?: { queryParams: object }): string; + urlFor(routeName: string, modelsA: RouteModel, modelsB: RouteModel, modelsC: RouteModel, modelsD: RouteModel, options?: { queryParams: object }): string; + } + + module '@ember/service' { + interface Registry { + 'router': RouterService; + } + } + export default Ember; } @@ -3362,6 +3449,10 @@ declare module '@ember/controller' { import Ember from 'ember'; export default class Controller extends Ember.Controller { } export const inject: typeof Ember.inject.controller; + + // A type registry for Ember `Controller`s. Meant to be declaration-merged + // so string lookups resolve to the correct type. + export interface Registry {} } declare module '@ember/debug' { @@ -3599,6 +3690,10 @@ declare module '@ember/service' { import Ember from 'ember'; export default class Service extends Ember.Service { } export const inject: typeof Ember.inject.service; + + // A type registry for Ember `Service`s. Meant to be declaration-merged so + // string lookups resolve to the correct type. + interface Registry {} } declare module '@ember/string' { diff --git a/types/ember/test/inject.ts b/types/ember/test/inject.ts index dd628f6d2a..5a372a2c5a 100755 --- a/types/ember/test/inject.ts +++ b/types/ember/test/inject.ts @@ -8,9 +8,21 @@ class ApplicationController extends Ember.Controller { transitionToLogin() {} } +declare module '@ember/service' { + interface Registry { + 'auth': AuthService; + } +} + +declare module '@ember/controller' { + interface Registry { + 'application': ApplicationController; + } +} + class LoginRoute extends Ember.Route { - auth = Ember.inject.service('authentication') as Ember.ComputedProperty; - application = Ember.inject.controller() as Ember.ComputedProperty; + auth = Ember.inject.service('auth'); + application = Ember.inject.controller('application'); didTransition() { if (!this.get('auth').get('isAuthenticated')) { @@ -18,3 +30,24 @@ class LoginRoute extends Ember.Route { } } } + +// New module injection style. +import Controller, { inject as controller } from '@ember/controller'; +import Service, { inject as service } from '@ember/service'; +import { assertType } from './lib/assert'; + +class ComponentInjection extends Ember.Component { + applicationController = controller('application'); + auth = service('auth'); + router = service('router'); + misc = service(); + + testem() { + assertType(this.get('misc')); + const url = this.get('router').urlFor('some-route', 1, 2, 3, { queryParams: { seriously: 'yes' } }); + assertType(url); + if (!this.get('auth').isAuthenticated) { + this.get('applicationController').transitionToLogin(); + } + } +}