Skip to content

Commit 88a7b81

Browse files
Merge pull request #1107 from NullVoxPopuli/NullVoxPopuli-patch-1
Move recommendation of resourceFactory to better align with how TypeScript works
2 parents 699b112 + 1794976 commit 88a7b81

File tree

5 files changed

+40
-26
lines changed

5 files changed

+40
-26
lines changed

DOCS.md

+11-6
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ Lastly, to support reactively changing the locale, we need to wrap the `resource
238238
```js
239239
import { resource, resourceFactory, use } from 'ember-resources';
240240

241-
const Clock = resourceFactory((locale = 'en-US') => {
241+
function Clock(locale = 'en-US') {
242242
return resource(({ on }) => {
243243
let time = new TrackedObject({ current: new Date() });
244244
let interval = setInterval(() => (time.current = new Date()), 1_000);
@@ -249,7 +249,9 @@ const Clock = resourceFactory((locale = 'en-US') => {
249249

250250
return () => formatter.format(time.current);
251251
});
252-
});
252+
}
253+
254+
resourceFactory(Clock);
253255
```
254256

255257
<details><summary>using &lt;template&gt;</summary>
@@ -258,7 +260,7 @@ const Clock = resourceFactory((locale = 'en-US') => {
258260
// NOTE: this snippet has bugs and is incomplete, don't copy this (explained later)
259261
import { resource, resourceFactory, use } from 'ember-resources';
260262

261-
const Clock = resourceFactory((locale = 'en-US') => {
263+
function Clock(locale = 'en-US') {
262264
return resource(({ on }) => {
263265
let time = new TrackedObject({ current: new Date() });
264266
let interval = setInterval(() => (time.current = new Date()), 1_000);
@@ -269,7 +271,9 @@ const Clock = resourceFactory((locale = 'en-US') => {
269271

270272
return () => formatter.format(time.current);
271273
});
272-
});
274+
}
275+
276+
resourceFactory(Clock);
273277

274278
<template>
275279
<time>{{Clock}}</time>
@@ -306,7 +310,7 @@ Supporting reactive argument changes from JS would require an arrow function to
306310
```js
307311
import { resource, resourceFactory, use } from 'ember-resources';
308312

309-
const Clock = resourceFactory((locale = 'en-US') => {
313+
function Clock(locale = 'en-US') {
310314
return resource(({ on }) => {
311315
let currentLocale = locale;
312316

@@ -323,7 +327,8 @@ if (typeof locale === 'function') {
323327

324328
return () => formatter.format(time.current);
325329
});
326-
});
330+
}
331+
resourceFactory(Clock):
327332
```
328333

329334
and then usage in a class would look like:

docs/docs/ember.md

+18-14
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ const Clock = resource(/* ... */);
2929
And then if your resource takes arguments:
3030

3131
```gjs
32-
const Clock = resourceFactory((locale) => {
32+
function Clock(locale) {
3333
return resource(/* ... */);
34-
});
34+
}
35+
36+
resourceFactory(Clock)
3537
3638
<template>
3739
{{Clock 'en-US'}}
@@ -167,13 +169,15 @@ class Demo {
167169

168170
This technique with using a function is nothing special to ember-resources, and can be used with any other data / class / etc as well.
169171

170-
Further, if multiple reactive arguments are needed with individual reactive behavior, you may instead decide to have your `resourceFactory` receive an object.
172+
Further, if multiple reactive arguments are needed with individual reactive behavior, you may instead decide to have your wrapping function receive an object.
171173

172174
<details><summary>about resourceFactory</summary>
173175

174176
`resourceFactory` is a pass-through function purely for telling ember to
175177
invoke the underlying resource immediately after invoking the `resourceFactory` function.
176178

179+
This is why we don't use its return value: it's the same as what you pass to it.
180+
177181
Without `resourceFactory`, ember would need extra internal changes to support primitives that
178182
don't yet exist within the framework to, by convention, decide to _double-invoke_ the functions.
179183

@@ -203,7 +207,7 @@ So when authoring a `Clock` that receives these types of function arguments, but
203207
```js
204208
import { resourceFactory } from 'ember-resources';
205209

206-
export const Clock = resourceFactory(( args ) => {
210+
export function Clock(args) {
207211
return resource(() => {
208212
let { locale, timeZone } = args;
209213

@@ -214,7 +218,9 @@ export const Clock = resourceFactory(( args ) => {
214218

215219
// ...
216220
});
217-
});
221+
}
222+
223+
resourceFactory(Clock);
218224
```
219225

220226
<details><summary>using functions for fine-grained reactivity</summary>
@@ -345,21 +351,19 @@ class Demo {
345351

346352
For TypeScript, you may have noticed that, if you're a library author, you may want to be concerned with supporting all usages of resources in all contexts, in which case, you may need to support overloaded function calls.
347353

348-
TypeScript does not support overloading anonymous functions, so we need to abstract the callback passed to `resourceFactory` into a named function, which we can then define overloads for.
349-
350354
Here is how the overloads for `Compiled`, the resource that represents a dynamically compiled component, provided by `ember-repl`, and used by https://limber.glimdown.com and https://tutorial.glimdown.com.
351355

352356
[compile/index.ts](https://github.com/NullVoxPopuli/limber/blob/main/packages/ember-repl/addon/src/browser/compile/index.ts)
353357

354358
```ts
355359
// Additional types and APIs omitted for brevity
356-
export function buildCompiler(markdownText: Input | (() => Input)): State;
357-
export function buildCompiler(markdownText: Input | (() => Input), options?: Format): State;
358-
export function buildCompiler(markdownText: Input | (() => Input), options?: () => Format): State;
359-
export function buildCompiler(markdownText: Input | (() => Input), options?: ExtraOptions): State;
360-
export function buildCompiler(markdownText: Input | (() => Input), options?: () => ExtraOptions): State;
360+
export function Compiled(markdownText: Input | (() => Input)): State;
361+
export function Compiled(markdownText: Input | (() => Input), options?: Format): State;
362+
export function Compiled(markdownText: Input | (() => Input), options?: () => Format): State;
363+
export function Compiled(markdownText: Input | (() => Input), options?: ExtraOptions): State;
364+
export function Compiled(markdownText: Input | (() => Input), options?: () => ExtraOptions): State;
361365

362-
export function buildCompiler(
366+
export function Compiled(
363367
markdownText: Input | (() => Input),
364368
maybeOptions?: Format | (() => Format) | ExtraOptions | (() => ExtraOptions)
365369
): State {
@@ -383,7 +387,7 @@ export function buildCompiler(
383387
});
384388
}
385389

386-
export const Compiled = resourceFactory(buildCompiler) as typeof buildCompiler;
390+
resourceFactory(Compiled)
387391
```
388392

389393
When defining `Compiled` this way, we can be type-safe in a variety of situations.

docs/docs/resources.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ In this example, the channel name that we're subscribing to is dynamic, and we w
269269
```js
270270
import { resourceFactory, resource, cell } from 'ember-resources';
271271

272-
const ChannelResource = resourceFactory((channelName) => {
272+
function ChannelResource(channelName) {
273273
return resource(({ on }) => {
274274
const lastMessage = cell(null);
275275

@@ -292,7 +292,8 @@ const ChannelResource = resourceFactory((channelName) => {
292292
}
293293
};
294294
});
295-
});
295+
}
296+
resourceFactory(ChannelResource);
296297
```
297298

298299
To see this code in action, [checkout the live demo](https://limber.glimdown.com/edit?c=MQAgMglgtgRgpgJxAUQCYQC4HsEChcAicUWAdgM4YICGGEZIWAZiNSAEpzlYCuCAxnBAYAFrRAI4AB0nk4pDOWEihAIhKUJcQQpBQu5agHM4qrYIgA3OKkalWIAOpwYAZSz8A1nAwgAwmKkpHAANgB0%2BAAG0UYAVkohVnC40FI4vgDeWtx8ggBi1PzYCACeADTZvAJwFYIhISAAviBMCFhQIADkxPAIALSyVYLknQDc%2BAD0AFRTIAAKkhjytgHUQaEgqSHE8hi09PZMOCAwkpaYJSBTE7j8ZJqr6w0AvCAZuCAg5Dww5PwIEHgAC4QAAKfiBYIhABy1H0AEoQM8AHxvD6fEDbXz8aj1GCFTxKV4AbQAuuN0Z8JhMvtAeCFaEJJBZzqQjF8PN5fPpyIYTEopIh6OgcfUSpTMT5NgpEJZcUivj4AJIyhBykKg0GIlFojEYrGbWyvACytBEYTaPFIqFBptEFrWqHaWquIAAHAAGREAahAAEZxnrPgaQHwXiBIiIMBgpOQgdTyAB3ahSCBhVBwSwTFMQCYAEgyELWUNh%2Bka%2BYyEFQjUi%2BCDLR8ENBYfhEr1YVE8lBsjSFCEOp79zgYXiZC1rfrnw7KlIoNQtDYOvek4xopC%2BK85DCUBT4Nx64JSNRa43njnC7CpDhcHhE8njXhgYxjQqfo978fdYxiz49mXQbIY0DGMOAQVBJhSG1Y991PLcpB4cgRHAyCyjbUMKB%2BP4AWBMEoN1ScTwJIkQDJJ9634bZqAQFUljVXFQQgVV1U-etGglNjPjYtj8DuChfEeKFOByaoFUGXI4AKIocBKTUiyeUsbyPfCfwQewxOqTUsgYB8lP-T5eM0BlKCA3kQIVOoNVIekQhYiUDOxSENleATQjCb5fn%2BQE4HBRyYWvWy9TkqEwkA4CTE1Hk%2BUUpc0KMjATKityfFBSKQJY58AoxMgwgouA1h4KRNTwvTV18sIrXcrCvK1Mimkyz4VPsF0YvI%2B5fBkOAmAgAAPBVImJAsgtCBTGlJCNas%2BCAWFBOKEpAnK%2BEkXRnhWkArPqRESr1RqIwLDquu65poSwPQwq4cw4CSWwSh8SIJqaEBpmQP1rhAUI5Hw%2BsdsiPbJAO5oC1ms6FoQJaMBre6OOfJ8H3GWH8AAHiWKApAZJZkXRBH0EsL4MBKbZnlUGAcAzBAQT9KReu4RJUFGEApGoVB0DZcnJCgUZVAxvUMgyFyQiEoY1EFLBUdMRooYRiZsYxyXkdRxkMeiWsgA&format=glimdown)

ember-resources/src/function-based/immediate-invocation.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class ResourceInvokerManager {
8989
* ```js
9090
* import { resource, resourceFactory } from 'ember-resources';
9191
*
92-
* const RemoteData = resourceFactory((url) => {
92+
* function RemoteData(url) {
9393
* return resource(({ on }) => {
9494
* let state = new TrackedObject({});
9595
* let controller = new AbortController();
@@ -107,7 +107,9 @@ class ResourceInvokerManager {
107107
*
108108
* return state;
109109
* })
110-
* });
110+
* }
111+
*
112+
* resourceFactory(RemoteData);
111113
*
112114
* <template>
113115
* {{#let (RemoteData "http://....") as |state|}}

ember-resources/src/type-tests/use.test.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const Clock = resource(({ on }) => {
1313
return now;
1414
});
1515

16-
const ParameterizedClock = resourceFactory((locale = 'en-US') => {
16+
function ParameterizedClock(locale = 'en-US') {
1717
return resource(({ use }) => {
1818
let now = use(Clock);
1919
let formatter = new Intl.DateTimeFormat(locale);
@@ -22,7 +22,9 @@ const ParameterizedClock = resourceFactory((locale = 'en-US') => {
2222
return formatter.format(now.current);
2323
};
2424
});
25-
});
25+
}
26+
27+
resourceFactory(ParameterizedClock);
2628

2729
class DemoA {
2830
@use stuck = StuckClock;

0 commit comments

Comments
 (0)