diff --git a/README.md b/README.md index eabbfcda6..899671cb6 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Make sure to have the latest Docker and Docker-compose versions installed on you ### Step 2: docker build Build docker containers. -The whole setup/development experience is happening in `infra/dev` folder. Make sure to be in this folder: +The whole setup experience is happening in `infra/dev` folder. Make sure to be in this folder: ``` cd infra/dev ``` @@ -49,38 +49,60 @@ Browse Hasura console on http://localhost:8080, go to settings and import metada ## Developping on Frontend +The whole development experience is happening in `infra/dev` folder. +``` +cd infra/dev +``` + The development FE server is running on docker up and is exposing the `twenty-front` on port http://localhost:3001. As you modify the `/front` folder on your computer, this folder is synced with your `twenty-front` container and the frontend application is automatically refreshed. ### Develop Recommended: as you modify frontend code, here is how to access `twenty-front` server logs in order to debug / watch typescript issues: ``` -docker-compose up -docker-compose logs twenty-front -f +make up +make logs container=twenty-front ``` ### Open a shell into the container ``` -docker-compose exec twenty-front sh +make front-sh ``` ### Tests #### Unit tests: ``` -docker-compose exec twenty-front sh -c "npm run test" +make front-test # coverage -docker-compose exec twenty-front sh -c "npm run coverage" +make front-coverage ``` #### Storybook: ``` -docker-compose exec twenty-front sh -c "npm run storybook" +make front-storybook ``` ## Developping on API -The API is a Hasura instance which is a no-code container. To modify API behavior, you'll need to connect to Hasura console on: http://localhost:8080/console +The whole development experience is happening in `infra/dev` folder. +``` +cd infra/dev +``` + +The API is a Hasura instance which is a no-code container. +To modify API behavior, you'll need to connect to run Hasura console through the CLI +``` +make api-console +``` + +Once your local changes in the console are finished you can export them into the filesystem (in order to version them, and deploy them to other environments), depending on your needs: + +``` +make api-make-migration name=my_migration_name +make api-make-metadata +make api-make-seeds +``` ## Developping on server diff --git a/api/config.yaml b/api/config.yaml new file mode 100644 index 000000000..725c8005e --- /dev/null +++ b/api/config.yaml @@ -0,0 +1,6 @@ +version: 3 +endpoint: http://localhost:8080 +metadata_directory: metadata +actions: + kind: synchronous + handler_webhook_baseurl: http://localhost:3000 diff --git a/api/metadata/actions.graphql b/api/metadata/actions.graphql new file mode 100644 index 000000000..e69de29bb diff --git a/api/metadata/actions.yaml b/api/metadata/actions.yaml new file mode 100644 index 000000000..1edb4c2ff --- /dev/null +++ b/api/metadata/actions.yaml @@ -0,0 +1,6 @@ +actions: [] +custom_types: + enums: [] + input_objects: [] + objects: [] + scalars: [] diff --git a/api/metadata/allow_list.yaml b/api/metadata/allow_list.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/api/metadata/allow_list.yaml @@ -0,0 +1 @@ +[] diff --git a/api/metadata/api_limits.yaml b/api/metadata/api_limits.yaml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/api/metadata/api_limits.yaml @@ -0,0 +1 @@ +{} diff --git a/api/metadata/backend_configs.yaml b/api/metadata/backend_configs.yaml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/api/metadata/backend_configs.yaml @@ -0,0 +1 @@ +{} diff --git a/api/metadata/cron_triggers.yaml b/api/metadata/cron_triggers.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/api/metadata/cron_triggers.yaml @@ -0,0 +1 @@ +[] diff --git a/api/metadata/databases/databases.yaml b/api/metadata/databases/databases.yaml new file mode 100644 index 000000000..52ba870eb --- /dev/null +++ b/api/metadata/databases/databases.yaml @@ -0,0 +1,9 @@ +- name: twenty + kind: postgres + configuration: + connection_info: + database_url: + from_env: HASURA_GRAPHQL_PG_DATABASE_URL + isolation_level: read-committed + use_prepared_statements: false + tables: "!include twenty/tables/tables.yaml" diff --git a/api/metadata/databases/twenty/tables/public_tenants.yaml b/api/metadata/databases/twenty/tables/public_tenants.yaml new file mode 100644 index 000000000..a9c8db72d --- /dev/null +++ b/api/metadata/databases/twenty/tables/public_tenants.yaml @@ -0,0 +1,23 @@ +table: + name: tenants + schema: public +array_relationships: + - name: users + using: + foreign_key_constraint_on: + column: tenant_id + table: + name: users + schema: public +select_permissions: + - role: user + permission: + columns: + - id + - name + - uuid + - email_domain + filter: + users: + email: + _eq: X-Hasura-User-Email diff --git a/api/metadata/databases/twenty/tables/public_users.yaml b/api/metadata/databases/twenty/tables/public_users.yaml new file mode 100644 index 000000000..fb601da78 --- /dev/null +++ b/api/metadata/databases/twenty/tables/public_users.yaml @@ -0,0 +1,23 @@ +table: + name: users + schema: public +object_relationships: + - name: tenant + using: + foreign_key_constraint_on: tenant_id +select_permissions: + - role: user + permission: + columns: + - id + - tenant_id + - email + - first_name + - last_name + - created_at + - updated_at + filter: + tenant: + users: + email: + _eq: X-Hasura-User-Email diff --git a/api/metadata/databases/twenty/tables/tables.yaml b/api/metadata/databases/twenty/tables/tables.yaml new file mode 100644 index 000000000..52f78d1d7 --- /dev/null +++ b/api/metadata/databases/twenty/tables/tables.yaml @@ -0,0 +1,2 @@ +- "!include public_tenants.yaml" +- "!include public_users.yaml" diff --git a/api/metadata/graphql_schema_introspection.yaml b/api/metadata/graphql_schema_introspection.yaml new file mode 100644 index 000000000..61a4dcac2 --- /dev/null +++ b/api/metadata/graphql_schema_introspection.yaml @@ -0,0 +1 @@ +disabled_for_roles: [] diff --git a/api/metadata/inherited_roles.yaml b/api/metadata/inherited_roles.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/api/metadata/inherited_roles.yaml @@ -0,0 +1 @@ +[] diff --git a/api/metadata/metrics_config.yaml b/api/metadata/metrics_config.yaml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/api/metadata/metrics_config.yaml @@ -0,0 +1 @@ +{} diff --git a/api/metadata/network.yaml b/api/metadata/network.yaml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/api/metadata/network.yaml @@ -0,0 +1 @@ +{} diff --git a/api/metadata/opentelemetry.yaml b/api/metadata/opentelemetry.yaml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/api/metadata/opentelemetry.yaml @@ -0,0 +1 @@ +{} diff --git a/api/metadata/query_collections.yaml b/api/metadata/query_collections.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/api/metadata/query_collections.yaml @@ -0,0 +1 @@ +[] diff --git a/api/metadata/remote_schemas.yaml b/api/metadata/remote_schemas.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/api/metadata/remote_schemas.yaml @@ -0,0 +1 @@ +[] diff --git a/api/metadata/rest_endpoints.yaml b/api/metadata/rest_endpoints.yaml new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/api/metadata/rest_endpoints.yaml @@ -0,0 +1 @@ +[] diff --git a/api/metadata/version.yaml b/api/metadata/version.yaml new file mode 100644 index 000000000..0a70affa4 --- /dev/null +++ b/api/metadata/version.yaml @@ -0,0 +1 @@ +version: 3 diff --git a/api/migrations/twenty/1675027570991_init/up.sql b/api/migrations/twenty/1675027570991_init/up.sql new file mode 100644 index 000000000..3744ba2e6 --- /dev/null +++ b/api/migrations/twenty/1675027570991_init/up.sql @@ -0,0 +1,57 @@ +SET check_function_bodies = false; +CREATE FUNCTION public.set_current_timestamp_updated_at() RETURNS trigger + LANGUAGE plpgsql + AS $$ +DECLARE + _new record; +BEGIN + _new := NEW; + _new."updated_at" = NOW(); + RETURN _new; +END; +$$; +CREATE TABLE public.tenants ( + id integer NOT NULL, + name text NOT NULL, + uuid uuid DEFAULT gen_random_uuid() NOT NULL, + email_domain text NOT NULL +); +CREATE SEQUENCE public.tenants_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; +ALTER SEQUENCE public.tenants_id_seq OWNED BY public.tenants.id; +CREATE TABLE public.users ( + id integer NOT NULL, + email text NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone DEFAULT now() NOT NULL, + first_name text NOT NULL, + last_name text NOT NULL, + tenant_id integer NOT NULL +); +CREATE SEQUENCE public.users_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; +ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; +ALTER TABLE ONLY public.tenants ALTER COLUMN id SET DEFAULT nextval('public.tenants_id_seq'::regclass); +ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); +ALTER TABLE ONLY public.tenants + ADD CONSTRAINT tenants_email_domain_key UNIQUE (email_domain); +ALTER TABLE ONLY public.tenants + ADD CONSTRAINT tenants_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.tenants + ADD CONSTRAINT tenants_uuid_key UNIQUE (uuid); +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); +CREATE TRIGGER set_public_users_updated_at BEFORE UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION public.set_current_timestamp_updated_at(); +COMMENT ON TRIGGER set_public_users_updated_at ON public.users IS 'trigger to set value of column "updated_at" to current timestamp on row update'; +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON UPDATE RESTRICT ON DELETE RESTRICT; diff --git a/api/seeds/twenty/1675183813451_seed.sql b/api/seeds/twenty/1675183813451_seed.sql new file mode 100644 index 000000000..e69de29bb diff --git a/api/seeds/twenty/1675183931547_seed.sql b/api/seeds/twenty/1675183931547_seed.sql new file mode 100644 index 000000000..4ee15aa16 --- /dev/null +++ b/api/seeds/twenty/1675183931547_seed.sql @@ -0,0 +1,6 @@ +SET check_function_bodies = false; +INSERT INTO public.users (id, email, created_at, updated_at, first_name, last_name, tenant_id) VALUES (1, 'charles@twenty.com', '2023-01-31 16:46:43.02666+00', '2023-01-31 16:46:43.02666+00', 'Charles', 'Bochet', 1); +INSERT INTO public.users (id, email, created_at, updated_at, first_name, last_name, tenant_id) VALUES (2, 'charles@ouihelp.twenty.com', '2023-01-31 16:46:49.72368+00', '2023-01-31 16:46:49.72368+00', 'Charles', 'Bochet', 2); +INSERT INTO public.users (id, email, created_at, updated_at, first_name, last_name, tenant_id) VALUES (3, 'felix@twenty.com', '2023-01-31 16:47:06.516066+00', '2023-01-31 16:47:06.516066+00', 'Félix', 'Malfait', 1); +INSERT INTO public.users (id, email, created_at, updated_at, first_name, last_name, tenant_id) VALUES (4, 'felix@ouihelp.twenty.com', '2023-01-31 16:47:13.684386+00', '2023-01-31 16:47:13.684386+00', 'Félix', 'Malfait', 2); +SELECT pg_catalog.setval('public.users_id_seq', 4, true); diff --git a/api/seeds/twenty/1675183944004_seed.sql b/api/seeds/twenty/1675183944004_seed.sql new file mode 100644 index 000000000..68fbfff55 --- /dev/null +++ b/api/seeds/twenty/1675183944004_seed.sql @@ -0,0 +1,4 @@ +SET check_function_bodies = false; +INSERT INTO public.tenants (id, name, uuid, email_domain) VALUES (1, 'pilot', '8375f69d-47bd-4baa-a3c1-f8aaef8d8b2b', 'twenty.com'); +INSERT INTO public.tenants (id, name, uuid, email_domain) VALUES (2, 'ouihelp', 'c71becee-2cd6-4b31-827e-6cbef4e66879', 'ouihelp.twenty.com'); +SELECT pg_catalog.setval('public.tenants_id_seq', 2, true); diff --git a/infra/dev/Makefile b/infra/dev/Makefile new file mode 100644 index 000000000..ab0ffa8bc --- /dev/null +++ b/infra/dev/Makefile @@ -0,0 +1,39 @@ +up: ## + @docker-compose up -d + +logs: ## + @docker-compose logs $(container) -f + +api-sh: ## + @docker-compose exec twenty-api bash + +api-console: ## + @docker-compose exec twenty-api bash -c "cd /api; \ + socat TCP-LISTEN:8080,fork TCP:twenty-api:8080 & \ + socat TCP-LISTEN:9695,fork,reuseaddr,bind=twenty-api TCP:127.0.0.1:9695 & \ + socat TCP-LISTEN:9693,fork,reuseaddr,bind=twenty-api TCP:127.0.0.1:9693 & \ + hasura console --log-level DEBUG --address "127.0.0.1" --no-browser || exit 1" + +api-make-seed: ## + @docker-compose exec twenty-api bash -c "cd /api; \ + hasura seeds create seed --from-table $(table)" + +api-make-migrations: ## + @docker-compose exec twenty-api bash -c "cd /api; \ + hasura migrate create $(name)" + +api-make-metadata: ## + @docker-compose exec twenty-api bash -c "cd /api; \ + hasura metadata export" + +front-sh: ## + @docker-compose exec twenty-front bash + +front-test: ## + @docker-compose exec twenty-front sh -c "npm run test" + +front-coverage: ## + @docker-compose exec twenty-front sh -c "npm run coverage" + +front-storybook: ## + @docker-compose exec twenty-front sh -c "npm run storybook" diff --git a/infra/dev/docker-compose.yml b/infra/dev/docker-compose.yml index 060d8634e..736d868e7 100644 --- a/infra/dev/docker-compose.yml +++ b/infra/dev/docker-compose.yml @@ -24,12 +24,16 @@ services: build: ./twenty-api ports: - "8080:8080" + - "9695:9695" + - "9693:9693" + volumes: + - ../../api:/api depends_on: - "postgres" restart: always environment: HASURA_GRAPHQL_METADATA_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/hasura - PG_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/twenty + HASURA_GRAPHQL_PG_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/twenty HASURA_GRAPHQL_ENABLE_CONSOLE: "true" HASURA_GRAPHQL_DEV_MODE: "true" HASURA_GRAPHQL_ADMIN_SECRET: ${HASURA_GRAPHQL_ADMIN_SECRET} diff --git a/infra/dev/twenty-api/Dockerfile b/infra/dev/twenty-api/Dockerfile index 3da6192dd..e5c425416 100644 --- a/infra/dev/twenty-api/Dockerfile +++ b/infra/dev/twenty-api/Dockerfile @@ -1,3 +1,9 @@ FROM hasura/graphql-engine:latest as api +RUN apt-get update +RUN apt-get install -y curl +RUN apt-get install -y socat +RUN apt-get install -y vim +RUN curl -L https://github.com/hasura/graphql-engine/raw/stable/cli/get.sh | bash + CMD ["sh", "-c", "graphql-engine serve"] diff --git a/infra/prod/twenty-api/Dockerfile b/infra/prod/twenty-api/Dockerfile index 3da6192dd..db0fd81b4 100644 --- a/infra/prod/twenty-api/Dockerfile +++ b/infra/prod/twenty-api/Dockerfile @@ -1,3 +1,7 @@ FROM hasura/graphql-engine:latest as api +RUN apt-get update +RUN apt-get install -y curl +RUN curl -L https://github.com/hasura/graphql-engine/raw/stable/cli/get.sh | bash + CMD ["sh", "-c", "graphql-engine serve"]