Skip to content

Commit

Permalink
[FIX] RecordData is not a constructor
Browse files Browse the repository at this point in the history
(cherry picked from commit 46085de)
  • Loading branch information
runspired authored and hjdivad committed Jan 24, 2020
1 parent b22d490 commit 9857ec9
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 47 deletions.
11 changes: 9 additions & 2 deletions packages/-ember-data/addon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
86 changes: 68 additions & 18 deletions packages/store/addon/-private/system/core-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<unknown>): RSVP.Promise<Record> {
Expand All @@ -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<void>).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 {
Expand All @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
31 changes: 4 additions & 27 deletions packages/store/addon/-private/system/ds-model-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 9857ec9

Please sign in to comment.