Setup GraphQL Code Generator (#74)

* chore: add types of schema

* Ease codegen use on FE

* chore: ignore prettier in generated files

* lint: generated files

* feature: strongly type filter of query

* chore: ignore generated files in prettier

* chore: eslint ignore generated files

---------

Co-authored-by: Sammy Teillet <sammy.teillet@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Charles Bochet
2023-04-25 17:25:30 +02:00
committed by GitHub
parent a93c92c65c
commit ae7bad65ca
13 changed files with 13478 additions and 30 deletions

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
**/generated/*

View File

@ -17,7 +17,8 @@ module.exports = {
node: true, node: true,
jest: true, jest: true,
}, },
ignorePatterns: ['.eslintrc.js'],
ignorePatterns: ['.eslintrc.js', 'codegen.js', '**/generated/*'],
rules: { rules: {
'@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',

28
front/codegen.js Normal file
View File

@ -0,0 +1,28 @@
module.exports = {
schema: [
{
[process.env.HASURA_GRAPHQL_ENDPOINT]: {
headers: {
'x-hasura-admin-secret': process.env.HASURA_GRAPHQL_ADMIN_SECRET,
},
},
},
],
documents: ['./src/**/*.tsx', './src/**/*.ts'],
overwrite: true,
generates: {
'./src/generated/graphql.tsx': {
plugins: [
'typescript',
'typescript-operations',
'typescript-react-apollo',
],
config: {
skipTypename: false,
withHooks: true,
withHOC: false,
withComponent: false,
},
},
},
};

5279
front/graphql.schema.json Normal file

File diff suppressed because it is too large Load Diff

2732
front/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,8 @@
"storybook": "storybook dev -p 6006 -s public", "storybook": "storybook dev -p 6006 -s public",
"build-storybook": "storybook build -s public", "build-storybook": "storybook build -s public",
"coverage": "react-scripts test --coverage --watchAll", "coverage": "react-scripts test --coverage --watchAll",
"coverage-ci": "react-scripts test --coverage --watchAll=false" "coverage-ci": "react-scripts test --coverage --watchAll=false",
"graphql-generate": "REACT_APP_GRAPHQL_ADMIN_SECRET=$REACT_APP_GRAPHQL_ADMIN_SECRET graphql-codegen --config codegen.js"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
@ -80,6 +81,10 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "^3.3.1",
"@graphql-codegen/typescript": "^3.0.4",
"@graphql-codegen/typescript-operations": "^3.0.4",
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
"@storybook/addon-actions": "^7.0.2", "@storybook/addon-actions": "^7.0.2",
"@storybook/addon-essentials": "^7.0.2", "@storybook/addon-essentials": "^7.0.2",
"@storybook/addon-interactions": "^7.0.2", "@storybook/addon-interactions": "^7.0.2",

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@ import { peopleColumns, sortsAvailable } from './people-table';
import { mapPerson } from '../../interfaces/person.interface'; import { mapPerson } from '../../interfaces/person.interface';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { import {
OrderBy,
PeopleSelectedSortType, PeopleSelectedSortType,
defaultOrderBy,
reduceSortsToOrderBy, reduceSortsToOrderBy,
usePeopleQuery, usePeopleQuery,
} from '../../services/people'; } from '../../services/people';
@ -17,12 +17,6 @@ const StyledPeopleContainer = styled.div`
width: 100%; width: 100%;
`; `;
const defaultOrderBy: OrderBy[] = [
{
created_at: 'desc',
},
];
function People() { function People() {
const [, setSorts] = useState([] as Array<PeopleSelectedSortType>); const [, setSorts] = useState([] as Array<PeopleSelectedSortType>);
const [orderBy, setOrderBy] = useState(defaultOrderBy); const [orderBy, setOrderBy] = useState(defaultOrderBy);

View File

@ -1,36 +1,32 @@
import { QueryResult, gql, useQuery } from '@apollo/client'; import { QueryResult, gql, useQuery } from '@apollo/client';
import { GraphqlQueryPerson } from '../../interfaces/person.interface'; import { GraphqlQueryPerson } from '../../interfaces/person.interface';
import { SelectedSortType } from '../../components/table/table-header/SortAndFilterBar'; import { SelectedSortType } from '../../components/table/table-header/SortAndFilterBar';
import { Order_By, People_Order_By } from '../../generated/graphql';
export type OrderByFields = export type OrderByFields = keyof People_Order_By | 'fullname' | 'company_name';
| keyof GraphqlQueryPerson
| 'fullname'
| 'company_name';
export type OrderBy = Partial<{
[key in keyof GraphqlQueryPerson]:
| 'asc'
| 'desc'
| { [key in string]: 'asc' | 'desc' };
}>;
export type PeopleSelectedSortType = SelectedSortType<OrderByFields>; export type PeopleSelectedSortType = SelectedSortType<OrderByFields>;
const mapOrder = (order: 'asc' | 'desc'): Order_By => {
return order === 'asc' ? Order_By.Asc : Order_By.Desc;
};
export const reduceSortsToOrderBy = ( export const reduceSortsToOrderBy = (
sorts: Array<PeopleSelectedSortType>, sorts: Array<PeopleSelectedSortType>,
): OrderBy[] => { ): People_Order_By[] => {
const mappedSorts = sorts.reduce((acc, sort) => { const mappedSorts = sorts.reduce((acc, sort) => {
const id = sort.id; const id = sort.id;
const order = mapOrder(sort.order);
if (id === 'fullname') { if (id === 'fullname') {
acc['firstname'] = sort.order; acc['firstname'] = order;
acc['lastname'] = sort.order; acc['lastname'] = order;
} else if (id === 'company_name') { } else if (id === 'company_name') {
acc['company'] = { company_name: sort.order }; acc['company'] = { company_name: order };
} else { } else {
acc[id] = sort.order; acc[id] = order;
} }
return acc; return acc;
}, {} as OrderBy); }, {} as People_Order_By);
return [mappedSorts]; return [mappedSorts];
}; };
@ -54,9 +50,15 @@ export const GET_PEOPLE = gql`
`; `;
export function usePeopleQuery( export function usePeopleQuery(
orderBy: OrderBy[], orderBy: People_Order_By[],
): QueryResult<{ people: GraphqlQueryPerson[] }> { ): QueryResult<{ people: GraphqlQueryPerson[] }> {
return useQuery<{ people: GraphqlQueryPerson[] }>(GET_PEOPLE, { return useQuery<{ people: GraphqlQueryPerson[] }>(GET_PEOPLE, {
variables: { orderBy }, variables: { orderBy },
}); });
} }
export const defaultOrderBy: People_Order_By[] = [
{
created_at: Order_By.Desc,
},
];

