#

API Docs for: v3.16.0-alpha.2
Show: Inherited Protected Private Deprecated

# File: ../store/addon/-private/system/references/reference.ts

    import InternalModel from '../model/internal-model';
    import recordDataFor from '../record-data-for';
    import { Object as JSONObject, Value as JSONValue } from 'json-typescript';
    import CoreStore from '../core-store';
    import { PaginationLinks, LinkObject } from '../../ts-interfaces/ember-data-json-api';
    import { JsonApiRelationship } from '../../ts-interfaces/record-data-json-api';
    import { FULL_LINKS_ON_RELATIONSHIPS } from '@ember-data/canary-features';
    import { Dict } from '../../ts-interfaces/utils';

    /**
      @module @ember-data/store
    */

    interface ResourceIdentifier {
      links?: {
        related?: string;
      };
      meta?: JSONObject;
    }

    function isResourceIdentiferWithRelatedLinks(
      value: any
    ): value is ResourceIdentifier & { links: { related: string | LinkObject | null } } {
      return value && value.links && value.links.related;
    }

    /**
      This is the baseClass for the different References
      like RecordReference/HasManyReference/BelongsToReference

     @class Reference
     */
    interface Reference {
      links(): PaginationLinks | null;
    }
    abstract class Reference {
      public recordData: InternalModel['_recordData'];
      constructor(public store: CoreStore, public internalModel: InternalModel) {
        this.recordData = recordDataFor(this);
      }

      public _resource(): ResourceIdentifier | JsonApiRelationship | void {}

      /**
       This returns a string that represents how the reference will be
       looked up when it is loaded. If the relationship has a link it will
       use the "link" otherwise it defaults to "id".

       Example

       ```app/models/post.js
       import Model, { hasMany } from '@ember-data/model';

       export default Model.extend({
         comments: hasMany({ async: true })
       });
       ```

       ```javascript
       let post = store.push({
         data: {
           type: 'post',
           id: 1,
           relationships: {
             comments: {
               data: [{ type: 'comment', id: 1 }]
             }
           }
         }
       });

       let commentsRef = post.hasMany('comments');

       // get the identifier of the reference
       if (commentsRef.remoteType() === "ids") {
         let ids = commentsRef.ids();
       } else if (commentsRef.remoteType() === "link") {
         let link = commentsRef.link();
       }
       ```

       @method remoteType
       @return {String} The name of the remote type. This should either be "link" or "ids"
       */
      remoteType(): 'link' | 'id' | 'identity' {
        let value = this._resource();
        if (isResourceIdentiferWithRelatedLinks(value)) {
          return 'link';
        }
        return 'id';
      }

      /**
       The link Ember Data will use to fetch or reload this belongs-to
       relationship.

       Example

       ```javascript
       // models/blog.js
       import Model, { belongsTo } from '@ember-data/model';
       export default Model.extend({
          user: belongsTo({ async: true })
        });

       let blog = store.push({
          data: {
            type: 'blog',
            id: 1,
            relationships: {
              user: {
                links: {
                  related: '/articles/1/author'
                }
              }
            }
          }
        });
       let userRef = blog.belongsTo('user');

       // get the identifier of the reference
       if (userRef.remoteType() === "link") {
          let link = userRef.link();
        }
       ```

       @method link
       @return {String} The link Ember Data will use to fetch or reload this belongs-to relationship.
       */
      link(): string | null {
        let link;
        let resource = this._resource();

        if (isResourceIdentiferWithRelatedLinks(resource)) {
          if (resource.links) {
            link = resource.links.related;
            link = !link || typeof link === 'string' ? link : link.href;
          }
        }
        return link || null;
      }

      /**
       The meta data for the belongs-to relationship.

       Example

       ```javascript
       // models/blog.js
       import Model, { belongsTo } from '@ember-data/model';
       export default Model.extend({
          user: belongsTo({ async: true })
        });

       let blog = store.push({
          data: {
            type: 'blog',
            id: 1,
            relationships: {
              user: {
                links: {
                  related: {
                    href: '/articles/1/author'
                  },
                  meta: {
                    lastUpdated: 1458014400000
                  }
                }
              }
            }
          }
        });

       let userRef = blog.belongsTo('user');

       userRef.meta() // { lastUpdated: 1458014400000 }
       ```

       @method meta
       @return {Object} The meta information for the belongs-to relationship.
       */
      meta() {
        let meta: Dict<JSONValue> | null = null;
        let resource = this._resource();
        if (resource && resource.meta && typeof resource.meta === 'object') {
          meta = resource.meta;
        }
        return meta;
      }
    }

    if (FULL_LINKS_ON_RELATIONSHIPS) {
      Reference.prototype.links = function links(): PaginationLinks | null {
        let resource = this._resource();

        return resource && resource.links ? resource.links : null;
      };
    }

    export default Reference;