ngrx-graphql
A helper library for convertion of selectors made by ngrx-entity-relationship to a GraphQL query.
Supports
- Angular 6 and
ngrx/store@6
- Angular 7 and
ngrx/store@7
- Angular 8 and
ngrx/store@8
- Angular 9 and
ngrx/store@9
- Angular 10 and
ngrx/store@10
Installation
To install the package execute the next command npm install --save ngrx-graphql
.
The next step is to add needed augments for types. It will help with integration of ngrx-graphql
into ngrx-entity-relationship
.
For that add the next line in src/main.ts
.
import 'ngrx-graphql/augments';
Usage
Note: you should be familiar with ngrx-entity-relationship.
Imagine we have a selector:
export const selectUser = rootEntity(
selectUserState,
relatedEntity(
selectCompanyState,
'companyId',
'company',
relatedEntity(
selectAddressState,
'addressId',
'address',
),
),
);
And we want to get a GraphQL query like that:
{
user(id: "1") {
id
firstName
lastName
companyId
company {
id
name
addressId
address {
id
street
city
country
}
}
}
}
The only issue is that the selector doesn't know fields of the entities.
To solve this we need to define them manually as meta of every selector.
Don't forget to include fields for the id detection.
export const selectUser = rootEntity(
selectUserState,
{
gqlFields: ['id', 'firstName', 'lastName'],
},
relatedEntity(
selectCompanyState,
'companyId',
'company',
{
gqlFields: ['id', 'name'],
},
relatedEntity(
selectAddressState,
'addressId',
'address',
{
gqlFields: ['id', 'street', 'city', 'country'],
},
),
),
);
Profit, now we can use this selector to generate a GraphQL query via toGraphQL
helper function.
const allUsers = toGraphQL('users', selectUser);
const userId1 = toGraphQL('user(id: "1")', selectUser);
const userId2 = toGraphQL('user', {id: '2'}, selectUser);
The result will be
{
users {
id
firstName
lastName
companyId
company {
id
name
addressId
address {
id
street
city
country
}
}
}
}
{
user(id: "1") {
id
}
}
{
user(id: "2") {
id
}
}
If we want we can combine them together to a single query
const combined = toGraphQL(
toGraphQL('all:users', selectUser),
toGraphQL('u1:user(id: "1")', selectUser),
toGraphQL('u2:user', {id: '2'}, selectUser),
);
will generate
{
all:users {
id
}
u1:user(id: "1") {
id
}
u2:user(id: "2") {
id
}
}
Usage with HttpClient
An example of a ngrx effect and HttpClient
.
@Injectable()
export class EntityEffects {
@Effect()
public readonly dataGraph$ = this.actions$.pipe(
ofType(UserActionTypes.LOAD),
switchMap(
() => this.http.get<{data: {users: Array<User>}}>('http://localhost:3000/graphql', {
params: {
query: toGraphQL('users', selectUser),
}
}).pipe(
map(response => reduceGraph({
data: response.data.users,
selector: selectUser,
})),
),
),
);
constructor(
protected readonly actions$: Actions,
protected readonly http: HttpClient,
) {
}
}
Usage with Apollo Service
An example of a ngrx effect and Apollo
service.
@Injectable()
export class EntityEffects {
@Effect()
public readonly dataGraph$ = this.actions$.pipe(
ofType(UserActionTypes.LOAD),
switchMap(
() => this.apollo.query<{users: Array<User>}>({
query: gql(toGraphQL('users', selectUser)),
}).pipe(
map(response => reduceGraph({
data: response.data.users,
selector: selectUser,
})),
),
),
);
constructor(
protected readonly actions$: Actions,
protected readonly apollo: Apollo,
) {
}
}
Subscriptions
Usage of toGraphQL
isn't enough to generate a subscription query.
Here toSubscription
solves the issue.
For example
const query = toSubscription(toGraphQL('users', action.selector));
will generate
subscription {
users {
id
}
}
With Apollo
service it can be used like thath
apollo.subscribe({
query: gql(toSubscription(toGraphQL('users', action.selector))),
}).subscribe(update => {
});
Mutations
Usage of toGraphQL
isn't enough to generate a mutation query.
Here toMutation
solves the issue.
For example
const query = toMutation(toGraphQL('updateUser', {
id: 'id1',
data: {
firstName: 'updatedFirstName',
lastName: 'lastFirstName',
}
}, action.selector));
will generate
mutation {
updateUser(
id:"id1",
data: {
firstName:"updatedFirstName",
lastName:"lastFirstName"
}
) {
id
}
}
With Apollo
service it can be used like that
apollo.mutate({
mutation: gql(toMutation(toGraphQL('updateUser', {
id: 'id1',
data: {
firstName: 'updatedFirstName',
lastName: 'lastFirstName',
}
}, action.selector))),
}).subscribe(update => {
});
Query
Usage of toGraphQL
isn't enough to generate a query with variables.
Here toQuery
solves the issue, but about that in the Variables section.
Variables
All toQuery
, toSubscription
and toMutation
support variables.
They can be passed as the first parameter.
toGraphQL
supports $
to define variables instead of values.
apollo.mutate({
mutation: gql(toMutation({
data: 'UpdateUserInput!',
}, toGraphQL('updateUser', {
id: 'id1',
$: {
data: '$data',
},
}, action.selector))),
variables: {
data: {
firstName: 'updatedFirstName',
lastName: 'lastFirstName',
},
},
}).subscribe(update => {
});
will generate
mutation($data: UpdateUserInput!) {
updateUser(
id:"id1",
data: $data
) {
id
}
}