View File

@ -12,6 +12,7 @@ HASURA_AUTH_GRAPHQL_URL: http://twenty-hasura:8080/v1/graphql
FRONT_REACT_APP_API_URL=http://localhost:8080 FRONT_REACT_APP_API_URL=http://localhost:8080
FRONT_REACT_APP_AUTH_URL=http://localhost:4000 FRONT_REACT_APP_AUTH_URL=http://localhost:4000
FRONT_HASURA_GRAPHQL_ENDPOINT=http://twenty-hasura:8080/v1/graphql
SERVER_HASURA_EVENT_HANDLER_SECRET_HEADER: secret SERVER_HASURA_EVENT_HANDLER_SECRET_HEADER: secret
SERVER_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/default SERVER_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/default

View File

@ -27,6 +27,9 @@ front-coverage: ##
front-storybook: ## front-storybook: ##
@docker-compose exec twenty-front sh -c "npm run storybook" @docker-compose exec twenty-front sh -c "npm run storybook"
front-graphql-generate: ##
@docker-compose exec twenty-front sh -c "npm run graphql-generate"
## Hasura ## Hasura
hasura-logs: ## hasura-logs: ##

View File

@ -8,8 +8,10 @@ services:
- "3001:3001" - "3001:3001"
- "6006:6006" - "6006:6006"
environment: environment:
- REACT_APP_API_URL=${FRONT_REACT_APP_API_URL} REACT_APP_API_URL: ${FRONT_REACT_APP_API_URL}
- REACT_APP_AUTH_URL=${FRONT_REACT_APP_AUTH_URL} REACT_APP_AUTH_URL: ${FRONT_REACT_APP_AUTH_URL}
HASURA_GRAPHQL_ENDPOINT: ${FRONT_HASURA_GRAPHQL_ENDPOINT}
HASURA_GRAPHQL_ADMIN_SECRET: ${HASURA_GRAPHQL_ADMIN_SECRET}
volumes: volumes:
- ../../front:/app/front - ../../front:/app/front
- twenty_node_modules_front:/app/front/node_modules - twenty_node_modules_front:/app/front/node_modules

View File

@ -2,7 +2,10 @@ FROM node:18.16.0-alpine as front
RUN apk update && apk upgrade && \ RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh && \ apk add --no-cache bash git openssh && \
apk add libc6-compat apk add libc6-compat \
apk add python3 \
apk add make \
apk add g++
WORKDIR /app/front WORKDIR /app/front