From 4865fe5c282a9cde4500a60ac25d2f649bf9b88a Mon Sep 17 00:00:00 2001 From: Anthony Gubler Date: Fri, 27 Nov 2020 09:54:56 +0000 Subject: [PATCH 1/2] Merges createResourceTemplate, createResourceWithInit and createMemoryResource --- src/core/middleware/resources.ts | 32 ++++----- tests/core/unit/middleware/resources.tsx | 89 +++++++----------------- 2 files changed, 40 insertions(+), 81 deletions(-) diff --git a/src/core/middleware/resources.ts b/src/core/middleware/resources.ts index 29c014e9d..7719337f6 100644 --- a/src/core/middleware/resources.ts +++ b/src/core/middleware/resources.ts @@ -301,23 +301,19 @@ interface ResourceMiddleware { ): boolean; } -export function createResourceTemplate( - template: ResourceTemplate -): ResourceTemplate & { type: 'standard' } { - return template as ResourceTemplate & { type: 'standard' }; -} - -export function createResourceTemplateWithInit( - template: ResourceTemplateWithInit -): ResourceTemplateWithInit & { type: 'init' } { - return template as ResourceTemplateWithInit & { type: 'init' }; -} - -export function createMemoryResourceTemplate(): ResourceTemplateWithInit< - RESOURCE, - { data: RESOURCE[] } -> & { type: 'init' } { - return { ...memoryTemplate } as ResourceTemplateWithInit & { type: 'init' }; +export function createResourceTemplate(): ResourceTemplateWithInit & { + type: 'init'; +}; +export function createResourceTemplate( + template: INIT extends void ? ResourceTemplate : ResourceTemplateWithInit +): INIT extends void + ? ResourceTemplate & { type: 'standard' } + : ResourceTemplateWithInit & { type: 'init' }; +export function createResourceTemplate(template?: any): any { + if (template) { + return template; + } + return { ...memoryTemplate }; } export function defaultFilter(query: ResourceQuery, item: any, type: string = 'contains') { @@ -985,7 +981,7 @@ const resourceMiddlewareFactory = factory( ) => { if (!nextProp || !nextProp.template) { return middleware({ - template: createMemoryResourceTemplate(), + template: createResourceTemplate(), initOptions: { data: [], id: '' }, ...nextProp }); diff --git a/tests/core/unit/middleware/resources.tsx b/tests/core/unit/middleware/resources.tsx index 7579ab44e..553dc11e7 100644 --- a/tests/core/unit/middleware/resources.tsx +++ b/tests/core/unit/middleware/resources.tsx @@ -7,9 +7,7 @@ import Map from '../../../../src/shim/Map'; import '../../../../src/shim/Promise'; import { createResolvers } from '../../support/util'; import { - createResourceTemplateWithInit, createResourceMiddleware, - createMemoryResourceTemplate, memoryTemplate, createResourceTemplate, defaultFind @@ -38,7 +36,7 @@ describe('Resources Middleware', () => { return
{JSON.stringify(getOrRead(template, options()))}
; }); - const template = createMemoryResourceTemplate<{ hello: string }>(); + const template = createResourceTemplate<{ hello: string }>(); const App = create({ resource: createResourceMiddleware() })(({ id, middleware: { resource } }) => { return ; @@ -69,9 +67,7 @@ describe('Resources Middleware', () => { ); }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const App = create({ resource: createResourceMiddleware() })(({ id, middleware: { resource } }) => { return ( @@ -115,7 +111,7 @@ describe('Resources Middleware', () => { return
{JSON.stringify(getOrRead(template, options()))}
; }); - const template = createMemoryResourceTemplate<{ hello: string }>(); + const template = createResourceTemplate<{ hello: string }>(); const r = renderer(() => ( )); @@ -173,9 +169,7 @@ describe('Resources Middleware', () => { ); }); - const template = createResourceTemplateWithInit<{ wrong: string }, { data: { wrong: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ wrong: string }, { data: { wrong: string }[] }>(memoryTemplate); const App = create({ resource: createResourceMiddleware() })(({ id, middleware: { resource } }) => { return ( @@ -206,7 +200,7 @@ describe('Resources Middleware', () => { return
{JSON.stringify(getOrRead(template, options({ query: { hello: '2', foo: '1' } })))}
; }); - const template = createResourceTemplateWithInit< + const template = createResourceTemplate< { wrong: string; foo: string }, { data: { wrong: string; foo: string }[] } >(memoryTemplate); @@ -242,7 +236,7 @@ describe('Resources Middleware', () => { return
{JSON.stringify(getOrRead(template, options({ query: { age: 10 } })))}
; }); - const template = createResourceTemplateWithInit<{ age: number }, { data: { age: number }[] }>(memoryTemplate); + const template = createResourceTemplate<{ age: number }, { data: { age: number }[] }>(memoryTemplate); const App = create({ resource: createResourceMiddleware() })(({ id, middleware: { resource } }) => { return ( @@ -271,9 +265,7 @@ describe('Resources Middleware', () => { return
{JSON.stringify(getOrRead(template, options({ size: 1 })))}
; }); - const template = createResourceTemplateWithInit<{ wrong: number }, { data: { wrong: number }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ wrong: number }, { data: { wrong: number }[] }>(memoryTemplate); const App = create({ resource: createResourceMiddleware() })(({ id, middleware: { resource } }) => { return ( @@ -390,9 +382,7 @@ describe('Resources Middleware', () => { it('should be able to share resource options across between widgets', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>() }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const WidgetOne = factory(({ properties, id, middleware: { resource } }) => { const { createOptions } = resource; @@ -459,9 +449,7 @@ describe('Resources Middleware', () => { it('should be only destroy the resource once all subscribers have been removed', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>(), icache }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const WidgetOne = factory(({ id, properties, middleware: { resource } }) => { const { createOptions } = resource; @@ -575,9 +563,7 @@ describe('Resources Middleware', () => { it('should be able to share search query across widgets', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>() }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const WidgetOne = factory(({ id, properties, middleware: { resource } }) => { const { createOptions } = resource; @@ -644,9 +630,7 @@ describe('Resources Middleware', () => { it('should update the data in the resource', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>() }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const WidgetOne = factory(({ id, properties, middleware: { resource } }) => { const { getOrRead, createOptions } = resource; @@ -690,9 +674,7 @@ describe('Resources Middleware', () => { it('should update the data in existing resources', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>() }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const WidgetOne = factory(({ id, properties, middleware: { resource } }) => { const { getOrRead, createOptions } = resource; @@ -749,9 +731,7 @@ describe('Resources Middleware', () => { it('should be able to change the options for a resource', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>() }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); const WidgetOne = factory(({ id, properties, middleware: { resource } }) => { const { getOrRead, createOptions } = resource; @@ -834,10 +814,9 @@ describe('Resources Middleware', () => { }); it('should be able to use a resource directly in a widget with init options', () => { - const template = createResourceTemplateWithInit< - { hello: string }, - { other: string; data: { hello: string }[] } - >(memoryTemplate); + const template = createResourceTemplate<{ hello: string }, { other: string; data: { hello: string }[] }>( + memoryTemplate + ); const App = create({ icache, resource: createResourceMiddleware() })(({ middleware: { resource, icache } }) => { const { createOptions, getOrRead } = resource; const options = createOptions('test'); @@ -879,9 +858,7 @@ describe('Resources Middleware', () => { it('should destroy resources when widget is removed', () => { const factory = create({ resource: createResourceMiddleware<{ hello: string }>() }); - const template = createResourceTemplateWithInit<{ hello: string }, { data: { hello: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ hello: string }, { data: { hello: string }[] }>(memoryTemplate); let renderCount = 0; let callOptions: any; const WidgetOne = factory(({ id, properties, middleware: { resource } }) => { @@ -1039,7 +1016,7 @@ describe('Resources Middleware', () => { } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 20; i++) { data.push({ foo: `Item ${i}` }); @@ -1089,7 +1066,7 @@ describe('Resources Middleware', () => { ); }); - const template = createResourceTemplateWithInit<{ value: string }, { data: { value: string }[] }>({ + const template = createResourceTemplate<{ value: string }, { data: { value: string }[] }>({ init: ({ data }, { put }) => { put({ data, total: data.length }, { offset: 0, size: 30, query: {} }); }, @@ -1234,9 +1211,7 @@ describe('Resources Middleware', () => { ); }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 200; i++) { if (i % 10 === 0) { @@ -1394,9 +1369,7 @@ describe('Resources Middleware', () => { ); } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 200; i++) { if (i % 10 === 0) { @@ -1436,9 +1409,7 @@ describe('Resources Middleware', () => { ); } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 200; i++) { if (i % 10 === 0) { @@ -1480,9 +1451,7 @@ describe('Resources Middleware', () => { ); } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 200; i++) { data.push({ foo: `${i} Item` }); @@ -1523,9 +1492,7 @@ describe('Resources Middleware', () => { ); } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 201; i++) { data.push({ foo: `${i} Item` }); @@ -1568,9 +1535,7 @@ describe('Resources Middleware', () => { ); } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 200; i++) { if (i % 10 === 0) { @@ -1615,9 +1580,7 @@ describe('Resources Middleware', () => { ); } }); - const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string }[] }>( - memoryTemplate - ); + const template = createResourceTemplate<{ foo: string }, { data: { foo: string }[] }>(memoryTemplate); let data: { foo: string }[] = []; for (let i = 0; i < 200; i++) { if (i % 10 === 0) { From e5e705274a5adcbe0fbc56a8e87e7a15f8352e7e Mon Sep 17 00:00:00 2001 From: Anthony Gubler Date: Tue, 1 Dec 2020 11:13:22 +0000 Subject: [PATCH 2/2] Update docs and provide deprecated shims for the old APIs --- docs/en/resources/introduction.md | 8 ++++---- docs/en/resources/supplemental.md | 22 +++++++++++----------- src/core/middleware/resources.ts | 16 ++++++++++++++++ tests/core/unit/middleware/resources.tsx | 10 +++++++--- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/docs/en/resources/introduction.md b/docs/en/resources/introduction.md index a5dcefa6d..b1b1220ba 100644 --- a/docs/en/resources/introduction.md +++ b/docs/en/resources/introduction.md @@ -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 ; @@ -72,7 +72,7 @@ interface ResourceData { value: string; } -const resource = createDataMiddleware(); +const resource = createResourceMiddleware(); const factory = create({ resource }); diff --git a/docs/en/resources/supplemental.md b/docs/en/resources/supplemental.md index 538a7fd7d..342e61a4e 100644 --- a/docs/en/resources/supplemental.md +++ b/docs/en/resources/supplemental.md @@ -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` 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; @@ -260,15 +260,15 @@ export interface ResourceInit { 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; @@ -281,7 +281,7 @@ interface MyWidgetProperties { const resource = createResourceMiddleware(); const factory = create({ resource }).properties(); -const template = createMemoryResourceTemplate(); +const template = createResourceTemplate(); export default factory(function MyWidget({ id, properties, middleware: { resource } }) { const { items } = properties(); @@ -328,10 +328,10 @@ export default createResourceTemplate({ ### 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; @@ -339,7 +339,7 @@ interface MyResource { email: string; } -export default createResourceTemplateWithInit({ +export default createResourceTemplate({ init: (request: { id: string } & { data: MyResource[] }, controls: ResourceControls) => { const { data } = request; // adds any data passed with the template to resource store @@ -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 diff --git a/src/core/middleware/resources.ts b/src/core/middleware/resources.ts index 7719337f6..b13a8da94 100644 --- a/src/core/middleware/resources.ts +++ b/src/core/middleware/resources.ts @@ -316,6 +316,22 @@ export function createResourceTemplate(template?: any): any { return { ...memoryTemplate }; } +/** + * @deprecated Please use `createResourceTemplate` instead + */ +export function createResourceTemplateWithInit( + template: ResourceTemplateWithInit +) { + return createResourceTemplate(template as any); +} + +/** + * @deprecated Please use `createResourceTemplate` instead + */ +export function createMemoryResourceTemplate() { + return createResourceTemplate(); +} + export function defaultFilter(query: ResourceQuery, item: any, type: string = 'contains') { const queryKeys = Object.keys(query); for (let i = 0; i < queryKeys.length; i++) { diff --git a/tests/core/unit/middleware/resources.tsx b/tests/core/unit/middleware/resources.tsx index 553dc11e7..a5327c9e6 100644 --- a/tests/core/unit/middleware/resources.tsx +++ b/tests/core/unit/middleware/resources.tsx @@ -10,6 +10,8 @@ import { createResourceMiddleware, memoryTemplate, createResourceTemplate, + createMemoryResourceTemplate, + createResourceTemplateWithInit, defaultFind } from '../../../../src/core/middleware/resources'; import icache from '../../../../src/core/middleware/icache'; @@ -90,7 +92,7 @@ describe('Resources Middleware', () => { it('should provide a default if no resource property is passed', () => { const factory = create({ resource: createResourceMiddleware<{}>() }); - const Widget = factory(({ id, properties }) => { + const Widget = factory(({ properties }) => { const { resource } = properties(); return resource &&
contents
; }); @@ -111,7 +113,7 @@ describe('Resources Middleware', () => { return
{JSON.stringify(getOrRead(template, options()))}
; }); - const template = createResourceTemplate<{ hello: string }>(); + const template = createMemoryResourceTemplate<{ hello: string }>(); const r = renderer(() => ( )); @@ -169,7 +171,9 @@ describe('Resources Middleware', () => { ); }); - const template = createResourceTemplate<{ wrong: string }, { data: { wrong: string }[] }>(memoryTemplate); + const template = createResourceTemplateWithInit<{ wrong: string }, { data: { wrong: string }[] }>({ + ...memoryTemplate + }); const App = create({ resource: createResourceMiddleware() })(({ id, middleware: { resource } }) => { return (