diff --git a/packages/generator-overreact-odata/src/index.js b/packages/generator-overreact-odata/src/index.js index 59fdb84..8655695 100644 --- a/packages/generator-overreact-odata/src/index.js +++ b/packages/generator-overreact-odata/src/index.js @@ -135,6 +135,7 @@ module.exports = class extends Generator { } async configuring() { + this.packageJson.set(this.packageJsonConfigs); const { url } = this.overreactJsonConfigs; try { this.log(`Fetching metadata from ${url}`); @@ -147,8 +148,6 @@ module.exports = class extends Generator { this.log('Metadata fetched.'); if (this.stage === packageStage.FIRST_RUN) { - this.packageJson.set(this.packageJsonConfigs); - const MODEL_PREFIX = 'Model/'; const pascalToSnakeCase = str => str.split(/(?=[A-Z])/).join('_').toLowerCase(); const modelAliases = {}; diff --git a/packages/generator-overreact-odata/src/templates/calls/action-spec.ejs b/packages/generator-overreact-odata/src/templates/calls/action-spec.ejs index 710c809..3dba6b8 100644 --- a/packages/generator-overreact-odata/src/templates/calls/action-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/calls/action-spec.ejs @@ -21,6 +21,7 @@ import { payloadDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './action-decorators'; @@ -75,7 +76,7 @@ export const fetchSpec = createSpec( requestContract, responseContract, specTypes.FETCH, - null, + sideEffects.fetch, environmentLookupFn, ); @@ -83,6 +84,6 @@ export const actionSpec = createSpec( requestContract, responseContract, specTypes.MUTATION, - null, + sideEffects.mutation, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/calls/func-spec.ejs b/packages/generator-overreact-odata/src/templates/calls/func-spec.ejs index 7921857..cd4e3bb 100644 --- a/packages/generator-overreact-odata/src/templates/calls/func-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/calls/func-spec.ejs @@ -20,6 +20,7 @@ import { headerDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './func-decorators'; @@ -68,7 +69,7 @@ export const fetchSpec = createSpec( requestContract, responseContract, specTypes.FETCH, - null, + sideEffects.fetch, environmentLookupFn, ); @@ -76,6 +77,6 @@ export const refetchSpec = createSpec( requestContract, responseContract, specTypes.REFETCH, - null, + sideEffects.refetch, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/coll/add-spec.ejs b/packages/generator-overreact-odata/src/templates/coll/add-spec.ejs index 60d73aa..0a4305d 100644 --- a/packages/generator-overreact-odata/src/templates/coll/add-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/coll/add-spec.ejs @@ -21,6 +21,7 @@ import { payloadDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './add-decorators'; @@ -75,6 +76,6 @@ export const addSpec = createSpec( requestContract, responseContract, specTypes.ADD, - null, + sideEffects.add, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/coll/destroy-spec.ejs b/packages/generator-overreact-odata/src/templates/coll/destroy-spec.ejs index 7aeb419..037ea03 100644 --- a/packages/generator-overreact-odata/src/templates/coll/destroy-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/coll/destroy-spec.ejs @@ -20,6 +20,7 @@ import { headerDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './destroy-decorators'; @@ -68,6 +69,6 @@ export const destroySpec = createSpec( requestContract, responseContract, specTypes.DELETE, - null, + sideEffects.destroy, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/coll/fetch-spec.ejs b/packages/generator-overreact-odata/src/templates/coll/fetch-spec.ejs index e5d2fe8..e27d0ab 100644 --- a/packages/generator-overreact-odata/src/templates/coll/fetch-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/coll/fetch-spec.ejs @@ -20,6 +20,7 @@ import { headerDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './fetch-decorators'; @@ -68,7 +69,7 @@ export const fetchSpec = createSpec( requestContract, responseContract, specTypes.PAGINATION, - null, + sideEffects.pagination, environmentLookupFn, ); @@ -76,6 +77,6 @@ export const refetchSpec = createSpec( requestContract, responseContract, specTypes.REFETCH, - null, + sideEffects.refetch, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/coll/mutation-spec.ejs b/packages/generator-overreact-odata/src/templates/coll/mutation-spec.ejs index 8d2a880..21e11c8 100644 --- a/packages/generator-overreact-odata/src/templates/coll/mutation-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/coll/mutation-spec.ejs @@ -21,6 +21,7 @@ import { payloadDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './mutation-decorators'; @@ -75,6 +76,6 @@ export const mutationSpec = createSpec( requestContract, responseContract, specTypes.MUTATION, - null, + sideEffects.mutation, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/entity/destroy-spec.ejs b/packages/generator-overreact-odata/src/templates/entity/destroy-spec.ejs index 6441408..3a2d725 100644 --- a/packages/generator-overreact-odata/src/templates/entity/destroy-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/entity/destroy-spec.ejs @@ -20,6 +20,7 @@ import { headerDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './destroy-decorators'; @@ -68,6 +69,6 @@ export const destroySpec = createSpec( requestContract, responseContract, specTypes.DELETE, - null, + sideEffects.destroy, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/entity/fetch-spec.ejs b/packages/generator-overreact-odata/src/templates/entity/fetch-spec.ejs index d617e56..445cc2e 100644 --- a/packages/generator-overreact-odata/src/templates/entity/fetch-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/entity/fetch-spec.ejs @@ -20,6 +20,7 @@ import { headerDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './fetch-decorators'; @@ -68,7 +69,7 @@ export const fetchSpec = createSpec( requestContract, responseContract, specTypes.FETCH, - null, + sideEffects.fetch, environmentLookupFn, ); @@ -76,6 +77,6 @@ export const refetchSpec = createSpec( requestContract, responseContract, specTypes.REFETCH, - null, + sideEffects.refetch, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/entity/mutation-spec.ejs b/packages/generator-overreact-odata/src/templates/entity/mutation-spec.ejs index b91be32..3b422ce 100644 --- a/packages/generator-overreact-odata/src/templates/entity/mutation-spec.ejs +++ b/packages/generator-overreact-odata/src/templates/entity/mutation-spec.ejs @@ -21,6 +21,7 @@ import { payloadDecorator, processorDecorator, keySelectorDecorator, + sideEffects, networkPolicy, } from './mutation-decorators'; @@ -75,6 +76,6 @@ export const mutationSpec = createSpec( requestContract, responseContract, specTypes.MUTATION, - null, + sideEffects.mutation, environmentLookupFn, ); diff --git a/packages/generator-overreact-odata/src/templates/hooks/use-action.ejs b/packages/generator-overreact-odata/src/templates/hooks/use-action.ejs index 094bee3..2e5da04 100644 --- a/packages/generator-overreact-odata/src/templates/hooks/use-action.ejs +++ b/packages/generator-overreact-odata/src/templates/hooks/use-action.ejs @@ -1,4 +1,5 @@ import { useCallback, useMemo } from 'react'; +import stringify from 'json-stable-stringify'; import { useFetch, @@ -9,8 +10,9 @@ import { import { environmentLookupFn } from '<%= envLocation %>'; import { fetchSpec, actionSpec } from '../../__specs/calls/action-spec'; -export function <%- hookName %>(dataLocator, config = {}) { - const dataRefId = useDataRefId(environmentLookupFn); +export function <%- hookName %>(variables, config = {}) { + const { dataLocator } = variables; + const dataRefId = useDataRefId(`call_${stringify(dataLocator)}`, environmentLookupFn); const defaultConfig = useMemo(() => ({ mutation: config.mutation || {}, @@ -23,12 +25,15 @@ export function <%- hookName %>(dataLocator, config = {}) { const action = useMutation(dataRefId, actionSpec, mutationConfig); const callFn = useCallback((param = {}, requestConfig, ...rest) => { - action({ - ...dataLocator, - ...param.variables, - }, - param.payload, - requestConfig, ...rest); + action( + { + ...dataLocator, + ...param.variables, + }, + param.payload, + requestConfig, + ...rest + ); }, [dataLocator, action]); const [data, error] = fetch; diff --git a/packages/generator-overreact-odata/src/templates/hooks/use-coll.ejs b/packages/generator-overreact-odata/src/templates/hooks/use-coll.ejs index 5fdad77..6cb5dc2 100644 --- a/packages/generator-overreact-odata/src/templates/hooks/use-coll.ejs +++ b/packages/generator-overreact-odata/src/templates/hooks/use-coll.ejs @@ -1,5 +1,12 @@ import { useCallback, useMemo } from 'react'; -import { useDataRefId, usePagination, useMutation } from '@microsoft/overreact'; +import stringify from 'json-stable-stringify'; + +import { + useDataRefId, + usePagination, + useMutation, + useRefetch, +} from '@microsoft/overreact'; import { environmentLookupFn } from '<%= envLocation %>'; @@ -8,37 +15,60 @@ import { destroySpec } from '../../__specs/coll/destroy-spec'; import { fetchSpec, refetchSpec } from '../../__specs/coll/fetch-spec'; import { mutationSpec } from '../../__specs/coll/mutation-spec'; -export function <%- hookName %>(specs, path, variables, config = {}) { - const dataRefId = useDataRefId(environmentLookupFn); +export function <%- hookName %>(variables, config = {}) { + const { dataLocator } = variables; + const dataRefId = useDataRefId(`coll_${stringify(dataLocator)}`, environmentLookupFn); - // FIXME: extract fetchVariables out from the config - const paginationConfig = useMemo(() => ({ - fetchVariables: { - ...variables, - }, - ...config, - }), [config, variables]); + const defaultConfig = useMemo(() => ({ + refetch: config.refetch || {}, + mutation: config.mutation || {}, + destroy: config.destroy || {}, + pagination: config.pagination || {}, + create: config.add || {}, + }), [config]); - const [data, methods] = usePagination(dataRefId, fetchSpec, paginationConfig); + const { + refetch: refetchConfig, + mutation: mutationConfig, + destroy: destroyConfig, + pagination: paginationConfig, + create: createConfig, + } = defaultConfig; - const mutateFn = useMutation(dataRefId, mutationSpec, config); - const destroyFn = useMutation(dataRefId, destroySpec, config); - const createFn = useMutation(dataRefId, addSpec, config); + const [data, paginationMethods] = usePagination(dataRefId, fetchSpec, paginationConfig); + const mutateFn = useMutation(dataRefId, mutationSpec, mutationConfig); + const destroyFn = useMutation(dataRefId, destroySpec, destroyConfig); + const createFn = useMutation(dataRefId, addSpec, createConfig); + const refetchFn = useRefetch(dataRefId, refetchSpec, refetchConfig); const update = useCallback((newData, ...rest) => { - mutateFn(variables, newData, ...rest); - }, [mutateFn, variables]); + mutateFn({ ...dataLocator }, newData, ...rest); + }, [mutateFn, dataLocator]); // FIXME: likezh: Why would destroy need data? const destroy = useCallback((newData, ...rest) => { - destroyFn(variables, newData, ...rest); - }, [destroyFn, variables]); + destroyFn({ ...dataLocator }, newData, ...rest); + }, [destroyFn, dataLocator]); const create = useCallback((newData, ...rest) => { - createFn(variables, newData, ...rest); - }, [createFn, variables]); + createFn({ ...dataLocator }, newData, ...rest); + }, [createFn, dataLocator]); - const { loadMore, hasMore, isLoading } = methods; + const refetch = useCallback((parameter, ...rest) => { + refetchFn( + { + variables: { + ...dataLocator, + ...parameter.variables, + }, + payload: parameter.payload, + }, + refetchConfig, + ...rest + ); + }, [refetchFn, refetchConfig, dataLocator]); + + const { loadMore, hasMore, isLoading } = paginationMethods; return [data, { loadMore, @@ -47,5 +77,6 @@ export function <%- hookName %>(specs, path, variables, config = {}) { create, update, destroy, + refetch, }]; } diff --git a/packages/generator-overreact-odata/src/templates/hooks/use-entity.ejs b/packages/generator-overreact-odata/src/templates/hooks/use-entity.ejs index de3c9e0..332ac89 100644 --- a/packages/generator-overreact-odata/src/templates/hooks/use-entity.ejs +++ b/packages/generator-overreact-odata/src/templates/hooks/use-entity.ejs @@ -1,5 +1,12 @@ -import { useCallback } from 'react'; -import { useDataRefId, useFetch, useMutation } from '@microsoft/overreact'; +import { useCallback, useMemo } from 'react'; +import stringify from 'json-stable-stringify'; + +import { + useDataRefId, + useFetch, + useMutation, + useRefetch, +} from '@microsoft/overreact'; import { environmentLookupFn } from '<%= envLocation %>'; @@ -7,12 +14,28 @@ import { destroySpec } from '../../__specs/entity/destroy-spec'; import { fetchSpec, refetchSpec } from '../../__specs/entity/fetch-spec'; import { mutationSpec } from '../../__specs/entity/mutation-spec'; -export function <%- hookName %>(specs, path, variables, config = {}) { - const dataRefId = useDataRefId(environmentLookupFn); +export function <%- hookName %>(variables, config = {}) { + const { dataLocator } = variables; + const dataRefId = useDataRefId(`entity_${stringify(dataLocator)}`, environmentLookupFn); - const [data, error] = useFetch(dataRefId, fetchSpec, variables, config); - const mutateFn = useMutation(dataRefId, mutationSpec, config); - const destroyFn = useMutation(dataRefId, destroySpec, config); + const defaultConfig = useMemo(() => ({ + fetch: config.fetch || {}, + refetch: config.refetch || {}, + mutation: config.mutation || {}, + destroy: config.destroy || {}, + }), [config]); + + const { + fetch: fetchConfig, + refetch: refetchConfig, + mutation: mutationConfig, + destroy: destroyConfig, + } = defaultConfig; + + const [data, error] = useFetch(dataRefId, fetchSpec, variables, fetchConfig); + const mutateFn = useMutation(dataRefId, mutationSpec, mutationConfig); + const destroyFn = useMutation(dataRefId, destroySpec, destroyConfig); + const refetchFn = useRefetch(dataRefId, refetchSpec, refetchConfig); const update = useCallback((newData, ...rest) => { mutateFn(variables, newData, ...rest); @@ -23,5 +46,19 @@ export function <%- hookName %>(specs, path, variables, config = {}) { destroyFn(variables, newData, ...rest); }, [destroyFn, variables]); - return [{ data, error }, { update, destroy }]; + const refetch = useCallback((parameter, ...rest) => { + refetchFn( + { + variables: { + ...dataLocator, + ...parameter.variables, + }, + payload: parameter.payload, + }, + refetchConfig, + ...rest + ); + }, [refetchFn, refetchConfig, dataLocator]); + + return [{ data, error }, { update, destroy, refetch }]; } diff --git a/packages/generator-overreact-odata/src/templates/hooks/use-func.ejs b/packages/generator-overreact-odata/src/templates/hooks/use-func.ejs index 3dcb63c..ebc8da6 100644 --- a/packages/generator-overreact-odata/src/templates/hooks/use-func.ejs +++ b/packages/generator-overreact-odata/src/templates/hooks/use-func.ejs @@ -1,4 +1,5 @@ import { useCallback, useMemo } from 'react'; +import stringify from 'json-stable-stringify'; import { useFetch, @@ -9,8 +10,9 @@ import { import { environmentLookupFn } from '<%= envLocation %>'; import { fetchSpec, refetchSpec } from '../../__specs/calls/func-spec'; -export function <%- hookName %>(dataLocator, config = {}) { - const dataRefId = useDataRefId(environmentLookupFn); +export function <%- hookName %>(variables, config = {}) { + const { dataLocator } = variables; + const dataRefId = useDataRefId(`call_${stringify(dataLocator)}`, environmentLookupFn); const defaultConfig = useMemo(() => ({ refetch: config.refetch || {}, @@ -23,12 +25,16 @@ export function <%- hookName %>(dataLocator, config = {}) { const func = useRefetch(dataRefId, refetchSpec, refetchConfig); const callFn = useCallback((param = {}, requestConfig, ...rest) => { - func({ - variables: { - ...dataLocator, - ...param.variables, + func( + { + variables: { + ...dataLocator, + ...param.variables, + }, }, - }, requestConfig, ...rest); + requestConfig, + ...rest + ); }, [dataLocator, func]); const [data, error] = fetch; diff --git a/packages/generator-overreact-odata/src/templates/root/package.json b/packages/generator-overreact-odata/src/templates/root/package.json index 496fad6..aa5138d 100644 --- a/packages/generator-overreact-odata/src/templates/root/package.json +++ b/packages/generator-overreact-odata/src/templates/root/package.json @@ -9,6 +9,7 @@ "@microsoft/overreact": "^0.1.0-alpha.9", "@microsoft/overreact-odata": "^0.1.0-alpha.9", "bluebird": "^3.7.2", + "json-stable-stringify": "^1.0.1", "query-string": "^7.0.1", "react": ">=16.8.0", "underscore": "^1.13.1" diff --git a/packages/generator-overreact-odata/src/templates/shared/decorators.js b/packages/generator-overreact-odata/src/templates/shared/decorators.js index 8d46560..e141e17 100644 --- a/packages/generator-overreact-odata/src/templates/shared/decorators.js +++ b/packages/generator-overreact-odata/src/templates/shared/decorators.js @@ -46,3 +46,12 @@ export function processorDecorator(fn) { return (response, request) => decorator(response, request, fn(response, request)); } + +export const sideEffects = { + fetch: null, + refetch: null, + mutation: null, + pagination: null, + add: null, + destroy: null, +};