Skip to content

Commit

Permalink
[Monorepo] redo codegen to be next to operation files and simpler (#424)
Browse files Browse the repository at this point in the history
Closes DG-136

## What changed? Why?
Dependency upgrades, tiny meta tweak, and redo codegen to be next to
operation files and simpler setup with a turbo clean that works
  • Loading branch information
dgattey committed Dec 30, 2023
1 parent 9652072 commit 594500d
Show file tree
Hide file tree
Showing 37 changed files with 228 additions and 384 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,3 @@ npm-debug.log*
.vercel
tsconfig.tsbuildinfo
.eslintcache

# Generated files
*/api/server/generated
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Pretty standard Next app here. `/public` contains static files, `/src` contains

- [MUI System](https://mui.com/system/getting-started/overview/) provides the styling system for layouts/usages of `sx` on props, running on `emotion` under the hood.

- [GraphQL Codegen](https://www.graphql-code-generator.com) makes all the `generated` files. It reads Github + Contentful's API schema + creates types out of them automatically. I run it on command when I write new queries/etc to get their types.
- [GraphQL Codegen](https://www.graphql-code-generator.com) makes all the `*.generated.ts` files. It reads Github + Contentful's API schema + creates types out of them automatically. I run it on command when I write new queries/etc to get their types.

- [PlanetScale](https://planetscale.com) powers a distributed DB. This DB is used to persist auth tokens for Spotify/Strava beyond the lifetime of a deploy + refresh the token as needed.

Expand Down
8 changes: 4 additions & 4 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@
"@contentful/rich-text-react-renderer": "15.19.0",
"@contentful/rich-text-types": "16.3.0",
"@emotion/cache": "11.11.0",
"@emotion/react": "11.11.1",
"@emotion/react": "11.11.3",
"@emotion/styled": "11.11.0",
"@fortawesome/fontawesome-svg-core": "6.5.1",
"@fortawesome/free-brands-svg-icons": "6.5.1",
"@fortawesome/free-solid-svg-icons": "6.5.1",
"@fortawesome/react-fontawesome": "0.2.0",
"@mui/material": "5.15.1",
"@mui/material": "5.15.2",
"@next/bundle-analyzer": "14.0.4",
"animate-css-grid": "1.5.1",
"db": "workspace:*",
"dotenv-mono": "1.3.13",
"graphql": "16.8.1",
"graphql-request": "6.1.0",
"lucide-react": "0.300.0",
"lucide-react": "0.303.0",
"mapbox-gl": "3.0.1",
"next": "14.0.4",
"og": "workspace:*",
Expand All @@ -47,7 +47,7 @@
"@next/eslint-plugin-next": "14.0.4",
"@types/mapbox-gl": "2.7.19",
"@types/node": "18.17.1",
"@types/react": "18.2.45",
"@types/react": "18.2.46",
"@types/react-dom": "18.2.18",
"eslint-config-dg": "workspace:*",
"tsconfig": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/api/parsers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Link, Project, TextBlock } from 'api/types/generated/contentfulApi.generated';
import type { Link, Project, TextBlock } from 'api/server/contentful/api.generated';

/**
* Type guard to get a link out
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as Types from './contentfulApi.generated';
import type * as Types from './api.generated';

export type MyLocationQueryVariables = Types.Exact<{ [key: string]: never }>;

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/api/server/contentful/fetchCurrentLocation.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { gql } from 'graphql-request';
import { isNotNullish } from 'shared-core/helpers/typeguards';
import type { MyLocationQuery } from 'api/types/generated/fetchCurrentLocation.generated';
import type { MapLocation } from 'api/types/MapLocation';
import { contentfulClient } from '../networkClients/contentfulClient';
import type { MyLocationQuery } from './fetchCurrentLocation.generated';

/**
* Grabs the home location using a known id for it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as Types from './contentfulApi.generated';
import type * as Types from './api.generated';

export type FooterQueryVariables = Types.Exact<{ [key: string]: never }>;

Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/api/server/contentful/fetchFooterLinks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { gql } from 'graphql-request';
import { isNotNullish } from 'shared-core/helpers/typeguards';
import { isLink } from 'api/parsers';
import type { Link } from 'api/types/generated/contentfulApi.generated';
import type { FooterQuery } from 'api/types/generated/fetchFooterLinks.generated';
import { contentfulClient } from '../networkClients/contentfulClient';
import type { Link } from './api.generated';
import type { FooterQuery } from './fetchFooterLinks.generated';

/**
* Grabs the contentful sections with the title of footer. Should
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as Types from './contentfulApi.generated';
import type * as Types from './api.generated';

export type IntroBlockQueryVariables = Types.Exact<{ [key: string]: never }>;

Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/api/server/contentful/fetchIntroContent.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { gql } from 'graphql-request';
import { isTextBlock } from 'api/parsers';
import type { TextBlock } from 'api/types/generated/contentfulApi.generated';
import type { IntroBlockQuery } from 'api/types/generated/fetchIntroContent.generated';
import { contentfulClient } from '../networkClients/contentfulClient';
import type { TextBlock } from './api.generated';
import type { IntroBlockQuery } from './fetchIntroContent.generated';

/**
* Grabs the contentful sections with the title of header. Should
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as Types from './contentfulApi.generated';
import type * as Types from './api.generated';

export type PrivacyBlockQueryVariables = Types.Exact<{ [key: string]: never }>;

Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/api/server/contentful/fetchPrivacyContent.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { gql } from 'graphql-request';
import { isTextBlock } from 'api/parsers';
import type { PrivacyBlockQuery } from 'api/types/generated/fetchPrivacyContent.generated';
import { contentfulClient } from '../networkClients/contentfulClient';
import type { TextBlock } from '../../types/generated/contentfulApi.generated';
import type { TextBlock } from './api.generated';
import type { PrivacyBlockQuery } from './fetchPrivacyContent.generated';

/**
* Grabs the Contentful text block for the privacy page - should be
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as Types from './contentfulApi.generated';
import type * as Types from './api.generated';

export type ProjectsQueryVariables = Types.Exact<{ [key: string]: never }>;

Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/api/server/contentful/fetchProjects.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { gql } from 'graphql-request';
import { isProject } from 'api/parsers';
import type { Project } from 'api/types/generated/contentfulApi.generated';
import type { ProjectsQuery } from 'api/types/generated/fetchProjects.generated';
import { contentfulClient } from '../networkClients/contentfulClient';
import type { Project } from './api.generated';
import type { ProjectsQuery } from './fetchProjects.generated';

/**
* Grabs all projects to display
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as Types from './githubApi.generated';
import type * as Types from './api.generated';

export type GithubRepoVersionQueryVariables = Types.Exact<{ [key: string]: never }>;

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/api/server/github/fetchRepoVersion.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { gql } from 'graphql-request';
import type { GithubRepoVersionQuery } from 'api/types/generated/fetchRepoVersion.generated';
import { githubClient } from '../networkClients/githubClient';
import type { GithubRepoVersionQuery } from './fetchRepoVersion.generated';

/**
* This, strictly speaking, is usually overkill. We fetch the 100 most recently
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/api/types/MapLocation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Asset } from 'api/types/generated/contentfulApi.generated';
import type { MyLocationQuery } from 'api/types/generated/fetchCurrentLocation.generated';
import type { Asset } from 'api/server/contentful/api.generated';
import type { MyLocationQuery } from 'api/server/contentful/fetchCurrentLocation.generated';

/**
* Represents a location along with some metadata
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ContentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Card, Typography } from '@mui/material';
import { mixinSx } from 'ui/helpers/mixinSx';
import type { SxProps } from 'ui/theme';
import { truncated } from 'ui/helpers/truncated';
import type { Link } from 'api/types/generated/contentfulApi.generated';
import type { Link } from 'api/server/contentful/api.generated';
import { ContentWrappingLink } from './ContentWrappingLink';

export type ContentCardProps = Pick<
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ContentWrappingLink.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { SxProps } from 'ui/theme';
import type { Link as LinkType } from 'api/types/generated/contentfulApi.generated';
import type { Link as LinkType } from 'api/server/contentful/api.generated';
import { Link } from 'components/Link';

type ContentWrappingLinkProps = Pick<React.ComponentProps<'div'>, 'children'> & {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Container } from '@mui/material';
import { Section } from 'ui/core/Section';
import { Nav, NavGroup, NavItem } from 'ui/core/Nav';
import { HorizontalStack } from 'ui/core/HorizontalStack';
import type { Link as LinkType } from 'api/types/generated/contentfulApi.generated';
import type { Link as LinkType } from 'api/server/contentful/api.generated';
import { useData } from 'api/useData';
import { Link } from './Link';

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { styled } from '@mui/material';
import NextImage from 'next/image';
import { BREAKPOINT_MAX_SIZES } from 'ui/helpers/imageSizes';
import type { Asset } from 'api/types/generated/contentfulApi.generated';
import type { Asset } from 'api/server/contentful/api.generated';

type ImageProps = Partial<Asset> & {
url: Asset['url'];
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/Meta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export function Meta({ title, description }: MetaProps) {

// Construct url-encoded title and subtitle for the og image
const imageTitle = encodeURIComponent(title ?? SITE_NAME);
const imageSubtitle = encodeURIComponent(title === HOMEPAGE_TITLE ? SITE_NAME : HOMEPAGE_TITLE);
const imageSubtitle = encodeURIComponent(title ? SITE_NAME : HOMEPAGE_TITLE);
const theme = useTheme();

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/RichText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { isNotNullish } from 'shared-core/helpers/typeguards';
import type { SxProps } from 'ui/theme';
import { PROJECT_MAX_IMAGE_DIMENSION } from 'ui/helpers/imageSizes';
import { isLink, isProject } from 'api/parsers';
import type { Asset, Entry, TextBlockContent } from 'api/types/generated/contentfulApi.generated';
import type { Asset, Entry, TextBlockContent } from 'api/server/contentful/api.generated';
import { ProjectCard } from 'components/homepage/ProjectCard';
import { Image } from './Image';
import { Link } from './Link';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/homepage/ProjectCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from 'react';
import { useCurrentImageSizes } from 'ui/helpers/useCurrentImageSizes';
import type { Project } from 'api/types/generated/contentfulApi.generated';
import type { Project } from 'api/server/contentful/api.generated';
import type { ContentCardProps } from 'components/ContentCard';
import { ContentCard } from 'components/ContentCard';
import { HoverableContainer } from 'components/HoverableContainer';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/hooks/useLinkWithName.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { findLinkWithName } from 'api/parsers';
import type { Link as LinkProps } from 'api/types/generated/contentfulApi.generated';
import type { Link as LinkProps } from 'api/server/contentful/api.generated';
import { useData } from 'api/useData';

/**
Expand Down
102 changes: 1 addition & 101 deletions packages/codegen/config.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,9 @@
import path from 'node:path';
import type { CodegenConfig } from '@graphql-codegen/cli';
import { dotenvLoad } from 'dotenv-mono';
import { createApiGenerator } from './createApiGenerator';

dotenvLoad();

// Get path from package root to `apps/web/src` folder
const ROOT = __dirname.split('/').slice(0, -2).join('/');

// Where all our documents to parse live by default
const BASE_FOLDER = path.join(ROOT, 'apps/web/src/api/server');

// Relative to BASE_FOLDER, where our generated files live
const GENERATED_FOLDER = '../types/generated';

// Standard options for the files generated from operations or the main api file
const SHARED_CONFIG = {
avoidOptionals: true,
immutableTypes: true,
skipTypename: true,
useTypeImports: true,
maybeValue: 'T | undefined',
};

// Standard options for the *api.generated.ts files
const API_CONFIG = {
...SHARED_CONFIG,
constEnums: true,
enumsAsTypes: true,
defaultScalarType: 'unknown',
};

/**
* Hi! Complicated file, read me to understand! This creates generators for
* `@graphql-codegen` so we can have nice types for the APIs we use and the queries/
* mutations we write.
*
* This function creates two generators for a given API configuration. One is for
* a main shared "xApi.generated.ts" file. The other generator creates one file
* per file that has operations in it, with types for each operation. The resulting
* object from this function is spread into the `generates` key in the options below.
*
* You'll notice that every API has the same configuration except for the name,
* scalars, and endpoint/authorization. That's intentional!
*/
const createApiGenerator = (
name: string,
{
schemaEndpoint,
token,
scalars,
onlyOperationTypes,
}: {
schemaEndpoint: string;
token: string;
scalars: Record<string, unknown>;
onlyOperationTypes: boolean;
},
): CodegenConfig['generates'] => {
const documents = `${BASE_FOLDER}/${name}/*.ts`;
const baseTypesPath = `${GENERATED_FOLDER}/${name}Api.generated.ts`;
const schemas = [
{
[schemaEndpoint]: {
headers: {
/**
* Required for Github to generate properly
*/
'User-Agent': 'dylangattey.com',
Authorization: `Bearer ${token}`,
},
},
},
];

return {
// Creates the main `${name}Api.generated.ts` file
[`${BASE_FOLDER}/${baseTypesPath}`]: {
documents,
schema: schemas,
plugins: ['typescript'],
config: {
...API_CONFIG,
onlyOperationTypes,
scalars,
},
},

// Creates individual `.generated.ts` files for each .ts file that has operations
[`${BASE_FOLDER}/${name}/`]: {
documents,
schema: schemas,
plugins: ['typescript-operations'],
preset: 'near-operation-file',
presetConfig: {
baseTypesPath: `../${baseTypesPath}`,
folder: `../${GENERATED_FOLDER}`,
},
config: {
...SHARED_CONFIG,
preResolveTypes: true,
},
},
};
};

// For the Contentful API
const contentfulGenerators = createApiGenerator('contentful', {
schemaEndpoint: `https://graphql.contentful.com/content/v1/spaces/${process.env.CONTENTFUL_SPACE_ID}`,
Expand Down
Loading

1 comment on commit 594500d

@vercel
Copy link

@vercel vercel bot commented on 594500d Dec 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

dg – ./

dg-dgattey.vercel.app
dg-git-main-dgattey.vercel.app
dylangattey.com
dg.vercel.app

Please sign in to comment.