From 873ba727582d8c19b5303f52285113c0ee2f3df5 Mon Sep 17 00:00:00 2001 From: Peter Wagenet Date: Tue, 12 Aug 2025 10:59:08 -0700 Subject: [PATCH] Add deprecation guides for ComputedProperties --- ...ecate-import-alias-from-object-computed.md | 34 ++++++++++++++++++ ...precate-import-and-from-object-computed.md | 30 ++++++++++++++++ ...recate-import-bool-from-object-computed.md | 27 ++++++++++++++ ...-computed-property-from-object-computed.md | 19 ++++++++++ ...dependent-key-compat-from-object-compat.md | 33 +++++++++++++++++ ...-deprecating-alias-from-object-computed.md | 36 +++++++++++++++++++ ...ecate-import-empty-from-object-computed.md | 28 +++++++++++++++ ...ecate-import-equal-from-object-computed.md | 29 +++++++++++++++ ...-expand-properties-from-object-computed.md | 18 ++++++++++ ...eprecate-import-gt-from-object-computed.md | 29 +++++++++++++++ ...precate-import-gte-from-object-computed.md | 26 ++++++++++++++ ...eprecate-import-lt-from-object-computed.md | 26 ++++++++++++++ ...precate-import-lte-from-object-computed.md | 26 ++++++++++++++ ...ecate-import-match-from-object-computed.md | 29 +++++++++++++++ ...e-import-not-empty-from-object-computed.md | 27 ++++++++++++++ ...precate-import-not-from-object-computed.md | 24 +++++++++++++ ...ate-import-one-way-from-object-computed.md | 27 ++++++++++++++ ...eprecate-import-or-from-object-computed.md | 26 ++++++++++++++ ...e-import-read-only-from-object-computed.md | 29 +++++++++++++++ 19 files changed, 523 insertions(+) create mode 100644 content/ember/v6/deprecate-import-alias-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-and-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-bool-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-computed-property-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-dependent-key-compat-from-object-compat.md create mode 100644 content/ember/v6/deprecate-import-deprecating-alias-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-empty-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-equal-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-expand-properties-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-gt-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-gte-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-lt-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-lte-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-match-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-not-empty-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-not-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-one-way-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-or-from-object-computed.md create mode 100644 content/ember/v6/deprecate-import-read-only-from-object-computed.md diff --git a/content/ember/v6/deprecate-import-alias-from-object-computed.md b/content/ember/v6/deprecate-import-alias-from-object-computed.md new file mode 100644 index 00000000..c5bad87d --- /dev/null +++ b/content/ember/v6/deprecate-import-alias-from-object-computed.md @@ -0,0 +1,34 @@ +--- +title: Deprecate import alias from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`alias` from `@ember/object/computed` is deprecated. + +It created a second property that reflected another property's value. + +## Migration +Prefer direct access to the original tracked state, or use a simple getter and setter. + +Before: +```js +import { alias } from '@ember/object/computed'; +import { tracked } from '@glimmer/tracking'; + +class Person { + @tracked firstName = 'Tom'; + @alias('firstName') name; +} +``` + +After: +```js +import { tracked } from '@glimmer/tracking'; +class Person { + @tracked firstName = 'Tom'; + get name() { return this.firstName; } + set name(value) { this.firstName = value; } +} +``` +If all call sites can use `firstName` directly, remove the alias entirely. diff --git a/content/ember/v6/deprecate-import-and-from-object-computed.md b/content/ember/v6/deprecate-import-and-from-object-computed.md new file mode 100644 index 00000000..2b2991c5 --- /dev/null +++ b/content/ember/v6/deprecate-import-and-from-object-computed.md @@ -0,0 +1,30 @@ +--- +title: Deprecate import and from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`and` from `@ember/object/computed` is deprecated. It previously produced the logical AND of dependent keys. + +## Migration +Use a getter with a standard JavaScript boolean expression. + +Before: +```js +import { and } from '@ember/object/computed'; +class Cart { + items = []; + user = null; + @and('items.length', 'user.isLoggedIn') canCheckout; +} +``` +After: +```js +class Cart { + items = []; + user = null; + get canCheckout() { + return this.items.length > 0 && this.user?.isLoggedIn; + } +} +``` diff --git a/content/ember/v6/deprecate-import-bool-from-object-computed.md b/content/ember/v6/deprecate-import-bool-from-object-computed.md new file mode 100644 index 00000000..9a5e9313 --- /dev/null +++ b/content/ember/v6/deprecate-import-bool-from-object-computed.md @@ -0,0 +1,27 @@ +--- +title: Deprecate import bool from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`bool` from `@ember/object/computed` is deprecated. It coerced the value of another property to a boolean. + +## Migration +Use a getter wrapping `Boolean(...)` or `!!`. + +Before: +```js +import { bool } from '@ember/object/computed'; +class State { + selectedItem = null; + @bool('selectedItem') hasSelection; +} +``` + +After: +```js +class State { + selectedItem = null; + get hasSelection() { return Boolean(this.selectedItem); } +} +``` diff --git a/content/ember/v6/deprecate-import-computed-property-from-object-computed.md b/content/ember/v6/deprecate-import-computed-property-from-object-computed.md new file mode 100644 index 00000000..d943258b --- /dev/null +++ b/content/ember/v6/deprecate-import-computed-property-from-object-computed.md @@ -0,0 +1,19 @@ +--- +title: Deprecate import ComputedProperty from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`ComputedProperty` (the default export of `@ember/object/computed`) is deprecated. It was the internal class backing classic computed properties. + +## Migration +Do not construct or refer to `ComputedProperty` directly. Use native getters with `@tracked` state instead. + +Before: +```js +import ComputedProperty from '@ember/object/computed'; +// rarely used directly +``` +After: Remove the import; refactor any custom meta-programming to simple getters. + +There is no public replacement for the class itself; the concept is removed. diff --git a/content/ember/v6/deprecate-import-dependent-key-compat-from-object-compat.md b/content/ember/v6/deprecate-import-dependent-key-compat-from-object-compat.md new file mode 100644 index 00000000..a4bacb5c --- /dev/null +++ b/content/ember/v6/deprecate-import-dependent-key-compat-from-object-compat.md @@ -0,0 +1,33 @@ +--- +title: Deprecate import dependentKeyCompat from @ember/object/compat +until: 7.0.0 +since: 6.0.0 +--- + +`dependentKeyCompat` is deprecated. It provided backwards compatibility so tracked getters could participate in classic CP dependency chains. + +## Migration +Remove all ComputedProperties that depend on this getter, then remove `@dependentKeyCompat`. + +Before: +```js +import { tracked } from '@glimmer/tracking'; +import { computed } from '@ember/object'; +import { dependentKeyCompat } from '@ember/object/compat'; +class Person { + @tracked firstName = 'Tom'; + @tracked lastName = 'Dale'; + @dependentKeyCompat get givenName() { return this.firstName; } + @computed('givenName','lastName') get fullName() { return `${this.givenName} ${this.lastName}`; } +} +``` +After: +```js +import { tracked } from '@glimmer/tracking'; +class Person { + @tracked firstName = 'Tom'; + @tracked lastName = 'Dale'; + get givenName() { return this.firstName; } + get fullName() { return `${this.givenName} ${this.lastName}`; } +} +``` diff --git a/content/ember/v6/deprecate-import-deprecating-alias-from-object-computed.md b/content/ember/v6/deprecate-import-deprecating-alias-from-object-computed.md new file mode 100644 index 00000000..d300aeb4 --- /dev/null +++ b/content/ember/v6/deprecate-import-deprecating-alias-from-object-computed.md @@ -0,0 +1,36 @@ +--- +title: Deprecate import deprecatingAlias from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`deprecatingAlias` from `@ember/object/computed` is deprecated. It created an alias that emitted a deprecation when accessed. + +## Migration +Remove the indirection and update callers to reference the canonical property. If you still need a deprecation message temporarily, implement a manual getter that logs once. + +Before (framework provided deprecation): +```js +import { deprecatingAlias } from '@ember/object/computed'; +class Person { + firstName = 'Tom'; + @deprecatingAlias('firstName', { id: 'app.old-name', until: '7.0.0' }) givenName; +} +``` +After (direct access): +```js +class Person { + firstName = 'Tom'; +} +``` +Optional transitional getter: +```js +import { deprecate } from '@ember/debug'; +class Person { + firstName = 'Tom'; + get givenName() { + deprecate('Usage of `givenName` is deprecated, use `firstNAme` instead.'); + return this.firstName; + } +} +``` diff --git a/content/ember/v6/deprecate-import-empty-from-object-computed.md b/content/ember/v6/deprecate-import-empty-from-object-computed.md new file mode 100644 index 00000000..969a603a --- /dev/null +++ b/content/ember/v6/deprecate-import-empty-from-object-computed.md @@ -0,0 +1,28 @@ +--- +title: Deprecate import empty from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`empty` from `@ember/object/computed` is deprecated. It returned true when the dependent value was `null`, `undefined`, an empty string, or had length 0. + +## Migration +Implement the check in a getter. + +Before: +```js +import { empty } from '@ember/object/computed'; +class ListState { + items = []; + @empty('items') isEmpty; +} +``` +After: +```js +import { isEmpty } from '@ember/utils'; +class ListState { + items = []; + get isEmpty() { return isEmpty(this.items); } +} +``` +Combine with `!` for `notEmpty` replacement. diff --git a/content/ember/v6/deprecate-import-equal-from-object-computed.md b/content/ember/v6/deprecate-import-equal-from-object-computed.md new file mode 100644 index 00000000..a7028d5c --- /dev/null +++ b/content/ember/v6/deprecate-import-equal-from-object-computed.md @@ -0,0 +1,29 @@ +--- +title: Deprecate import equal from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`equal` from `@ember/object/computed` is deprecated. It compared a dependent key's value to a constant. + +## Migration +Use a getter with a strict equality expression. + +Before: +```js +import { equal } from '@ember/object/computed'; +class Person { + role = 'admin'; + @equal('role', 'admin') isAdmin; +} +``` + +After: +```js +class Person { + role = 'admin'; + get isAdmin() { + return this.role === 'admin'; + } +} +``` diff --git a/content/ember/v6/deprecate-import-expand-properties-from-object-computed.md b/content/ember/v6/deprecate-import-expand-properties-from-object-computed.md new file mode 100644 index 00000000..a50afd3d --- /dev/null +++ b/content/ember/v6/deprecate-import-expand-properties-from-object-computed.md @@ -0,0 +1,18 @@ +--- +title: Deprecate import expandProperties from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`expandProperties` is deprecated. It expanded bracket / brace notation in classic CP dependent key strings. + +## Migration +This is largely unneeded and there is no direct replacement. + +Before: +```js +import { expandProperties } from '@ember/object/computed'; +expandProperties('user.{first,last}Name', (prop) => {/* ... */}); +``` + +After: List properties explicitly: `user.firstName`, `user.lastName`. diff --git a/content/ember/v6/deprecate-import-gt-from-object-computed.md b/content/ember/v6/deprecate-import-gt-from-object-computed.md new file mode 100644 index 00000000..921692d8 --- /dev/null +++ b/content/ember/v6/deprecate-import-gt-from-object-computed.md @@ -0,0 +1,29 @@ +--- +title: Deprecate import gt from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`gt` (greater than) from `@ember/object/computed` is deprecated. + +## Migration +Use a comparison inside a getter. + +Before: +```js +import { gt } from '@ember/object/computed'; +class Score { + value = 42; + @gt('value', 10) isHigh; +} +``` + +After: +```js +class Score { + value = 42; + get isHigh() { + return this.value > 10; + } +} +``` diff --git a/content/ember/v6/deprecate-import-gte-from-object-computed.md b/content/ember/v6/deprecate-import-gte-from-object-computed.md new file mode 100644 index 00000000..5514f5f8 --- /dev/null +++ b/content/ember/v6/deprecate-import-gte-from-object-computed.md @@ -0,0 +1,26 @@ +--- +title: Deprecate import gte from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`gte` (greater than or equal) from `@ember/object/computed` is deprecated. + +Before: +```js +import { gte } from '@ember/object/computed'; +class Score { + value = 42; + @gte('value', 10) meetsThreshold; +} +``` + +After: +```js +class Score { + value = 42; + get meetsThreshold() { + return this.value >= 10; + } +} +``` diff --git a/content/ember/v6/deprecate-import-lt-from-object-computed.md b/content/ember/v6/deprecate-import-lt-from-object-computed.md new file mode 100644 index 00000000..7e48a1ed --- /dev/null +++ b/content/ember/v6/deprecate-import-lt-from-object-computed.md @@ -0,0 +1,26 @@ +--- +title: Deprecate import lt from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`lt` (less than) from `@ember/object/computed` is deprecated. + +Before: +```js +import { lt } from '@ember/object/computed'; +class Score { + value = 5; + @lt('value', 10) isLow; +} +``` + +After: +```js +class Score { + value = 5; + get isLow() { + return this.value < 10; + } +} +``` diff --git a/content/ember/v6/deprecate-import-lte-from-object-computed.md b/content/ember/v6/deprecate-import-lte-from-object-computed.md new file mode 100644 index 00000000..26cd26fb --- /dev/null +++ b/content/ember/v6/deprecate-import-lte-from-object-computed.md @@ -0,0 +1,26 @@ +--- +title: Deprecate import lte from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`lte` (less than or equal) from `@ember/object/computed` is deprecated. + +Before: +```js +import { lte } from '@ember/object/computed'; +class Score { + value = 5; + @lte('value', 10) withinLimit; +} +``` + +After: +```js +class Score { + value = 5; + get withinLimit() { + return this.value <= 10; + } +} +``` diff --git a/content/ember/v6/deprecate-import-match-from-object-computed.md b/content/ember/v6/deprecate-import-match-from-object-computed.md new file mode 100644 index 00000000..d6649b4f --- /dev/null +++ b/content/ember/v6/deprecate-import-match-from-object-computed.md @@ -0,0 +1,29 @@ +--- +title: Deprecate import match from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`match` from `@ember/object/computed` is deprecated. It tested a property's string value against a regular expression. + +## Migration +Use a getter with `RegExp.test`. + +Before: +```js +import { match } from '@ember/object/computed'; +class User { + email = 'me@example.com'; + @match('email', /@example\.com$/) isInternal; +} +``` + +After: +```js +class User { + email = 'me@example.com'; + get isInternal() { + return /@example\.com$/.test(this.email); + } +} +``` diff --git a/content/ember/v6/deprecate-import-not-empty-from-object-computed.md b/content/ember/v6/deprecate-import-not-empty-from-object-computed.md new file mode 100644 index 00000000..27f4d359 --- /dev/null +++ b/content/ember/v6/deprecate-import-not-empty-from-object-computed.md @@ -0,0 +1,27 @@ +--- +title: Deprecate import notEmpty from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`notEmpty` from `@ember/object/computed` is deprecated. + +Before: +```js +import { notEmpty } from '@ember/object/computed'; +class ListState { + items = []; + @notEmpty('items') hasItems; +} +``` + +After: +```js +import { isEmpty } from '@ember/utils'; +class ListState { + items = []; + get hasItems() { + return !isEmpty(this.items); + } +} +``` diff --git a/content/ember/v6/deprecate-import-not-from-object-computed.md b/content/ember/v6/deprecate-import-not-from-object-computed.md new file mode 100644 index 00000000..2811788b --- /dev/null +++ b/content/ember/v6/deprecate-import-not-from-object-computed.md @@ -0,0 +1,24 @@ +--- +title: Deprecate import not from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`not` from `@ember/object/computed` is deprecated. + +Before: +```js +import { not } from '@ember/object/computed'; +class State { + isActive = true; + @not('isActive') isInactive; +} +``` + +After: +```js +class State { + isActive = true; + get isInactive() { return !this.isActive; } +} +``` diff --git a/content/ember/v6/deprecate-import-one-way-from-object-computed.md b/content/ember/v6/deprecate-import-one-way-from-object-computed.md new file mode 100644 index 00000000..534268e1 --- /dev/null +++ b/content/ember/v6/deprecate-import-one-way-from-object-computed.md @@ -0,0 +1,27 @@ +--- +title: Deprecate import oneWay / reads from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`oneWay` (often aliased locally as `reads`) from `@ember/object/computed` is deprecated. It made a property that reflects another property's value but did not propagate sets back. + +## Migration +Use the original property or a getter. + +Before: +```js +import { oneWay } from '@ember/object/computed'; +class Person { + firstName = 'Tom'; + @oneWay('firstName') name; +} + +``` +After: +```js +class Person { + firstName = 'Tom'; + get name() { return this.firstName; } +} +``` diff --git a/content/ember/v6/deprecate-import-or-from-object-computed.md b/content/ember/v6/deprecate-import-or-from-object-computed.md new file mode 100644 index 00000000..06e38a78 --- /dev/null +++ b/content/ember/v6/deprecate-import-or-from-object-computed.md @@ -0,0 +1,26 @@ +--- +title: Deprecate import or from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`or` from `@ember/object/computed` is deprecated. + +Before: +```js +import { or } from '@ember/object/computed'; +class Session { + token = null; + cachedToken = 'abc'; + @or('token','cachedToken') activeToken; +} +``` + +After: +```js +class Session { + token = null; + cachedToken = 'abc'; + get activeToken() { return this.token || this.cachedToken; } +} +``` diff --git a/content/ember/v6/deprecate-import-read-only-from-object-computed.md b/content/ember/v6/deprecate-import-read-only-from-object-computed.md new file mode 100644 index 00000000..821cd9f7 --- /dev/null +++ b/content/ember/v6/deprecate-import-read-only-from-object-computed.md @@ -0,0 +1,29 @@ +--- +title: Deprecate import readOnly from @ember/object/computed +until: 7.0.0 +since: 6.0.0 +--- + +`readOnly` from `@ember/object/computed` is deprecated. + +## Migration +Use a getter that returns the underlying value. + +Before: +```js +import { readOnly } from '@ember/object/computed'; +class Person { + firstName = 'Tom'; + @readOnly('firstName') givenName; +} +``` + +After: +```js +class Person { + firstName = 'Tom'; + get givenName() { return this.firstName; } +} +``` + +Don't define a setter to keep it effectively read-only.