Skip to content

Commit

Permalink
chore: macros for DEBUG, assertPolymorphicType, HAS_DEBUG_PACKAGE (em…
Browse files Browse the repository at this point in the history
…berjs#8284)

* add macros for DEBUG

* transform HAS_DEBUG_PACKAGE

* convert assertPolymorphicType to macros approach
  • Loading branch information
runspired authored Oct 31, 2022
1 parent c897f55 commit f7d3d67
Show file tree
Hide file tree
Showing 35 changed files with 441 additions and 274 deletions.
File renamed without changes.
61 changes: 31 additions & 30 deletions packages/model/addon/-private/legacy-data-fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,36 +195,37 @@ function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, paren

let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;

if (
DEBUG &&
typeof relationshipData !== 'undefined' &&
!relationshipDataPointsToParent(relationshipData, parentIdentifier)
) {
let inspect = function inspect(thing) {
return `'${JSON.stringify(thing)}'`;
};
let quotedType = inspect(type);
let quotedInverse = inspect(inverseKey);
let expected = inspect({
id: parentIdentifier.id,
type: parentIdentifier.type,
});
let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
let got = inspect(relationshipData);
let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
let path = `${prefix}.relationships.${inverseKey}.data`;
let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
let includedRecord = `<${type}:${id}>`;
let message = [
`Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`,
`The ${includedRecord} record loaded at ${prefix} in the payload specified ${other} as its ${quotedInverse}, but should have specified ${expectedModel} (the record the relationship is being loaded from) as its ${quotedInverse} instead.`,
`This could mean that the response for ${relationshipFetched} may have accidentally returned ${quotedType} records that aren't related to ${expectedModel} and could be related to a different ${parentIdentifier.type} record instead.`,
`Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`,
`Please update the response from the server or change your serializer to either ensure that the response for only includes ${quotedType} records that specify ${expectedModel} as their ${quotedInverse}, or omit the ${quotedInverse} relationship from the response.`,
].join('\n');

assert(message);
if (DEBUG) {
if (
typeof relationshipData !== 'undefined' &&
!relationshipDataPointsToParent(relationshipData, parentIdentifier)
) {
let inspect = function inspect(thing) {
return `'${JSON.stringify(thing)}'`;
};
let quotedType = inspect(type);
let quotedInverse = inspect(inverseKey);
let expected = inspect({
id: parentIdentifier.id,
type: parentIdentifier.type,
});
let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
let got = inspect(relationshipData);
let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
let path = `${prefix}.relationships.${inverseKey}.data`;
let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
let includedRecord = `<${type}:${id}>`;
let message = [
`Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`,
`The ${includedRecord} record loaded at ${prefix} in the payload specified ${other} as its ${quotedInverse}, but should have specified ${expectedModel} (the record the relationship is being loaded from) as its ${quotedInverse} instead.`,
`This could mean that the response for ${relationshipFetched} may have accidentally returned ${quotedType} records that aren't related to ${expectedModel} and could be related to a different ${parentIdentifier.type} record instead.`,
`Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`,
`Please update the response from the server or change your serializer to either ensure that the response for only includes ${quotedType} records that specify ${expectedModel} as their ${quotedInverse}, or omit the ${quotedInverse} relationship from the response.`,
].join('\n');

assert(message);
}
}

if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
Expand Down
16 changes: 9 additions & 7 deletions packages/model/addon/-private/legacy-relationships-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,15 @@ export class LegacySupport {
const graph = graphFor(this.store);
const relationship = graph.get(this.identifier, name);

if (DEBUG && kind) {
let modelName = this.identifier.type;
let actualRelationshipKind = relationship.definition.kind;
assert(
`You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`,
actualRelationshipKind === kind
);
if (DEBUG) {
if (kind) {
let modelName = this.identifier.type;
let actualRelationshipKind = relationship.definition.kind;
assert(
`You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`,
actualRelationshipKind === kind
);
}
}

let relationshipKind = relationship.definition.kind;
Expand Down
103 changes: 55 additions & 48 deletions packages/model/addon/-private/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/

import { assert, deprecate, warn } from '@ember/debug';
import EmberError from '@ember/error';
import EmberObject from '@ember/object';
import { dependentKeyCompat } from '@ember/object/compat';
import { run } from '@ember/runloop';
Expand Down Expand Up @@ -125,10 +124,12 @@ class Model extends EmberObject {
___private_notifications;

init(options = {}) {
if (DEBUG && !options._secretInit && !options._createProps) {
throw new EmberError(
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
);
if (DEBUG) {
if (!options._secretInit && !options._createProps) {
throw new Error(
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
);
}
}
const createProps = options._createProps;
const _secretInit = options._secretInit;
Expand Down Expand Up @@ -521,8 +522,10 @@ class Model extends EmberObject {
// when using legacy/classic ember classes. Basically: lazy in prod and eager in dev.
// so we do this to try to steer folks to the nicer "dont user currentState"
// error.
if (!DEBUG && !this.___recordState) {
this.___recordState = new RecordState(this);
if (!DEBUG) {
if (!this.___recordState) {
this.___recordState = new RecordState(this);
}
}
return this.___recordState;
}
Expand Down Expand Up @@ -1489,56 +1492,60 @@ class Model extends EmberObject {
}

// ensure inverse is properly configured
if (DEBUG && isPolymorphic) {
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
if (!inverseOptions.as) {
deprecate(
if (DEBUG) {
if (isPolymorphic) {
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
if (!inverseOptions.as) {
deprecate(
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
false,
{
id: 'ember-data:non-explicit-relationships',
since: { enabled: '4.7', available: '4.7' },
until: '5.0',
for: 'ember-data',
}
);
}
} else {
assert(
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
false,
{
id: 'ember-data:non-explicit-relationships',
since: { enabled: '4.7', available: '4.7' },
until: '5.0',
for: 'ember-data',
}
inverseOptions.as
);
assert(
`options.as should match the expected type of the polymorphic relationship. Expected field '${fieldOnInverse}' on type '${inverseSchema.modelName}' to specify '${relationship.type}' but found '${inverseOptions.as}'`,
!!inverseOptions.as && relationship.type === inverseOptions.as
);
}
} else {
assert(
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
inverseOptions.as
);
assert(
`options.as should match the expected type of the polymorphic relationship. Expected field '${fieldOnInverse}' on type '${inverseSchema.modelName}' to specify '${relationship.type}' but found '${inverseOptions.as}'`,
!!inverseOptions.as && relationship.type === inverseOptions.as
);
}
}

// ensure we are properly configured
if (DEBUG && inverseOptions.polymorphic) {
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
if (!options.as) {
deprecate(
if (DEBUG) {
if (inverseOptions.polymorphic) {
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
if (!options.as) {
deprecate(
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
false,
{
id: 'ember-data:non-explicit-relationships',
since: { enabled: '4.7', available: '4.7' },
until: '5.0',
for: 'ember-data',
}
);
}
} else {
assert(
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
false,
{
id: 'ember-data:non-explicit-relationships',
since: { enabled: '4.7', available: '4.7' },
until: '5.0',
for: 'ember-data',
}
options.as
);
assert(
`options.as should match the expected type of the polymorphic relationship. Expected field '${name}' on type '${this.modelName}' to specify '${inverseRelationship.type}' but found '${options.as}'`,
!!options.as && inverseRelationship.type === options.as
);
}
} else {
assert(
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
options.as
);
assert(
`options.as should match the expected type of the polymorphic relationship. Expected field '${name}' on type '${this.modelName}' to specify '${inverseRelationship.type}' but found '${options.as}'`,
!!options.as && inverseRelationship.type === options.as
);
}
}

Expand Down Expand Up @@ -2469,7 +2476,7 @@ if (DEBUG) {
let idDesc = lookupDescriptor(this, 'id');

if (idDesc.get !== ID_DESCRIPTOR.get) {
throw new EmberError(
throw new Error(
`You may not set 'id' as an attribute on your model. Please remove any lines that look like: \`id: attr('<type>')\` from ${this.constructor.toString()}`
);
}
Expand Down
19 changes: 11 additions & 8 deletions packages/model/addon/-private/references/belongs-to.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { deprecate } from '@ember/debug';
import { dependentKeyCompat } from '@ember/object/compat';
import { DEBUG } from '@glimmer/env';
import { cached, tracked } from '@glimmer/tracking';

import type { Object as JSONObject, Value as JSONValue } from 'json-typescript';
Expand All @@ -9,7 +10,6 @@ import { DEPRECATE_PROMISE_PROXIES } from '@ember-data/private-build-infra/depre
import type { Graph } from '@ember-data/record-data/-private/graph/graph';
import type BelongsToRelationship from '@ember-data/record-data/-private/relationships/state/belongs-to';
import type Store from '@ember-data/store';
import { assertPolymorphicType } from '@ember-data/store/-debug';
import { recordIdentifierFor } from '@ember-data/store/-private';
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
import type {
Expand All @@ -22,6 +22,7 @@ import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
import type { RecordInstance } from '@ember-data/types/q/record-instance';
import type { Dict } from '@ember-data/types/q/utils';

import { assertPolymorphicType } from '../debug/assert-polymorphic-type';
import type { LegacySupport } from '../legacy-relationships-support';
import { LEGACY_SUPPORT } from '../model';

Expand Down Expand Up @@ -417,13 +418,15 @@ export default class BelongsToReference {
}
let record = this.store.push(jsonApiDoc);

// eslint-disable-next-line @typescript-eslint/no-unsafe-call
assertPolymorphicType(
this.belongsToRelationship.identifier,
this.belongsToRelationship.definition,
recordIdentifierFor(record),
this.store
);
if (DEBUG) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
assertPolymorphicType(
this.belongsToRelationship.identifier,
this.belongsToRelationship.definition,
recordIdentifierFor(record),
this.store
);
}

const { identifier } = this.belongsToRelationship;
this.store._join(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/model/addon/-private/references/has-many.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type { Graph } from '@ember-data/record-data/-private/graph/graph';
import type ManyRelationship from '@ember-data/record-data/-private/relationships/state/has-many';
import type Store from '@ember-data/store';
import { recordIdentifierFor } from '@ember-data/store';
import { assertPolymorphicType } from '@ember-data/store/-debug';
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
import type {
CollectionResourceDocument,
Expand All @@ -28,6 +27,7 @@ import type { RecordInstance } from '@ember-data/types/q/record-instance';
import type { FindOptions } from '@ember-data/types/q/store';
import type { Dict } from '@ember-data/types/q/utils';

import { assertPolymorphicType } from '../debug/assert-polymorphic-type';
import type { LegacySupport } from '../legacy-relationships-support';
import { LEGACY_SUPPORT } from '../model';

Expand Down
6 changes: 4 additions & 2 deletions packages/model/addon/-private/relationship-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ class RelationshipDefinition implements RelationshipSchema {
inverse = modelClass.inverseFor(this.key, store);
}
// TODO make this error again for the non-polymorphic case
if (DEBUG && !this.options.polymorphic) {
modelClass.typeForRelationship(this.key, store);
if (DEBUG) {
if (!this.options.polymorphic) {
modelClass.typeForRelationship(this.key, store);
}
}

if (inverse) {
Expand Down
1 change: 0 additions & 1 deletion packages/model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ module.exports = Object.assign({}, addonBaseConfig, {
'@ember-data/canary-features',
'@ember-data/store',
'@ember-data/store/-private',
'@ember-data/store/-debug',
'@embroider/macros',
'@ember/string',
'@embroider/macros/es-compat',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const path = require('path');

const calculateCacheKeyForTree = require('calculate-cache-key-for-tree');
const Funnel = require('broccoli-funnel');
const merge = require('broccoli-merge-trees');
Expand Down Expand Up @@ -144,7 +146,7 @@ function addonBuildConfigForDataPackage(PackageName) {
let existingPlugins = babelOptions.plugins || [];
let config = this.getEmberDataConfig();

let customPlugins = require('./stripped-build-plugins')(process.env.EMBER_ENV, this._findHost(), config);
let customPlugins = require('./stripped-build-plugins')(config);
let plugins = existingPlugins.map((plugin) => {
return Array.isArray(plugin) ? plugin : [plugin];
});
Expand Down Expand Up @@ -274,6 +276,34 @@ function addonBuildConfigForDataPackage(PackageName) {
options.emberData.debug
);
options.emberData.debug = debugOptions;
let HAS_DEBUG_PACKAGE, HAS_META_PACKAGE;

try {
// eslint-disable-next-line node/no-missing-require
require.resolve('@ember-data/debug', { paths: [process.cwd(), path.join(__dirname, '../')] });
HAS_DEBUG_PACKAGE = true;
} catch {
HAS_DEBUG_PACKAGE = false;
}
try {
// eslint-disable-next-line node/no-missing-require
require.resolve('ember-data', { paths: [process.cwd(), path.join(__dirname, '../')] });
HAS_META_PACKAGE = true;
} catch {
HAS_META_PACKAGE = false;
}
options.emberData.includeDataAdapterInProduction =
typeof options.emberData.includeDataAdapterInProduction === 'boolean'
? options.emberData.includeDataAdapterInProduction
: HAS_META_PACKAGE;

const includeDataAdapter = HAS_DEBUG_PACKAGE
? isProd
? options.emberData.includeDataAdapterInProduction
: true
: false;
options.emberData.includeDataAdapter = includeDataAdapter;

const DEPRECATIONS = require('./deprecations')(options.emberData.compatWith || null);
const FEATURES = require('./features')(isProd);
options.emberData.__DEPRECATIONS = DEPRECATIONS;
Expand All @@ -285,10 +315,10 @@ function addonBuildConfigForDataPackage(PackageName) {
ownConfig.debug = debugOptions;
ownConfig.deprecations = Object.assign(DEPRECATIONS, ownConfig.deprecations || {});
ownConfig.features = Object.assign({}, FEATURES);
ownConfig.includeDataAdapter = includeDataAdapter;

const returnedOptions = Object.assign({ compatWith: null }, options.emberData);

return returnedOptions;
this._emberDataConfig = ownConfig;
return ownConfig;
},
};
}
Expand Down
Loading

0 comments on commit f7d3d67

Please sign in to comment.