From 9857ec9f4a5d96860b2101f58d497a0ef5874ae7 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Tue, 21 Jan 2020 12:31:46 -0800 Subject: [PATCH] [FIX] RecordData is not a constructor (cherry picked from commit 46085de0476a99b03160caa76f0eb5f61efd62df) --- packages/-ember-data/addon/index.js | 11 ++- .../ts-interfaces/relationship-record-data.ts | 8 ++ .../store/addon/-private/system/core-store.ts | 86 +++++++++++++++---- .../addon/-private/system/ds-model-store.ts | 31 +------ 4 files changed, 89 insertions(+), 47 deletions(-) diff --git a/packages/-ember-data/addon/index.js b/packages/-ember-data/addon/index.js index 26b2c5ca7f5..e9a9b6eaeaa 100644 --- a/packages/-ember-data/addon/index.js +++ b/packages/-ember-data/addon/index.js @@ -33,8 +33,6 @@ import 'ember-inflector'; import setupContainer from './setup-container'; import initializeStoreService from './initialize-store-service'; -import Transform from '@ember-data/serializer/transform'; - import { BooleanTransform, DateTransform, NumberTransform, StringTransform } from '@ember-data/serializer/-private'; import Adapter, { BuildURLMixin } from '@ember-data/adapter'; @@ -60,6 +58,15 @@ import JSONSerializer from '@ember-data/serializer/json'; import RESTSerializer, { EmbeddedRecordsMixin } from '@ember-data/serializer/rest'; import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; +import Transform from '@ember-data/serializer/transform'; + +if (VERSION.match(/^1\.([0-9]|1[0-2])\./)) { + throw new EmberError( + 'Ember Data requires at least Ember 1.13.0, but you have ' + + VERSION + + '. Please upgrade your version of Ember, then upgrade Ember Data.' + ); +} DS.Store = Store; DS.PromiseArray = PromiseArray; diff --git a/packages/record-data/addon/-private/ts-interfaces/relationship-record-data.ts b/packages/record-data/addon/-private/ts-interfaces/relationship-record-data.ts index 5530f8ed0d0..398da33fb78 100644 --- a/packages/record-data/addon/-private/ts-interfaces/relationship-record-data.ts +++ b/packages/record-data/addon/-private/ts-interfaces/relationship-record-data.ts @@ -10,6 +10,14 @@ import { RecordDataStoreWrapper } from '@ember-data/store/-private/ts-interfaces import BelongsToRelationship from '../relationships/state/belongs-to'; import HasManyRelationship from '../relationships/state/has-many'; import { ConfidentDict } from '@ember-data/store/-private/ts-interfaces/utils'; +type SingleResourceRelationship = import('@ember-data/store/-private/ts-interfaces/ember-data-json-api').SingleResourceRelationship; +type CollectionResourceRelationship = import('@ember-data/store/-private/ts-interfaces/ember-data-json-api').CollectionResourceRelationship; +type HasManyRelationship = import('../relationships/state/has-many').default; +type BelongsToRelationship = import('../relationships/state/belongs-to').default; +type RecordDataStoreWrapper = import('@ember-data/store/-private/ts-interfaces/record-data-store-wrapper').RecordDataStoreWrapper; +type RecordIdentifier = import('@ember-data/store/-private/ts-interfaces/identifier').RecordIdentifier; +type Relationship = import('../relationships/state/relationship').default; +type Relationships = import('../relationships/state/create').default; export interface DefaultSingleResourceRelationship extends SingleResourceRelationship { _relationship: BelongsToRelationship; diff --git a/packages/store/addon/-private/system/core-store.ts b/packages/store/addon/-private/system/core-store.ts index b4cf1b8b3e2..cb608d535a9 100644 --- a/packages/store/addon/-private/system/core-store.ts +++ b/packages/store/addon/-private/system/core-store.ts @@ -48,6 +48,20 @@ import { } from '@ember-data/canary-features'; import { Record } from '../ts-interfaces/record'; +import { + HAS_ADAPTER_PACKAGE, + HAS_MODEL_PACKAGE, + HAS_RECORD_DATA_PACKAGE, + HAS_SERIALIZER_PACKAGE, +} from '@ember-data/private-build-infra'; +import { + DEPRECATE_DEFAULT_ADAPTER, + DEPRECATE_DEFAULT_SERIALIZER, + DEPRECATE_LEGACY_TEST_REGISTRATIONS, +} from '@ember-data/private-build-infra/deprecations'; + +// TODO this comes from ts-interfaces but it is a function we ship +// so needs to be moved somewhere else import promiseRecord from '../utils/promise-record'; import { identifierCacheFor, IdentifierCache } from '../identifiers/cache'; import { internalModelFactoryFor, setRecordIdentifier, recordIdentifierFor } from './store/internal-model-factory'; @@ -78,7 +92,9 @@ import { errorsArrayToHash } from './errors-utils'; type Relationship = import('@ember-data/record-data/-private').Relationship; type RelationshipRecordData = import('@ember-data/record-data/-private/ts-interfaces/relationship-record-data').RelationshipRecordData; +type RecordDataClass = typeof import('@ember-data/record-data/-private').RecordData; +let _RecordData: RecordDataClass | undefined; const emberRun = emberRunLoop.backburner; const { ENV } = Ember; @@ -393,14 +409,16 @@ abstract class CoreStore extends Service { if (REQUEST_SERVICE) { return this._fetchManager.requestCache; } - throw new Error('RequestService is not available unless the feature flag is on and running on a canary build'); + + assertInDebug('RequestService is not available unless the feature flag is on and running on a canary build', false); } get identifierCache(): IdentifierCache { - if (!IDENTIFIERS) { - throw new Error(`Store.identifierCache is unavailable in this build of EmberData`); + if (IDENTIFIERS) { + return identifierCacheFor(this); } - return identifierCacheFor(this); + + assertInDebug(`Store.identifierCache is unavailable in this build of EmberData`, false); } _instantiateRecord( @@ -456,9 +474,9 @@ abstract class CoreStore extends Service { setRecordIdentifier(record, identifier); //recordToInternalModelMap.set(record, internalModel); return record; - } else { - throw new Error('should not be here, custom model class ff error'); } + + assertInDebug('should not be here, custom model class ff error', false); } abstract instantiateRecord( @@ -498,9 +516,9 @@ abstract class CoreStore extends Service { getSchemaDefinitionService(): SchemaDefinitionService { if (CUSTOM_MODEL_CLASS) { return this._schemaDefinitionService; - } else { - throw new Error('need to enable CUSTOM_MODEL_CLASS feature flag in order to access SchemaDefinitionService'); } + + assertInDebug('need to enable CUSTOM_MODEL_CLASS feature flag in order to access SchemaDefinitionService', false); } // TODO Double check this return value is correct @@ -3018,9 +3036,9 @@ abstract class CoreStore extends Service { let internalModel = internalModelFactoryFor(this).peek(identifier); // TODO we used to check if the record was destroyed here return internalModel!.createSnapshot(options).serialize(options); - } else { - throw new Error('serializeRecord is only available when CUSTOM_MODEL_CLASS ff is on'); } + + assertInDebug('serializeRecord is only available when CUSTOM_MODEL_CLASS ff is on', false); } saveRecord(record: Record, options?: Dict): RSVP.Promise { @@ -3031,9 +3049,9 @@ abstract class CoreStore extends Service { // Casting can be removed once REQUEST_SERVICE ff is turned on // because a `Record` is provided there will always be a matching internalModel return (internalModel!.save(options) as RSVP.Promise).then(() => record); - } else { - throw new Error('saveRecord is only available when CUSTOM_MODEL_CLASS ff is on'); } + + assertInDebug('saveRecord is only available when CUSTOM_MODEL_CLASS ff is on', false); } relationshipReferenceFor(identifier: RecordIdentifier, key: string): BelongsToReference | HasManyReference { @@ -3042,9 +3060,9 @@ abstract class CoreStore extends Service { let internalModel = internalModelFactoryFor(this).peek(stableIdentifier); // TODO we used to check if the record was destroyed here return internalModel!.referenceFor(null, key); - } else { - throw new Error('relationshipReferenceFor is only available when CUSTOM_MODEL_CLASS ff is on'); } + + assertInDebug('relationshipReferenceFor is only available when CUSTOM_MODEL_CLASS ff is on', false); } /** @@ -3069,7 +3087,26 @@ abstract class CoreStore extends Service { clientId: string, storeWrapper: RecordDataStoreWrapper ): RecordData { - throw new Error(`Expected store.createRecordDataFor to be implemented but it wasn't`); + if (HAS_RECORD_DATA_PACKAGE) { + // we can't greedily use require as this causes + // a cycle we can't easily fix (or clearly pin point) at present. + if (_RecordData === undefined) { + _RecordData = require('@ember-data/record-data/-private').RecordData as RecordDataClass; + } + + if (IDENTIFIERS) { + let identifier = identifierCacheFor(this).getOrCreateRecordIdentifier({ + type: modelName, + id, + lid: clientId, + }); + return new _RecordData(identifier, storeWrapper); + } else { + return new _RecordData(modelName, id, clientId, storeWrapper); + } + } + + assertInDebug(`Expected store.createRecordDataFor to be implemented but it wasn't`, false); } /** @@ -3137,10 +3174,11 @@ abstract class CoreStore extends Service { } newClientId() { - if (IDENTIFIERS) { - throw new Error(`Private API Removed`); + if (!IDENTIFIERS) { + return globalClientIdCounter++; } - return globalClientIdCounter++; + + assertInDebug(`Private API Removed`, false); } //Called by the state machine to notify the store that the record is ready to be interacted with @@ -3641,3 +3679,15 @@ if (DEBUG) { } }; } + +function assertInDebug(msg: string, cond: boolean = false): asserts cond is true { + if (DEBUG && cond) { + throw new Error(msg); + } +} + +function assertIdentifierHasId( + identifier: StableRecordIdentifier +): asserts identifier is StableExistingRecordIdentifier { + assertInDebug(`Attempted to schedule a fetch for a record without an id.`, identifier.id === null); +} diff --git a/packages/store/addon/-private/system/ds-model-store.ts b/packages/store/addon/-private/system/ds-model-store.ts index 208469925df..b7476412690 100644 --- a/packages/store/addon/-private/system/ds-model-store.ts +++ b/packages/store/addon/-private/system/ds-model-store.ts @@ -7,23 +7,17 @@ import { DEBUG } from '@glimmer/env'; import { deprecate } from '@ember/application/deprecations'; import { CUSTOM_MODEL_CLASS, IDENTIFIERS } from '@ember-data/canary-features'; -import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra'; import { isPresent } from '@ember/utils'; import EmberError from '@ember/error'; import { get } from '@ember/object'; import { setOwner, getOwner } from '@ember/application'; -import { identifierCacheFor } from '../identifiers/cache'; import CoreStore from './core-store'; import notifyChanges from './model/notify-changes'; import { getShimClass } from './model/shim-model-class'; import normalizeModelName from './normalize-model-name'; import { DSModelSchemaDefinitionService, getModelFactory } from './schema-definition-service'; -type RecordDataStoreWrapper = import('./store/record-data-store-wrapper').default; - -const RecordData = HAS_RECORD_DATA_PACKAGE ? require('@ember-data/record-data/-private').RecordData : null; - type RelationshipsSchema = import('../ts-interfaces/record-data-schemas').RelationshipsSchema; type SchemaDefinitionService = import('../ts-interfaces/schema-definition-service').SchemaDefinitionService; type RecordDataRecordWrapper = import('../ts-interfaces/record-data-record-wrapper').RecordDataRecordWrapper; @@ -142,31 +136,14 @@ class Store extends CoreStore { record.destroy(); } - createRecordDataFor(modelName: string, id: string | null, clientId: string, storeWrapper: RecordDataStoreWrapper) { - if (HAS_RECORD_DATA_PACKAGE) { - if (IDENTIFIERS) { - let identifier = identifierCacheFor(this).getOrCreateRecordIdentifier({ - type: modelName, - id, - lid: clientId, - }); - return new RecordData(identifier, storeWrapper); - } else { - return new RecordData(modelName, id, clientId, storeWrapper); - } - } else { - throw new Error(`Expected store.createRecordDataFor to be implemented but it wasn't`); - } - } - /** Returns the model class for the particular `modelName`. - + The class of a model might be useful if you want to get a list of all the relationship names of the model, see [`relationshipNames`](/ember-data/release/classes/Model?anchor=relationshipNames) for example. - + @method modelFor @param {String} modelName @return {Model} @@ -215,10 +192,10 @@ class Store extends CoreStore { This exists for legacy support for the RESTSerializer, which due to how it must guess whether a key is a model must query for whether a match exists. - + We should investigate an RFC to make this public or removing this requirement. - + @private */ _hasModelFor(modelName) {