diff --git a/src/actions.ts b/src/actions.ts index 3825de1..8ad79d1 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -86,42 +86,66 @@ export class ApiApplyFailAction extends NgrxJsonApiAction { export class ApiPostInitAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_POST_INIT; - constructor(public payload: Resource, public zoneId: string) { + constructor( + public payload: Resource, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiPostSuccessAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_POST_SUCCESS; - constructor(public payload: Payload, public zoneId: string) { + constructor( + public payload: Payload, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiPostFailAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_POST_FAIL; - constructor(public payload: Payload, public zoneId: string) { + constructor( + public payload: Payload, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiDeleteInitAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_DELETE_INIT; - constructor(public payload: ResourceIdentifier, public zoneId: string) { + constructor( + public payload: ResourceIdentifier, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiDeleteSuccessAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_DELETE_SUCCESS; - constructor(public payload: Payload, public zoneId: string) { + constructor( + public payload: Payload, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiDeleteFailAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_DELETE_FAIL; - constructor(public payload: Payload, public zoneId: string) { + constructor( + public payload: Payload, + public queryId: string, + public zoneId: string + ) { super(); } } @@ -156,21 +180,33 @@ export class ApiRollbackAction extends NgrxJsonApiAction { export class ApiPatchInitAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_PATCH_INIT; - constructor(public payload: Resource, public zoneId: string) { + constructor( + public payload: Resource, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiPatchSuccessAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_PATCH_SUCCESS; - constructor(public payload: Payload, public zoneId: string) { + constructor( + public payload: Payload, + public queryId: string, + public zoneId: string + ) { super(); } } export class ApiPatchFailAction extends NgrxJsonApiAction { readonly type = NgrxJsonApiActionTypes.API_PATCH_FAIL; - constructor(public payload: Payload, public zoneId: string) { + constructor( + public payload: Payload, + public queryId: string, + public zoneId: string + ) { super(); } } diff --git a/src/effects.ts b/src/effects.ts index 787f607..63dbd77 100644 --- a/src/effects.ts +++ b/src/effects.ts @@ -94,6 +94,7 @@ export class NgrxJsonApiEffects implements OnDestroy { jsonApiData: response.body, query: payload.query, }, + action.queryId, action.zoneId ) ), @@ -101,6 +102,7 @@ export class NgrxJsonApiEffects implements OnDestroy { of( new ApiPostFailAction( this.toErrorPayload(payload.query, error), + action.queryId, action.zoneId ) ) @@ -122,6 +124,7 @@ export class NgrxJsonApiEffects implements OnDestroy { jsonApiData: response.body, query: payload.query, }, + action.queryId, action.zoneId ) ), @@ -129,6 +132,7 @@ export class NgrxJsonApiEffects implements OnDestroy { of( new ApiPatchFailAction( this.toErrorPayload(payload.query, error), + action.queryId, action.zoneId ) ) @@ -262,6 +266,7 @@ export class NgrxJsonApiEffects implements OnDestroy { jsonApiData: data, query: payload.query, }, + action.queryId, action.zoneId ) ), @@ -269,6 +274,7 @@ export class NgrxJsonApiEffects implements OnDestroy { of( new ApiDeleteFailAction( this.toErrorPayload(payload.query, error), + action.queryId, action.zoneId ) ) @@ -340,6 +346,7 @@ export class NgrxJsonApiEffects implements OnDestroy { jsonApiData: response.body, query: payload.query, }, + null, zoneId ) ), @@ -347,6 +354,7 @@ export class NgrxJsonApiEffects implements OnDestroy { of( new ApiPostFailAction( this.toErrorPayload(payload.query, error), + null, zoneId ) ) @@ -364,6 +372,7 @@ export class NgrxJsonApiEffects implements OnDestroy { jsonApiData: response.body, query: payload.query, }, + null, zoneId ) ), @@ -371,6 +380,7 @@ export class NgrxJsonApiEffects implements OnDestroy { of( new ApiPatchFailAction( this.toErrorPayload(payload.query, error), + null, zoneId ) ) @@ -388,6 +398,7 @@ export class NgrxJsonApiEffects implements OnDestroy { jsonApiData: response.body, query: payload.query, }, + null, zoneId ) ), @@ -395,6 +406,7 @@ export class NgrxJsonApiEffects implements OnDestroy { of( new ApiDeleteFailAction( this.toErrorPayload(payload.query, error), + null, zoneId ) ) diff --git a/src/reducers.ts b/src/reducers.ts index e54b688..8bf4fde 100644 --- a/src/reducers.ts +++ b/src/reducers.ts @@ -86,9 +86,11 @@ export function NgrxJsonApiZoneReducer( false, true ); + let query = { queryId: action.queryId }; newZone = { ...zone, data: updatedData, + queries: updateQueryParams(zone.queries, query), isCreating: zone.isCreating + 1, }; return newZone; @@ -109,17 +111,21 @@ export function NgrxJsonApiZoneReducer( false, false ); + let query = { queryId: action.queryId }; newZone = { ...zone, data: updatedData, + queries: updateQueryParams(zone.queries, query), isUpdating: zone.isUpdating + 1, }; return newZone; } case NgrxJsonApiActionTypes.API_DELETE_INIT: { + let query = { queryId: action.queryId }; newZone = { ...zone, data: updateResourceState(zone.data, action.payload, 'DELETED'), + queries: updateQueryParams(zone.queries, query), isDeleting: zone.isDeleting + 1, }; return newZone; @@ -128,6 +134,11 @@ export function NgrxJsonApiZoneReducer( newZone = { ...zone, data: updateStoreDataFromPayload(zone.data, action.payload.jsonApiData), + queries: updateQueryResults( + zone.queries, + action.queryId, + action.payload.jsonApiData + ), isCreating: zone.isCreating - 1, }; return newZone; @@ -149,6 +160,11 @@ export function NgrxJsonApiZoneReducer( newZone = { ...zone, data: updateStoreDataFromPayload(zone.data, action.payload.jsonApiData), + queries: updateQueryResults( + zone.queries, + action.queryId, + action.payload.jsonApiData + ), isUpdating: zone.isUpdating - 1, }; return newZone; @@ -157,7 +173,7 @@ export function NgrxJsonApiZoneReducer( newZone = { ...zone, data: deleteStoreResources(zone.data, action.payload.query), - queries: updateQueriesForDeletedResource(zone.queries, { + queries: updateQueriesForDeletedResource(zone.queries, action.queryId, { id: action.payload.query.id, type: action.payload.query.type, }), @@ -181,6 +197,11 @@ export function NgrxJsonApiZoneReducer( action.payload.query, action.payload.jsonApiData ), + queries: updateQueryErrors( + zone.queries, + action.queryId, + action.payload.jsonApiData + ), isCreating: zone.isCreating - 1, }; return newZone; @@ -205,6 +226,11 @@ export function NgrxJsonApiZoneReducer( action.payload.query, action.payload.jsonApiData ), + queries: updateQueryErrors( + zone.queries, + action.queryId, + action.payload.jsonApiData + ), isUpdating: zone.isUpdating - 1, }; return newZone; @@ -217,6 +243,11 @@ export function NgrxJsonApiZoneReducer( action.payload.query, action.payload.jsonApiData ), + queries: updateQueryErrors( + zone.queries, + action.queryId, + action.payload.jsonApiData + ), isDeleting: zone.isDeleting - 1, }; return newZone; diff --git a/src/services.ts b/src/services.ts index a58c251..4b1bff6 100644 --- a/src/services.ts +++ b/src/services.ts @@ -193,15 +193,24 @@ export class NgrxJsonApiZoneService { * * @param resource */ - public patchResource(options: PatchResourceOptions) { + public patchResource(options: PatchResourceOptions): Observable { let resource = options.resource; let toRemote = _.isUndefined(options.toRemote) ? false : options.toRemote; + const queryId = uuid(); if (toRemote) { - this.store.dispatch(new ApiPatchInitAction(resource, this.zoneId)); + this.store.dispatch( + new ApiPatchInitAction(resource, queryId, this.zoneId) + ); } else { this.store.dispatch(new PatchStoreResourceAction(resource, this.zoneId)); } + return this.store + .let(selectNgrxJsonApiZone(this.zoneId)) + .let(selectOneQueryResult(queryId)) + .finally(() => { + this.removeQuery(queryId); + }); } /** @@ -222,15 +231,24 @@ export class NgrxJsonApiZoneService { * * @param resource */ - public postResource(options: PostResourceOptions) { + public postResource(options: PostResourceOptions): Observable { let resource = options.resource; let toRemote = _.isUndefined(options.toRemote) ? false : options.toRemote; + const queryId = uuid(); if (toRemote) { - this.store.dispatch(new ApiPostInitAction(resource, this.zoneId)); + this.store.dispatch( + new ApiPostInitAction(resource, queryId, this.zoneId) + ); } else { this.store.dispatch(new PostStoreResourceAction(resource, this.zoneId)); } + return this.store + .let(selectNgrxJsonApiZone(this.zoneId)) + .let(selectOneQueryResult(queryId)) + .finally(() => { + this.removeQuery(queryId); + }); } /** @@ -238,17 +256,28 @@ export class NgrxJsonApiZoneService { * * @param resourceId */ - public deleteResource(options: DeleteResourceOptions) { + public deleteResource( + options: DeleteResourceOptions + ): Observable { let resourceId = options.resourceId; let toRemote = _.isUndefined(options.toRemote) ? false : options.toRemote; + const queryId = uuid(); if (toRemote) { - this.store.dispatch(new ApiDeleteInitAction(resourceId, this.zoneId)); + this.store.dispatch( + new ApiDeleteInitAction(resourceId, queryId, this.zoneId) + ); } else { this.store.dispatch( new DeleteStoreResourceAction(resourceId, this.zoneId) ); } + return this.store + .let(selectNgrxJsonApiZone(this.zoneId)) + .let(selectOneQueryResult(queryId)) + .finally(() => { + this.removeQuery(queryId); + }); } /** diff --git a/src/utils.ts b/src/utils.ts index 35c5d79..b200c94 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -421,9 +421,15 @@ export const updateStoreResource = ( export const updateQueriesForDeletedResource = ( state: NgrxJsonApiStoreQueries, + queryId: string, deletedId: ResourceIdentifier ): NgrxJsonApiStoreQueries => { - let newState: NgrxJsonApiStoreQueries = state; + const document = { data: deletedId }; + let newState: NgrxJsonApiStoreQueries = updateQueryResults( + state, + queryId, + document + ); for (let queryId in state) { if (state.hasOwnProperty(queryId)) { let queryState = state[queryId]; @@ -446,7 +452,8 @@ export const updateResourceErrorsForQuery = ( query: Query, document: Document ): NgrxJsonApiStoreData => { - if (!query.type || !query.id || document.data instanceof Array) { + // id can be nullify when queryType is POST + if (!query.type || query.id === undefined || document.data instanceof Array) { throw new Error('invalid parameters'); } return updateResourceErrors(