0.0.5 • Published 2 years ago

tpxrx v0.0.5

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

tpxrx

tpxrx is a collection of nx workspace generators for a specific ngrx store pattern. tpxrx combines two goals to improve ngrx stores.

1) Split store contents into smaller parts to make store more clear. 2) Standardize asset properties to access the state of http requests.

Installation

Install @tpx1/tpxrx via npm:

npm i @tpx1/tpxrx@latest

##Store concepts tpxrx combines two goals to improve ngrx stores.

1) Split store contents into smaller parts to make store more clear. 2) Standardize asset properties to access the state of http requests.

Split store

In large projects there might be many store actions, properties, etc. Dozens of actions, effects and selectors can become confusing. tpxrx provides a concept to divide contents into domains.

The domain concept will be explained by an example:

There is a store containing actions to set one or many companies and users and selectors for each property. The store will be split into domains, so that each domain contains action, effect, facade, reducer and selector file. How many and which items you want to split is your own decision as long as you don't split actions using the same state property. Often it makes sense to use each domain model type in a domain. In this example we create a company domain and a user domain.

Domains will be aggregated by base reducer, base selectors and base facade. They are explained at the end of this chapter.

File structure

The store contains the following file structure:

| +state
|--- company
|---|--- company.actions.ts
|---|--- company.actions.resets.ts
|---|--- company.effects.ts
|---|--- company.facade.ts
|---|--- company.facade.resets.ts
|---|--- company.reducer.ts
|---|--- company.reducer.resets.ts
|---|--- company.selectors.ts
|--- user
|---|--- user.actions.ts
|---|--- user.actions.resets.ts
|---|--- user.effects.ts
|---|--- user.facade.ts
|---|--- user.facade.resets.ts
|---|--- user.reducer.ts
|---|--- user.reducer.resets.ts
|---|--- user.selectors.ts
|--- example.facade.ts
|--- example.reducer.ts
|--- example.selectors.ts
| example.module.ts

Run

nx g @tpx1/tpxrx:lib example --domains=company,user --crud

inside your nx workspace to generate this file structure and have a look at each file content.

actions

*.actions.ts contains all actions of the domain in the same format you already know.

*.actions.resets.ts contains all actions to reset properties of the store. Read more about reset actions in chapter Generator commands. Use comments for each action group.

effects

*.effects.ts contains an injectable class, including all effects of the domain in the same format you already know.

reducer

*.reducer.ts contains a state definition, an initialState definition and a function to get ReducerTypes.

*.reducer.resets.ts contains a function to get ReducerTypes of resets actions. Use comments for each action group.

selectors

*.selectors.ts contains all selectors of the domain in the same format you already know.

facade

*.facade.ts contains Observable properties of selectors and action functions.

*.facade.resets.ts contain resets action functions.

base reducer

The base reducer (example.reducer.ts in this example) aggregates all domain reducers. The state interface extends all domain state interfaces. The initialState Object aggregates all domain initialState Objects. The reducer function returns an array of all domain Reducer Types.

base selectors

The base selectors file defines a feature selector used by all domain selectors.

base facade

The base facade injects all domain facades to provide functions to base facade usage. This is the service used in your components to interact with the store. It's the only store file visibile for other libs. So it's important to export this file in the index.ts

Use ExampleFacade this way:

this.exampleFacade.userFacade.user$.pipe(
    filter(u => !!u)
).subscribe((user) => {
    console.log(user);
});
this.exampleFacade.userFacade.loadUserById('123');

Standardization

In most projects store asset properties are defined in confusing ways. Sometimes there is a loading property, sometimes there is a loadingFinished or a loadingStarted. Each developer chooses an own naming and boolean logic. This becomes confusing and might produce errors.

tpxrx improves assets behaviour by standardized property names. Each action group for http requests (consisting of a default action, success action and failure action) defines a pending property, success property and failure property which indicates if the request is actually pending (waiting for response), successfully responded or responded with an error. The action loadUserById implicates the actions loadUserByIdSuccess and loadUserByIdFailure. The state defines a property user which is set when the http request is responded successfully. Additional the state defines three properties:

loadUserByIdPending?: boolean;
loadUserByIdSuccess?: boolean;
loadUserByIdError?: Error;

The action listeners for the loadUserById actions underly strict rules for value assignment:

/*
 * loadUserById
 */
on(UserActions.loadUserById, (state) => ({
  ...state,
  user: null,
  loadUserByIdPending: true,
  loadUserByIdSuccess: false,
  loadUserByIdError: null,
})),
on(UserActions.loadUserByIdSuccess, (state, {user}) => ({
  ...state,
  user: user,
  loadUserByIdPending: false,
  loadUserByIdSuccess: true,
})),
on(UserActions.loadUserByIdFailure, (state, {error}) => ({
  ...state,
  loadUserByIdPending: false,
  loadUserByIdError: error,
})),

In default action the data property user might be resetted. It's not required because update and create actions might not want to lose data. Pending is set to true, success is set to false and error is set to null. These assignments are required and have to be set in each default action.

In success action the data property is set to response data. Other properties might also be set, like add user to users array when created. Pending is set to false, success is set to true.

In error action there is no data property set. Pending is set to false, error is set to error response.

reset properties

For each property of the state there should be a reset action to set the property to null. Additionally add a resetAssets action to reset all action properties of a domain in one.

Generator commands

tpxrx provides a collection of nx generator commands to generate a tpxrx store or parts of it.

Some commands are available with optional flag --crud. If this flag is set actions are generated as crud actions: load all, load by id, create, update, delete, reset.

lib

nx g @tpx1/tpxrx:lib example/domain
nx g @tpx1/tpxrx:lib example/domain --domains=domain1,domain2
nx g @tpx1/tpxrx:lib example/domain --domains=domain1,domain2 --crud

domain

nx g @tpx1/tpxrx:domain domain1 --project=example/domain
nx g @tpx1/tpxrx:domain domain1 --project=example/domain --crud

action

nx g @tpx1/tpxrx:action loadPropertyById --project=example/domain --domain=domain1
nx g @tpx1/tpxrx:action property --project=example/domain --domain=domain1 --crud

property

nx g @tpx1/tpxrx:property propertyA --project=example/domain --domain=domain1
nx g @tpx1/tpxrx:property propertyA --project=example/domain --domain=domain1 --array