API Docs for: 5.4.0-alpha.70+386b38ef
Show:

File: ../packages/legacy-compat/src/builders/save-record.ts

/**
 * @module @ember-data/legacy-compat/builders
 */
import { recordIdentifierFor, storeFor, type StoreRequestInput } from '@ember-data/store';
import type { InstanceCache } from '@ember-data/store/-private';
import { assert } from '@warp-drive/build-config/macros';
import type { StableRecordIdentifier } from '@warp-drive/core-types';
import type { Cache } from '@warp-drive/core-types/cache';
import type { TypedRecordInstance, TypeFromInstance } from '@warp-drive/core-types/record';
import { SkipCache } from '@warp-drive/core-types/request';
import type { RequestSignature } from '@warp-drive/core-types/symbols';

type SaveRecordRequestInput<T extends string = string, RT = unknown> = StoreRequestInput & {
  op: 'createRecord' | 'deleteRecord' | 'updateRecord';
  data: {
    record: StableRecordIdentifier<T>;
    options: SaveRecordBuilderOptions;
  };
  records: [StableRecordIdentifier<T>];
  [RequestSignature]?: RT;
};

type SaveRecordBuilderOptions = Record<string, unknown>;

function _resourceIsFullDeleted(identifier: StableRecordIdentifier, cache: Cache): boolean {
  return cache.isDeletionCommitted(identifier) || (cache.isNew(identifier) && cache.isDeleted(identifier));
}

function resourceIsFullyDeleted(instanceCache: InstanceCache, identifier: StableRecordIdentifier): boolean {
  const cache = instanceCache.cache;
  return !cache || _resourceIsFullDeleted(identifier, cache);
}

/**
  This function builds a request config for saving the given record (e.g. creating, updating, or deleting the record).
  When passed to `store.request`, this config will result in the same behavior as a legacy `store.saveRecord` request.
  Additionally, it takes the same options as `store.saveRecord`.

  All `@ember-data/legacy-compat` builders exist to enable you to migrate your codebase to using the correct syntax for `store.request` while temporarily preserving legacy behaviors.
  This is useful for quickly upgrading an entire app to a unified syntax while a longer incremental migration is made to shift off of adapters and serializers.
  To that end, these builders are deprecated and will be removed in a future version of Ember Data.

  @method saveRecord
  @deprecated
  @public
  @static
  @for @ember-data/legacy-compat/builders
  @param {object} record a record to save
  @param {SaveRecordBuilderOptions} options optional, may include `adapterOptions` hash which will be passed to adapter.saveRecord
  @return {SaveRecordRequestInput} request config
*/
export function saveRecordBuilder<T extends TypedRecordInstance>(
  record: T,
  options: Record<string, unknown> = {}
): SaveRecordRequestInput<TypeFromInstance<T>, T> {
  const store = storeFor(record);
  assert(`Unable to initiate save for a record in a disconnected state`, store);
  const identifier = recordIdentifierFor<T>(record);

  if (!identifier) {
    // this commonly means we're disconnected
    // but just in case we throw here to prevent bad things.
    throw new Error(`Record Is Disconnected`);
  }
  assert(
    `Cannot initiate a save request for an unloaded record: ${identifier.lid}`,
    store._instanceCache.recordIsLoaded(identifier)
  );
  if (resourceIsFullyDeleted(store._instanceCache, identifier)) {
    throw new Error('cannot build saveRecord request for deleted record');
  }

  if (!options) {
    options = {};
  }
  let operation: 'createRecord' | 'deleteRecord' | 'updateRecord' = 'updateRecord';

  const cache = store.cache;
  if (cache.isNew(identifier)) {
    operation = 'createRecord';
  } else if (cache.isDeleted(identifier)) {
    operation = 'deleteRecord';
  }

  return {
    op: operation,
    data: {
      options,
      record: identifier,
    },
    records: [identifier],
    cacheOptions: { [SkipCache]: true },
  };
}