|
1 | 1 | # ember-resources
|
2 | 2 |
|
| 3 | +## 6.0.0-beta.0 |
| 4 | + |
| 5 | +### Major Changes |
| 6 | + |
| 7 | +- [#715](https://github.com/NullVoxPopuli/ember-resources/pull/715) [`e8155b2`](https://github.com/NullVoxPopuli/ember-resources/commit/e8155b254cfef874287a3b1d0d9c562ed97b88dc) Thanks [@NullVoxPopuli](https://github.com/NullVoxPopuli)! - Drop support for TypeScript < 4.8 in order to support Glint. |
| 8 | + |
| 9 | +- [#778](https://github.com/NullVoxPopuli/ember-resources/pull/778) [`901ae9a`](https://github.com/NullVoxPopuli/ember-resources/commit/901ae9a0b6919af8c66fb8102927d5dee0d2f694) Thanks [@NullVoxPopuli](https://github.com/NullVoxPopuli)! - The `map` utility resource has changed its first type-argument for better inference. |
| 10 | + |
| 11 | + The utility already supported inference, so this change should not impact too many folks. |
| 12 | + |
| 13 | + When explicit type-arguments were specified, |
| 14 | + |
| 15 | + ```ts |
| 16 | + class Demo { |
| 17 | + // previously |
| 18 | + a = map<Element>(this, { |
| 19 | + data: () => [ |
| 20 | + /* ... list of Element(s) ... */ |
| 21 | + ], |
| 22 | + map: (element) => { |
| 23 | + /* some transform */ |
| 24 | + }, |
| 25 | + }); |
| 26 | + |
| 27 | + // now |
| 28 | + a = map<Element[]>(this, { |
| 29 | + data: () => [ |
| 30 | + /* ... list of Element(s) ... */ |
| 31 | + ], |
| 32 | + map: (element) => { |
| 33 | + /* some transform */ |
| 34 | + }, |
| 35 | + }); |
| 36 | + } |
| 37 | + ``` |
| 38 | + |
| 39 | + This is advantageous, because with `@tsconfig/ember`, the option `noUncheckedIndexedAccess` |
| 40 | + is enabled by default. This is a great strictness / quality option to have enabled, |
| 41 | + as arrays in javascript are mutable, and we can't guarantee that they don't change between |
| 42 | + index-accesses. |
| 43 | + |
| 44 | + _However_ the `map` utility resource explicitly disallows the indicies to get out of sync |
| 45 | + with the source `data`. |
| 46 | + |
| 47 | + But!, with `noUncheckedIndexedAccess`, you can only infer so much before TS goes the safe route, |
| 48 | + and makes the returned type `X | undefined`. |
| 49 | + |
| 50 | + For example, in these type-tests: |
| 51 | + |
| 52 | + ```ts |
| 53 | + import { map } from "ember-resources/util/map"; |
| 54 | + import { expectType } from "ts-expect"; |
| 55 | + |
| 56 | + const constArray = [1, 2, 3]; |
| 57 | + |
| 58 | + b = map(this, { |
| 59 | + data: () => constArray, |
| 60 | + map: (element) => { |
| 61 | + expectType<number>(element); |
| 62 | + return element; |
| 63 | + }, |
| 64 | + }); |
| 65 | + |
| 66 | + // index-access here is *safely* `| undefined`, due to `constArray` being mutable. |
| 67 | + expectType<number | undefined>(b[0]); |
| 68 | + expectType<number | undefined>(b.values()[0]); |
| 69 | + |
| 70 | + // but when we use a const as const array, we define a tuple, |
| 71 | + // and can correctly infer and return real values via index access |
| 72 | + const tupleArray = [1, 2, 3] as const; |
| 73 | + |
| 74 | + c = map(this, { |
| 75 | + data: () => tupleArray, |
| 76 | + map: (element) => { |
| 77 | + expectType<number>(element); |
| 78 | + return element; |
| 79 | + }, |
| 80 | + }); |
| 81 | + |
| 82 | + // No `| undefined` here |
| 83 | + expectType<number>(c[0]); |
| 84 | + expectType<number>(c.values()[0]); |
| 85 | + ``` |
| 86 | + |
| 87 | +- [#779](https://github.com/NullVoxPopuli/ember-resources/pull/779) [`a471d9b`](https://github.com/NullVoxPopuli/ember-resources/commit/a471d9b2dad67a73062f9786869fdb00de25f79a) Thanks [@NullVoxPopuli](https://github.com/NullVoxPopuli)! - `trackedFunction` has a new API and thus a major version release is required. |
| 88 | + |
| 89 | + _Work by [@lolmaus](https://github.com/lolmaus)_ |
| 90 | + |
| 91 | + tl;dr: the breaking changes: |
| 92 | + |
| 93 | + - no more manual initial value |
| 94 | + - `isResolved` is only true on success |
| 95 | + - `isError` has been renamed to `isRejected` |
| 96 | + - `isLoading` has been removed as it was redundant |
| 97 | + |
| 98 | + other changes: |
| 99 | + |
| 100 | + - `trackedFunction` is a wrapper around `ember-async-data`'s [`TrackedAsyncData`](https://github.com/tracked-tools/ember-async-data/blob/main/ember-async-data/src/tracked-async-data.ts) |
| 101 | + - behavior is otherwise the same |
| 102 | + |
| 103 | + NOTE: `trackedFunction` is an example utility of how to use auto-tracking with function invocation, |
| 104 | + and abstract away the various states involved with async behavior. Now that the heavy lifting is done by `ember-async-data`, |
| 105 | + `trackedFunction` is now more of an example of how to integrated existing tracked utilities in to resources. |
| 106 | + |
| 107 | + *** |
| 108 | + |
| 109 | + **Migration** |
| 110 | + |
| 111 | + **_Previously_, `trackedFunction` could take an initial value for its second argument.** |
| 112 | + |
| 113 | + ```js |
| 114 | + class Demo { |
| 115 | + foo = trackedFunction(this, "initial value", async () => { |
| 116 | + /* ... */ |
| 117 | + }); |
| 118 | + } |
| 119 | + ``` |
| 120 | + |
| 121 | + This has been removed, as initial value can be better maintained _and made more explicit_ |
| 122 | + in user-space. For example: |
| 123 | + |
| 124 | + ```js |
| 125 | + class Demo { |
| 126 | + foo = trackedFunction(this, async () => { |
| 127 | + /* ... */ |
| 128 | + }); |
| 129 | + |
| 130 | + get value() { |
| 131 | + return this.foo.value ?? "initial value"; |
| 132 | + } |
| 133 | + } |
| 134 | + ``` |
| 135 | +
|
| 136 | + Or, in a template: |
| 137 | +
|
| 138 | + ```hbs |
| 139 | + {{#if this.foo.value}} |
| 140 | + {{this.foo.value}} |
| 141 | + {{else}} |
| 142 | + initial displayed content |
| 143 | + {{/if}} |
| 144 | + ``` |
| 145 | +
|
| 146 | + Or, in gjs/strict mode: |
| 147 | +
|
| 148 | + ```gjs |
| 149 | + const withDefault = (value) => value ?? 'initial value'; |
| 150 | + |
| 151 | + class Demo extends Component { |
| 152 | + foo = trackedFunction(this, async () => { /* ... */ }); |
| 153 | + |
| 154 | + <template> |
| 155 | + {{withDefault this.foo.value}} |
| 156 | + </template> |
| 157 | + } |
| 158 | + ``` |
| 159 | +
|
| 160 | + **_Previously_, the `isResolved` property was `true` for succesful and error states** |
| 161 | +
|
| 162 | + Now, `isResolved` is only true when the function passed to `trackedFunction` has succesfully |
| 163 | + completed. |
| 164 | +
|
| 165 | + To have behavior similar to the old behavior, you may want to implement your own `isFinished` getter: |
| 166 | +
|
| 167 | + ```js |
| 168 | + class Demo { |
| 169 | + foo = trackedFunction(this, async () => { |
| 170 | + /* ... */ |
| 171 | + }); |
| 172 | + |
| 173 | + get isFinished() { |
| 174 | + return this.foo.isResolved || this.foo.isRejected; |
| 175 | + } |
| 176 | + } |
| 177 | + ``` |
| 178 | +
|
| 179 | +### Minor Changes |
| 180 | +
|
| 181 | +- [#778](https://github.com/NullVoxPopuli/ember-resources/pull/778) [`f841a98`](https://github.com/NullVoxPopuli/ember-resources/commit/f841a982197f64b0756f8ee9fc35ed3d690fa959) Thanks [@NullVoxPopuli](https://github.com/NullVoxPopuli)! - Use strictest possible settings with TypeScript so that consumers can't be stricter than this library |
| 182 | +
|
| 183 | +- [#776](https://github.com/NullVoxPopuli/ember-resources/pull/776) [`a99793e`](https://github.com/NullVoxPopuli/ember-resources/commit/a99793ed126366a9da40a8df632ac660f05b68b1) Thanks [@NullVoxPopuli](https://github.com/NullVoxPopuli)! - Glint is now supported starting with 1.0.0-beta.3 |
| 184 | +
|
| 185 | +### Patch Changes |
| 186 | +
|
| 187 | +- [#769](https://github.com/NullVoxPopuli/ember-resources/pull/769) [`abaad4a`](https://github.com/NullVoxPopuli/ember-resources/commit/abaad4ad9974cf86632524f01bef331cfaa8d253) Thanks [@GreatWizard](https://github.com/GreatWizard)! - fix typo in map error message when checking if every datum is an object |
| 188 | +
|
3 | 189 | ## 5.6.2
|
4 | 190 |
|
5 | 191 | ### Patch Changes
|
|
40 | 226 | import { service } from "@ember/service";
|
41 | 227 |
|
42 | 228 | const intervals = new WeakMap();
|
43 |
| - |
| 229 | + |
44 | 230 | export default class Demo extends Component {
|
45 | 231 | @service declare router: RouterService;
|
46 | 232 |
|
|
51 | 237 | clearInterval(intervals.get(this);
|
52 | 238 | intervals.set(this, setInterval(fn, interval));
|
53 | 239 | });
|
54 |
| - |
| 240 | + |
55 | 241 | refreshData = () => this.router.refresh();
|
56 | 242 | }
|
57 | 243 | ```
|
|
0 commit comments