#

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

# File: ../store/addon/-private/system/store/record-data-store-wrapper.ts

    import { RecordDataStoreWrapper as IRecordDataStoreWrapper } from '../../ts-interfaces/record-data-store-wrapper';
    import { AttributesSchema, RelationshipsSchema } from '../../ts-interfaces/record-data-schemas';
    import { BRAND_SYMBOL } from '../../ts-interfaces/utils/brand';
    import { upgradeForInternal } from '../ts-upgrade-map';
    import RecordData from '../../ts-interfaces/record-data';
    import { internalModelFactoryFor } from './internal-model-factory';
    import { IDENTIFIERS, CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
    import { identifierCacheFor, IdentifierCache } from '../../identifiers/cache';
    import CoreStore from '../core-store';
    import constructResource from '../../utils/construct-resource';
    import { StableRecordIdentifier } from '../../ts-interfaces/identifier';

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

    type StableIdentifierOrString = StableRecordIdentifier | string;

    export default class RecordDataStoreWrapper implements IRecordDataStoreWrapper {
      [BRAND_SYMBOL]: 'RecordDataStoreWrapper';
      _willUpdateManyArrays: boolean;
      private _pendingManyArrayUpdates: StableIdentifierOrString[];

      constructor(public _store: CoreStore) {
        this._willUpdateManyArrays = false;
        this._pendingManyArrayUpdates = [];
      }

      get identifierCache(): IdentifierCache {
        if (!IDENTIFIERS) {
          throw new Error(`Store.identifierCache is unavailable in this build of EmberData`);
        }
        return identifierCacheFor(this._store);
      }

      /**
       * Exists so that DefaultRecordData can check for model types
       * in DEBUG for relationships. Should be refactored away.
       *
       * @internal
       */
      _hasModelFor(type: string) {
        return this._store._hasModelFor(type);
      }

      /**
       * @internal
       */
      _scheduleManyArrayUpdate(identifier: StableRecordIdentifier, key: string) {
        let pending = (this._pendingManyArrayUpdates = this._pendingManyArrayUpdates || []);
        pending.push(identifier, key);

        if (this._willUpdateManyArrays === true) {
          return;
        }

        this._willUpdateManyArrays = true;
        let backburner: any = this._store._backburner;

        backburner.join(() => {
          backburner.schedule('syncRelationships', this, this._flushPendingManyArrayUpdates);
        });
      }

      notifyErrorsChange(type: string, id: string, lid: string | null): void;
      notifyErrorsChange(type: string, id: string | null, lid: string): void;
      notifyErrorsChange(type: string, id: string | null, lid: string | null): void {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);

        let internalModel = internalModelFactoryFor(this._store).peek(identifier);

        if (internalModel) {
          internalModel.notifyErrorsChange();
        }
      }

      _flushPendingManyArrayUpdates(): void {
        if (this._willUpdateManyArrays === false) {
          return;
        }

        let pending = this._pendingManyArrayUpdates;
        this._pendingManyArrayUpdates = [];
        this._willUpdateManyArrays = false;
        const factory = internalModelFactoryFor(this._store);

        for (let i = 0; i < pending.length; i += 2) {
          let identifier = pending[i] as StableRecordIdentifier;
          let key = pending[i + 1] as string;
          let internalModel = factory.peek(identifier);

          if (internalModel) {
            internalModel.notifyHasManyChange(key);
          }
        }
      }

      attributesDefinitionFor(type: string): AttributesSchema {
        return this._store._attributesDefinitionFor(type);
      }

      relationshipsDefinitionFor(type: string): RelationshipsSchema {
        return this._store._relationshipsDefinitionFor(type);
      }

      inverseForRelationship(type: string, key: string): string | null {
        const modelClass = this._store.modelFor(type);
        const definition = upgradeForInternal(this.relationshipsDefinitionFor(type)[key]);
        if (CUSTOM_MODEL_CLASS) {
          if (definition.inverse !== undefined) {
            return definition.inverse;
          } else {
            //TODO add a test for this branch
            if (!definition._inverseKey) {
              return null;
            }
            return definition._inverseKey(this._store, modelClass);
          }
        } else {
          return definition._inverseKey(this._store, modelClass);
        }
      }

      inverseIsAsyncForRelationship(type: string, key: string): boolean {
        const modelClass = this._store.modelFor(type);
        const definition = upgradeForInternal(this.relationshipsDefinitionFor(type)[key]);
        if (CUSTOM_MODEL_CLASS) {
          if (definition.inverse === null) {
            return false;
          }
          if (definition.inverseIsAsync !== undefined) {
            return !!definition.inverseIsAsync;
          } else {
            return definition._inverseIsAsync(this._store, modelClass);
          }
        } else {
          return definition._inverseIsAsync(this._store, modelClass);
        }
      }

      notifyPropertyChange(type: string, id: string | null, lid: string, key: string): void;
      notifyPropertyChange(type: string, id: string, lid: string | null | undefined, key: string): void;
      notifyPropertyChange(type: string, id: string | null, lid: string | null | undefined, key: string): void {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        let internalModel = internalModelFactoryFor(this._store).peek(identifier);

        if (internalModel) {
          internalModel.notifyPropertyChange(key);
        }
      }

      notifyHasManyChange(type: string, id: string | null, lid: string, key: string): void;
      notifyHasManyChange(type: string, id: string, lid: string | null | undefined, key: string): void;
      notifyHasManyChange(type: string, id: string | null, lid: string | null | undefined, key: string): void {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        this._scheduleManyArrayUpdate(identifier, key);
      }

      notifyBelongsToChange(type: string, id: string | null, lid: string, key: string): void;
      notifyBelongsToChange(type: string, id: string, lid: string | null | undefined, key: string): void;
      notifyBelongsToChange(type: string, id: string | null, lid: string | null | undefined, key: string): void {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        let internalModel = internalModelFactoryFor(this._store).peek(identifier);

        if (internalModel) {
          internalModel.notifyBelongsToChange(key);
        }
      }

      notifyStateChange(type: string, id: string, lid: string | null, key?: string): void;
      notifyStateChange(type: string, id: string | null, lid: string, key?: string): void;
      notifyStateChange(type: string, id: string | null, lid: string | null, key?: string): void {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        let internalModel = internalModelFactoryFor(this._store).peek(identifier);

        if (internalModel) {
          internalModel.notifyStateChange(key);
        }
      }

      recordDataFor(type: string, id: string, lid?: string | null): RecordData;
      recordDataFor(type: string, id: string | null, lid: string): RecordData;
      recordDataFor(type: string): RecordData;
      recordDataFor(type: string, id?: string | null, lid?: string | null): RecordData {
        let identifier: StableRecordIdentifier | { type: string };
        let isCreate: boolean = false;
        if (!id && !lid) {
          isCreate = true;
          identifier = { type };
        } else {
          const resource = constructResource(type, id, lid);
          identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        }

        return this._store.recordDataFor(identifier, isCreate);
      }

      setRecordId(type: string, id: string, lid: string) {
        this._store.setRecordId(type, id, lid);
      }

      isRecordInUse(type: string, id: string | null, lid: string): boolean;
      isRecordInUse(type: string, id: string, lid?: string | null): boolean;
      isRecordInUse(type: string, id: string | null, lid?: string | null): boolean {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        let internalModel = internalModelFactoryFor(this._store).peek(identifier);
        if (!internalModel) {
          return false;
        }
        return internalModel.isRecordInUse();
      }

      disconnectRecord(type: string, id: string | null, lid: string): void;
      disconnectRecord(type: string, id: string, lid?: string | null): void;
      disconnectRecord(type: string, id: string | null, lid?: string | null): void {
        const resource = constructResource(type, id, lid);
        const identifier = identifierCacheFor(this._store).getOrCreateRecordIdentifier(resource);
        let internalModel = internalModelFactoryFor(this._store).peek(identifier);
        if (internalModel) {
          internalModel.destroyFromRecordData();
        }
      }
    }