Skip to content

Commit

Permalink
Refines the create template function APIs (#866)
Browse files Browse the repository at this point in the history
* Merges createResourceTemplate, createResourceWithInit and createMemoryResource

* Update docs and provide deprecated shims for the old APIs
  • Loading branch information
agubler authored Dec 1, 2020
1 parent 272a7ef commit 384c639
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 91 deletions.
8 changes: 4 additions & 4 deletions docs/en/resources/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ Dojo Resources is designed to provide a consistent pattern to make widgets "reso

In order to work with Dojo resources, widgets need to use the `resource` middleware created with the `createResourceMiddleware` factory from `@dojo/framework/middleware/resources`. There are two types of "resource-aware" widgets: widgets that expose a `resource` on their property API and widgets that need to use a resource internally. The same factory is used to create both types of middleware, but the main difference is for widgets that require resources to be passed via properties, a resource type is needed on creation.

Using the `resource` middleware enables working with resource templates in your widget. Resources templates are created using the `createResourceTemplate` and `createResourceTemplateWithInit` factories from `@dojo/framework/middleware/resources`. Dojo resources also provides a utility factory `createMemoryResourceTemplate` which can be used to create a resource template that can be populated on initialization and works with the data in the client. The initialization includes a `data` and an `id` that is required to identify the instance of the resource and is passed with `template` into the `resource` middleware to use with a "resource" aware widget.
Using the `resource` middleware enables working with resource templates in your widget. Resources templates are created using the `createResourceTemplate` factory from `@dojo/framework/middleware/resources`. If a custom template is not passed to the `createResourceTemplate` factory the default resources template will be used. The default template required `initOptions` which include `data` and an `id` to identify the instance of the resource and is passed with `template` into the `resource` middleware to use with a "resource" aware widget.

> App.tsx
```tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import { createMemoryResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
import DataAwareWidget from './DataAwareWidget';

const resource = createResourceMiddleware();
const factory = create({ resource });
const myTemplate = createMemoryResourceTemplate<{ foo: string }>();
const myTemplate = createResourceTemplate<{ foo: string }>();

const App = factory(function App({ id, middleware: { resource } }) {
return <DataAwareWidget resource={resource({ template, initOptions: { id, data: [{ foo: 'string' }] } })} />;
Expand Down Expand Up @@ -72,7 +72,7 @@ interface ResourceData {
value: string;
}

const resource = createDataMiddleware<ResourceData>();
const resource = createResourceMiddleware<ResourceData>();

const factory = create({ resource });

Expand Down
22 changes: 11 additions & 11 deletions docs/en/resources/supplemental.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,14 @@ The `type` describes how to use the query to find the item in the resource, ther
## `init()`
The `init` function is used to deal with options passed with the `template` using the `resource` middleware. These options are defined when creating the template using `createResourceTemplateWithInit` as the second generic parameter.
The `init` function is used to deal with options passed with the `template` using the `resource` middleware. These options are defined when creating the template and passing an interface for the required options, `createResourceTemplate<RESOURCE, INIT>` as the second generic parameter.
```tsx
import { createResourceTemplateWithInit } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';


// only showing the init api
const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string; }[]; extra: number; }>({
const template = createResourceTemplate<{ foo: string }, { data: { foo: string; }[]; extra: number; }>({
init: (options, controls) {
// the options matches the type passed as the second generic
const { data, extra } = options;
Expand All @@ -260,15 +260,15 @@ export interface ResourceInit<S, I> {
The init options are injected into the function along with the standard `ResourceControls` to be used to add the initialize the resource store.
## Memory Resource Templates
## Default Resource Templates
Dojo resources offers a pre-configured memory resource template that implements the complete resource template API. The memory template is designed to work with [data passed to a widget when using the template](/learn/resources/using-resource-templates) that initializes the resource store for the template. The memory template is created using the `createMemoryResourceTemplate` factory from `@dojo/framework/core/middleware/resources`, with the type of the resource data being passed to the factory.
Dojo resources offers a pre-configured default resource template that implements the complete resource template API. The default template is designed to work with [data passed to a widget when using the template](/learn/resources/using-resource-templates) that initializes the resource store for the template. The memory template is created using the `createResourceTemplate` factory from `@dojo/framework/core/middleware/resources` passing no arguments.
> MyWidget.tsx
```tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import { createMemoryResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';

interface ResourceItem {
value: string;
Expand All @@ -281,7 +281,7 @@ interface MyWidgetProperties {
const resource = createResourceMiddleware();
const factory = create({ resource }).properties<MyWidgetProperties>();

const template = createMemoryResourceTemplate<ResourceItem>();
const template = createResourceTemplate<ResourceItem>();

export default factory(function MyWidget({ id, properties, middleware: { resource } }) {
const { items } = properties();
Expand Down Expand Up @@ -328,18 +328,18 @@ export default createResourceTemplate<MyResource>({

### Create a Resource Template with initialization options

If the resource template needs to support custom initialization the `createResourceTemplateWithInit` can be used. This requires the template to have an `init` API that will be called when a backing resource is created. The initialize options required are typed using the second generic on the factory function.
If the resource template needs to support custom initialization the `createResourceTemplate` can be used. This requires the template to have an `init` API that will be called when a backing resource is created. The initialize options required are typed using the second generic on the factory function.

```tsx
import { createResourceTemplateWithInit } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';

interface MyResource {
id: string;
name: string;
email: string;
}

export default createResourceTemplateWithInit<MyResource, { data: MyResource[] }>({
export default createResourceTemplate<MyResource, { data: MyResource[] }>({
init: (request: { id: string } & { data: MyResource[] }, controls: ResourceControls) => {
const { data } = request;
// adds any data passed with the template to resource store
Expand Down Expand Up @@ -422,7 +422,7 @@ export factory(function MyWidget({ middleware: { resource }}) {

## Passing Initialization Options

Initialization options can be passed with any template created using the `createResourceTemplateWithInit` factory and are passed to the template's `init` function to initialize the resource. The `initOptions` includes an `id` used to identify the backing resource and optional `data` that can be added to the resource on creation.
Initialization options can be passed with any template created using the `createResourceTemplate` factory and are passed to the template's `init` function to initialize the resource. The `initOptions` includes an `id` used to identify the backing resource and optional `data` that can be added to the resource on creation.

> MyWidget.ts

Expand Down
38 changes: 25 additions & 13 deletions src/core/middleware/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,23 +301,35 @@ interface ResourceMiddleware<MIDDLEWARE = {}> {
): boolean;
}

export function createResourceTemplate<RESOURCE = void>(
template: ResourceTemplate<RESOURCE>
): ResourceTemplate<RESOURCE> & { type: 'standard' } {
return template as ResourceTemplate<RESOURCE> & { type: 'standard' };
export function createResourceTemplate<RESOURCE = void>(): ResourceTemplateWithInit<RESOURCE, { data: RESOURCE[] }> & {
type: 'init';
};
export function createResourceTemplate<RESOURCE = void, INIT = void>(
template: INIT extends void ? ResourceTemplate<RESOURCE> : ResourceTemplateWithInit<RESOURCE, INIT>
): INIT extends void
? ResourceTemplate<RESOURCE> & { type: 'standard' }
: ResourceTemplateWithInit<RESOURCE, INIT> & { type: 'init' };
export function createResourceTemplate(template?: any): any {
if (template) {
return template;
}
return { ...memoryTemplate };
}

export function createResourceTemplateWithInit<RESOURCE = void, INIT = never>(
/**
* @deprecated Please use `createResourceTemplate` instead
*/
export function createResourceTemplateWithInit<RESOURCE = void, INIT = {}>(
template: ResourceTemplateWithInit<RESOURCE, INIT>
): ResourceTemplateWithInit<RESOURCE, INIT> & { type: 'init' } {
return template as ResourceTemplateWithInit<RESOURCE, INIT> & { type: 'init' };
) {
return createResourceTemplate<RESOURCE, INIT>(template as any);
}

export function createMemoryResourceTemplate<RESOURCE = void>(): ResourceTemplateWithInit<
RESOURCE,
{ data: RESOURCE[] }
> & { type: 'init' } {
return { ...memoryTemplate } as ResourceTemplateWithInit<RESOURCE, { data: RESOURCE[] }> & { type: 'init' };
/**
* @deprecated Please use `createResourceTemplate` instead
*/
export function createMemoryResourceTemplate<RESOURCE = void>() {
return createResourceTemplate<RESOURCE>();
}

export function defaultFilter(query: ResourceQuery<any>, item: any, type: string = 'contains') {
Expand Down Expand Up @@ -985,7 +997,7 @@ const resourceMiddlewareFactory = factory(
) => {
if (!nextProp || !nextProp.template) {
return middleware({
template: createMemoryResourceTemplate(),
template: createResourceTemplate(),
initOptions: { data: [], id: '' },
...nextProp
});
Expand Down
Loading

0 comments on commit 384c639

Please sign in to comment.