diff --git a/codegen.js b/codegen.ts similarity index 87% rename from codegen.js rename to codegen.ts index c15a1881..6185eda7 100644 --- a/codegen.js +++ b/codegen.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { CodegenConfig } from '@graphql-codegen/cli'; + require('dotenv').config(); // Where all our documents to parse live by default @@ -35,15 +38,22 @@ const API_CONFIG = { * * You'll notice that every API has the same configuration except for the name, * scalars, and endpoint/authorization. That's intentional! - * - * @param {String} name The API name (lowercase) - * @param {{ schemaEndpoint: string, token: string, scalars: Record, onlyOperationTypes: boolean }} options all API options - * - * @returns {Record>} The generators to spread */ -const createApiGenerator = (name, { schemaEndpoint, token, scalars, onlyOperationTypes }) => { - const firstLetter = name[0] ?? ''; - const documents = `${BASE_FOLDER}/fetch${firstLetter.toUpperCase() + name.slice(1)}*.ts`; +const createApiGenerator = ( + name: string, + { + schemaEndpoint, + token, + scalars, + onlyOperationTypes, + }: { + schemaEndpoint: string; + token: string; + scalars: Record; + onlyOperationTypes: boolean; + }, +): CodegenConfig['generates'] => { + const documents = `${BASE_FOLDER}/${name}/*.ts`; const baseTypesPath = `${GENERATED_FOLDER}/${name}Api.generated.ts`; const schemas = [ { @@ -76,7 +86,7 @@ const createApiGenerator = (name, { schemaEndpoint, token, scalars, onlyOperatio preset: 'near-operation-file', presetConfig: { baseTypesPath: `../${baseTypesPath}`, - folder: GENERATED_FOLDER, + folder: `../${GENERATED_FOLDER}`, }, config: { ...SHARED_CONFIG, @@ -124,7 +134,7 @@ const githubGenerators = createApiGenerator('github', { * prettier after running generation for Contentful and Github, * and overwrite existing files. */ -module.exports = { +const config: CodegenConfig = { overwrite: true, hooks: { afterAllFileWrite: ['prettier --write'], @@ -134,3 +144,5 @@ module.exports = { ...githubGenerators, }, }; + +export default config; diff --git a/package.json b/package.json index 8651c2f2..a6589472 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "format": "prettier --loglevel warn --write \"**/*.{js,ts,tsx,mjs,cjs,css,md,json,yml,yaml}\"", "lint": "eslint . --cache --fix --ext .js,.ts,.tsx,.mjs,.cjs --no-eslintrc -c config/eslint.config.js", "lint:types": "tsc --noEmit", - "codegen": "DOTENV_CONFIG_PATH='.env.development.local' graphql-codegen --require dotenv/config --config codegen.js", + "codegen": "DOTENV_CONFIG_PATH='.env.development.local' graphql-codegen --require dotenv/config --config codegen.ts", "db": "sequelize", "db:migrate": "sequelize db:migrate", "db:migrate:status": "sequelize db:migrate:status", diff --git a/scripts/getVersion.ts b/scripts/getVersion.ts deleted file mode 100644 index da43fb76..00000000 --- a/scripts/getVersion.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { fetchGithubRepoVersion } from '../src/api/server/fetchGithubRepoVersion'; - -/** - * Asynchronously fetches the version of the repo from Github using the - * right data, then writes it to STDOUT for later use. - */ -const getVersion = async () => { - const version = (await fetchGithubRepoVersion()) ?? 'vX.Y.Z'; - process.stdout.write(version); -}; - -(() => getVersion())(); diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index 096e11cc..934c3b0c 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -1,10 +1,10 @@ -import { fetchContentfulFooterLinks } from './server/fetchContentfulFooterLinks'; -import { fetchContentfulIntroBlock } from './server/fetchContentfulIntroBlock'; -import { fetchContentfulLocation } from './server/fetchContentfulLocation'; -import { fetchContentfulPrivacyBlock } from './server/fetchContentfulPrivacyBlock'; -import { fetchContentfulProjects } from './server/fetchContentfulProjects'; -import { fetchGithubRepoVersion } from './server/fetchGithubRepoVersion'; -import { fetchSpotifyCurrentlyPlaying } from './server/fetchSpotifyCurrentlyOrRecentlyPlayed'; +import { fetchFooterLinks } from './server/contentful/fetchFooterLinks'; +import { fetchIntroContent } from './server/contentful/fetchIntroContent'; +import { fetchCurrentLocation } from './server/contentful/fetchCurrentLocation'; +import { fetchPrivacyContent } from './server/contentful/fetchPrivacyContent'; +import { fetchProjects } from './server/contentful/fetchProjects'; +import { fetchRepoVersion } from './server/github/fetchRepoVersion'; +import { fetchRecentlyPlayed } from './server/spotify/fetchRecentlyPlayed'; import { fetchLatestStravaActivityFromDb } from './server/strava/fetchLatestStravaActivityFromDb'; /** @@ -30,25 +30,25 @@ export type AwaitedType = Awaited>; */ export const endpoints = { // Intro block of content via Contentful - intro: fetchContentfulIntroBlock, + intro: fetchIntroContent, // Privacy block of content via Contentful - privacy: fetchContentfulPrivacyBlock, + privacy: fetchPrivacyContent, // My current location via Contentful - location: fetchContentfulLocation, + location: fetchCurrentLocation, // All projects via Contentful - projects: fetchContentfulProjects, + projects: fetchProjects, // Footer links via Contentful - footer: fetchContentfulFooterLinks, + footer: fetchFooterLinks, // App version via Github - version: fetchGithubRepoVersion, + version: fetchRepoVersion, // Last played song via Spotify - 'latest/track': fetchSpotifyCurrentlyPlaying, + 'latest/track': fetchRecentlyPlayed, // Fetches the latest Strava activity I've done 'latest/activity': fetchLatestStravaActivityFromDb, diff --git a/src/api/server/fetchContentfulLocation.ts b/src/api/server/contentful/fetchCurrentLocation.ts similarity index 60% rename from src/api/server/fetchContentfulLocation.ts rename to src/api/server/contentful/fetchCurrentLocation.ts index d2385ced..d2705b84 100644 --- a/src/api/server/fetchContentfulLocation.ts +++ b/src/api/server/contentful/fetchCurrentLocation.ts @@ -1,15 +1,8 @@ import { isDefinedItem } from 'api/parsers'; -import type { MyLocationQuery } from 'api/types/generated/fetchContentfulLocation.generated'; +import type { MyLocationQuery } from 'api/types/generated/fetchCurrentLocation.generated'; import type { MapLocation } from 'api/types/MapLocation'; -import { MAP_MARKER_IMAGE_SIZE, PROJECT_MAX_IMAGE_DIMENSION } from 'constants/imageSizes'; import { gql } from 'graphql-request'; -import { contentfulClient } from './networkClients/contentfulClient'; - -// To account for pixel density, we need double the size! -const IMAGE_SIZE = MAP_MARKER_IMAGE_SIZE * 2; - -// The preview image is a standard project size -const PREVIEW_IMAGE_SIZE = PROJECT_MAX_IMAGE_DIMENSION * 2; +import { contentfulClient } from '../networkClients/contentfulClient'; /** * Grabs the home location using a known id for it @@ -24,30 +17,36 @@ const QUERY = gql` initialZoom zoomLevels image { - url(transform: { - width: ${IMAGE_SIZE}, - height: ${IMAGE_SIZE}, - format: WEBP - }) + url( + transform: { + width: 170 # MAP_MARKER_IMAGE_SIZE * 2 + height: 170 # MAP_MARKER_IMAGE_SIZE * 2 + format: WEBP + } + ) width height } } lightImage: asset(id: "5PrFVu1gJBLhgJGixRL4Wc") { - url(transform: { - width: ${PREVIEW_IMAGE_SIZE}, - height: ${PREVIEW_IMAGE_SIZE}, - quality: 80, + url( + transform: { + width: 660 # PROJECT_MAX_IMAGE_DIMENSION * 2 + height: 660 # PROJECT_MAX_IMAGE_DIMENSION * 2 + quality: 80 format: WEBP - }) + } + ) } darkImage: asset(id: "6bRgM9lkcceJQOE0jSOEfu") { - url(transform: { - width: ${PREVIEW_IMAGE_SIZE}, - height: ${PREVIEW_IMAGE_SIZE}, - quality: 80, + url( + transform: { + width: 660 # PROJECT_MAX_IMAGE_DIMENSION * 2 + height: 660 # PROJECT_MAX_IMAGE_DIMENSION * 2 + quality: 80 format: WEBP - }) + } + ) } } `; @@ -55,7 +54,7 @@ const QUERY = gql` /** * Fetches my current location from Contentful. */ -export const fetchContentfulLocation = async (): Promise => { +export async function fetchCurrentLocation(): Promise { const data = await contentfulClient.request(QUERY); const location = data?.contentTypeLocation; if (!location || !data?.lightImage?.url || !data?.darkImage?.url) { @@ -75,4 +74,4 @@ export const fetchContentfulLocation = async (): Promise => zoomLevels, backupImageUrls: { light: data.lightImage.url, dark: data.darkImage.url }, }; -}; +} diff --git a/src/api/server/fetchContentfulFooterLinks.ts b/src/api/server/contentful/fetchFooterLinks.ts similarity index 67% rename from src/api/server/fetchContentfulFooterLinks.ts rename to src/api/server/contentful/fetchFooterLinks.ts index ad6abc9d..79fa13c1 100644 --- a/src/api/server/fetchContentfulFooterLinks.ts +++ b/src/api/server/contentful/fetchFooterLinks.ts @@ -1,7 +1,8 @@ import { isDefinedItem, isLink } from 'api/parsers'; -import type { FooterQuery } from 'api/types/generated/fetchContentfulFooterLinks.generated'; +import type { Link } from 'api/types/generated/contentfulApi.generated'; +import type { FooterQuery } from 'api/types/generated/fetchFooterLinks.generated'; import { gql } from 'graphql-request'; -import { contentfulClient } from './networkClients/contentfulClient'; +import { contentfulClient } from '../networkClients/contentfulClient'; /** * Grabs the contentful sections with the title of footer. Should @@ -26,13 +27,12 @@ const QUERY = gql` `; /** - * Fetches all our site footer blocks from the Contentful API. Parses - * out the text and icon links separately + * Fetches all our site footer blocks from the Contentful API. */ -export const fetchContentfulFooterLinks = async () => { +export async function fetchFooterLinks(): Promise> { const data = await contentfulClient.request(QUERY); const items = data?.sectionCollection?.items.flatMap((item) => item?.blocksCollection?.items ?? []) ?? []; const links = items.filter(isLink).filter(isDefinedItem); return links; -}; +} diff --git a/src/api/server/fetchContentfulIntroBlock.ts b/src/api/server/contentful/fetchIntroContent.ts similarity index 68% rename from src/api/server/fetchContentfulIntroBlock.ts rename to src/api/server/contentful/fetchIntroContent.ts index 2a536e79..d7b52b88 100644 --- a/src/api/server/fetchContentfulIntroBlock.ts +++ b/src/api/server/contentful/fetchIntroContent.ts @@ -1,11 +1,8 @@ import { isTextBlock } from 'api/parsers'; -import type { IntroBlockQuery } from 'api/types/generated/fetchContentfulIntroBlock.generated'; -import { PROJECT_MAX_IMAGE_DIMENSION } from 'constants/imageSizes'; +import type { TextBlock } from 'api/types/generated/contentfulApi.generated'; +import type { IntroBlockQuery } from 'api/types/generated/fetchIntroContent.generated'; import { gql } from 'graphql-request'; -import { contentfulClient } from './networkClients/contentfulClient'; - -// Account for pixel density -const IMAGE_SIZE = PROJECT_MAX_IMAGE_DIMENSION * 2; +import { contentfulClient } from '../networkClients/contentfulClient'; /** * Grabs the contentful sections with the title of header. Should @@ -14,11 +11,13 @@ const IMAGE_SIZE = PROJECT_MAX_IMAGE_DIMENSION * 2; const QUERY = gql` query IntroBlock { asset(id: "1P5peDFKfzDHjWd6mcytc8") { - url(transform: { - width: ${IMAGE_SIZE} - height: ${IMAGE_SIZE} - format: WEBP - }) + url( + transform: { + width: 660 # PROJECT_MAX_IMAGE_DIMENSION * 2 + height: 660 # PROJECT_MAX_IMAGE_DIMENSION * 2 + format: WEBP + } + ) width height title @@ -67,7 +66,15 @@ const QUERY = gql` * Fetches the text block corresponding to the introduction rich text * for the home page. */ -export const fetchContentfulIntroBlock = async () => { +export async function fetchIntroContent(): Promise { const data = await contentfulClient.request(QUERY); const textBlock = data?.textBlockCollection?.items?.filter(isTextBlock)?.[0]; const image = data?.asset; @@ -75,4 +82,4 @@ export const fetchContentfulIntroBlock = async () => { return { textBlock, image }; } return null; -}; +} diff --git a/src/api/server/fetchContentfulPrivacyBlock.ts b/src/api/server/contentful/fetchPrivacyContent.ts similarity index 83% rename from src/api/server/fetchContentfulPrivacyBlock.ts rename to src/api/server/contentful/fetchPrivacyContent.ts index 99f58a38..5eee1881 100644 --- a/src/api/server/fetchContentfulPrivacyBlock.ts +++ b/src/api/server/contentful/fetchPrivacyContent.ts @@ -1,7 +1,8 @@ import { isTextBlock } from 'api/parsers'; -import type { PrivacyBlockQuery } from 'api/types/generated/fetchContentfulPrivacyBlock.generated'; import { gql } from 'graphql-request'; -import { contentfulClient } from './networkClients/contentfulClient'; +import type { PrivacyBlockQuery } from 'api/types/generated/fetchPrivacyContent.generated'; +import { contentfulClient } from '../networkClients/contentfulClient'; +import { TextBlock } from '../../types/generated/contentfulApi.generated'; /** * Grabs the Contentful text block for the privacy page - should be @@ -53,7 +54,7 @@ const QUERY = gql` * Fetches the text block corresponding to the privacy rich text * for the privacy page. */ -export const fetchContentfulPrivacyBlock = async () => { +export async function fetchPrivacyContent(): Promise { const data = await contentfulClient.request(QUERY); - return data?.textBlockCollection?.items?.filter(isTextBlock)?.[0]; -}; + return data?.textBlockCollection?.items?.filter(isTextBlock)?.[0] ?? null; +} diff --git a/src/api/server/fetchContentfulProjects.ts b/src/api/server/contentful/fetchProjects.ts similarity index 70% rename from src/api/server/fetchContentfulProjects.ts rename to src/api/server/contentful/fetchProjects.ts index 6bb3b205..b96c4a34 100644 --- a/src/api/server/fetchContentfulProjects.ts +++ b/src/api/server/contentful/fetchProjects.ts @@ -1,7 +1,8 @@ import { isProject } from 'api/parsers'; -import type { ProjectsQuery } from 'api/types/generated/fetchContentfulProjects.generated'; +import { Project } from 'api/types/generated/contentfulApi.generated'; +import type { ProjectsQuery } from 'api/types/generated/fetchProjects.generated'; import { gql } from 'graphql-request'; -import { contentfulClient } from './networkClients/contentfulClient'; +import { contentfulClient } from '../networkClients/contentfulClient'; /** * Grabs all projects to display @@ -33,7 +34,7 @@ const QUERY = gql` /** * Fetches all projects sorted by newest first. */ -export const fetchContentfulProjects = async () => { +export async function fetchProjects(): Promise> { const data = await contentfulClient.request(QUERY); return data?.projectCollection?.items.filter(isProject) ?? []; -}; +} diff --git a/src/api/server/fetchGithubRepoVersion.ts b/src/api/server/github/fetchRepoVersion.ts similarity index 92% rename from src/api/server/fetchGithubRepoVersion.ts rename to src/api/server/github/fetchRepoVersion.ts index 6f737341..fb8c5f20 100644 --- a/src/api/server/fetchGithubRepoVersion.ts +++ b/src/api/server/github/fetchRepoVersion.ts @@ -1,6 +1,6 @@ -import type { GithubRepoVersionQuery } from 'api/types/generated/fetchGithubRepoVersion.generated'; +import type { GithubRepoVersionQuery } from 'api/types/generated/fetchRepoVersion.generated'; import { gql } from 'graphql-request'; -import { githubClient } from './networkClients/githubClient'; +import { githubClient } from '../networkClients/githubClient'; /** * This, strictly speaking, is usually overkill. We fetch the 100 most recently @@ -35,7 +35,7 @@ const QUERY = gql` * help us find the release when running locally. A production build locally won't * have either of these defined, so we'll just return `null`. */ -export const fetchGithubRepoVersion = async () => { +export async function fetchRepoVersion(): Promise { const version = process.env.NEXT_PUBLIC_APP_VERSION; if (version?.length) { return version; @@ -48,4 +48,4 @@ export const fetchGithubRepoVersion = async () => { const filteredReleases = releases?.filter((release) => release?.tagCommit?.oid === commitSha?.trim()) ?? []; return filteredReleases[0]?.name ?? commitSha?.slice(-12) ?? null; -}; +} diff --git a/src/api/server/fetchSpotifyCurrentlyOrRecentlyPlayed.ts b/src/api/server/spotify/fetchRecentlyPlayed.ts similarity index 84% rename from src/api/server/fetchSpotifyCurrentlyOrRecentlyPlayed.ts rename to src/api/server/spotify/fetchRecentlyPlayed.ts index 70b2a3e7..a82e037f 100644 --- a/src/api/server/fetchSpotifyCurrentlyOrRecentlyPlayed.ts +++ b/src/api/server/spotify/fetchRecentlyPlayed.ts @@ -1,6 +1,7 @@ import type { CurrentlyPlaying } from 'api/types/spotify/CurrentlyPlaying'; import type { RecentlyPlayed } from 'api/types/spotify/RecentlyPlayed'; -import { spotifyClient } from './networkClients/spotifyClient'; +import { Track } from 'api/types/spotify/Track'; +import { spotifyClient } from '../networkClients/spotifyClient'; const CURRENTLY_PLAYING_RESOURCE = 'me/player/currently-playing'; const RECENTLY_PLAYED_RESOURCE = 'me/player/recently-played?limit=1'; @@ -10,13 +11,13 @@ const RECENTLY_PLAYED_RESOURCE = 'me/player/recently-played?limit=1'; * May have no content, which signifies nothing is playing, which is returned * as `null`, or returns full JSON. */ -export const fetchSpotifyCurrentlyPlaying = async () => { +export async function fetchRecentlyPlayed(): Promise { const currentlyPlaying = await spotifyClient.fetch(CURRENTLY_PLAYING_RESOURCE); switch (currentlyPlaying.status) { case 200: { const data = await currentlyPlaying.json(); - return data?.item; + return data?.item ?? null; } case 204: { // Fetch the last played song instead @@ -32,4 +33,4 @@ export const fetchSpotifyCurrentlyPlaying = async () => { // This could be rate limiting, or auth problems, etc. return null; } -}; +} diff --git a/src/api/types/MapLocation.ts b/src/api/types/MapLocation.ts index 1317db91..665dafee 100644 --- a/src/api/types/MapLocation.ts +++ b/src/api/types/MapLocation.ts @@ -1,5 +1,5 @@ import { Asset } from 'api/types/generated/contentfulApi.generated'; -import type { MyLocationQuery } from 'api/types/generated/fetchContentfulLocation.generated'; +import type { MyLocationQuery } from 'api/types/generated/fetchCurrentLocation.generated'; /** * Represents a location along with some metadata diff --git a/src/api/types/generated/fetchContentfulHeaderLinks.generated.ts b/src/api/types/generated/fetchContentfulHeaderLinks.generated.ts deleted file mode 100644 index 645ffad7..00000000 --- a/src/api/types/generated/fetchContentfulHeaderLinks.generated.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type * as Types from './contentfulApi.generated'; - -export type HeaderQueryVariables = Types.Exact<{ [key: string]: never }>; - -export type HeaderQuery = { - readonly sectionCollection: - | { - readonly items: ReadonlyArray< - | { - readonly blocksCollection: - | { - readonly items: ReadonlyArray< - | { readonly title: string | undefined; readonly url: string | undefined } - | {} - | undefined - >; - } - | undefined; - } - | undefined - >; - } - | undefined; -}; diff --git a/src/api/types/generated/fetchContentfulLocation.generated.ts b/src/api/types/generated/fetchCurrentLocation.generated.ts similarity index 100% rename from src/api/types/generated/fetchContentfulLocation.generated.ts rename to src/api/types/generated/fetchCurrentLocation.generated.ts diff --git a/src/api/types/generated/fetchContentfulFooterLinks.generated.ts b/src/api/types/generated/fetchFooterLinks.generated.ts similarity index 100% rename from src/api/types/generated/fetchContentfulFooterLinks.generated.ts rename to src/api/types/generated/fetchFooterLinks.generated.ts diff --git a/src/api/types/generated/fetchContentfulIntroBlock.generated.ts b/src/api/types/generated/fetchIntroContent.generated.ts similarity index 100% rename from src/api/types/generated/fetchContentfulIntroBlock.generated.ts rename to src/api/types/generated/fetchIntroContent.generated.ts diff --git a/src/api/types/generated/fetchContentfulPrivacyBlock.generated.ts b/src/api/types/generated/fetchPrivacyContent.generated.ts similarity index 100% rename from src/api/types/generated/fetchContentfulPrivacyBlock.generated.ts rename to src/api/types/generated/fetchPrivacyContent.generated.ts diff --git a/src/api/types/generated/fetchContentfulProjects.generated.ts b/src/api/types/generated/fetchProjects.generated.ts similarity index 100% rename from src/api/types/generated/fetchContentfulProjects.generated.ts rename to src/api/types/generated/fetchProjects.generated.ts diff --git a/src/api/types/generated/fetchGithubRepoVersion.generated.ts b/src/api/types/generated/fetchRepoVersion.generated.ts similarity index 100% rename from src/api/types/generated/fetchGithubRepoVersion.generated.ts rename to src/api/types/generated/fetchRepoVersion.generated.ts diff --git a/src/api/types/generated/githubApi.generated.ts b/src/api/types/generated/githubApi.generated.ts index c1ac6355..d69e97a8 100644 --- a/src/api/types/generated/githubApi.generated.ts +++ b/src/api/types/generated/githubApi.generated.ts @@ -839,6 +839,18 @@ export type ConvertPullRequestToDraftInput = { readonly pullRequestId: Scalars['ID']; }; +/** Autogenerated input type of CreateAttributionInvitation */ +export type CreateAttributionInvitationInput = { + /** A unique identifier for the client performing the mutation. */ + readonly clientMutationId: InputMaybe; + /** The Node ID of the owner scoping the reattributable data. */ + readonly ownerId: Scalars['ID']; + /** The Node ID of the account owning the data to reattribute. */ + readonly sourceId: Scalars['ID']; + /** The Node ID of the account which may claim the data. */ + readonly targetId: Scalars['ID']; +}; + /** Autogenerated input type of CreateBranchProtectionRule */ export type CreateBranchProtectionRuleInput = { /** Can this branch be deleted. */ @@ -1041,19 +1053,19 @@ export type CreateLinkedBranchInput = { /** Autogenerated input type of CreateMigrationSource */ export type CreateMigrationSourceInput = { - /** The Octoshift migration source access token. */ + /** The migration source access token. */ readonly accessToken: InputMaybe; /** A unique identifier for the client performing the mutation. */ readonly clientMutationId: InputMaybe; /** The GitHub personal access token of the user importing to the target repository. */ readonly githubPat: InputMaybe; - /** The Octoshift migration source name. */ + /** The migration source name. */ readonly name: Scalars['String']; - /** The ID of the organization that will own the Octoshift migration source. */ + /** The ID of the organization that will own the migration source. */ readonly ownerId: Scalars['ID']; - /** The Octoshift migration source type. */ + /** The migration source type. */ readonly type: MigrationSourceType; - /** The Octoshift migration source URL. */ + /** The migration source URL. */ readonly url: Scalars['String']; }; @@ -1108,6 +1120,8 @@ export type CreatePullRequestInput = { * */ readonly headRefName: Scalars['String']; + /** The Node ID of the head repository. */ + readonly headRepositoryId: InputMaybe; /** Indicates whether maintainers can modify the pull request. */ readonly maintainerCanModify: InputMaybe; /** The Node ID of the repository. */ @@ -1152,6 +1166,26 @@ export type CreateRepositoryInput = { readonly visibility: RepositoryVisibility; }; +/** Autogenerated input type of CreateSponsorsListing */ +export type CreateSponsorsListingInput = { + /** The country or region where the sponsorable's bank account is located. Required if fiscalHostLogin is not specified, ignored when fiscalHostLogin is specified. */ + readonly billingCountryOrRegionCode: InputMaybe; + /** A unique identifier for the client performing the mutation. */ + readonly clientMutationId: InputMaybe; + /** The email address we should use to contact you about the GitHub Sponsors profile being created. This will not be shared publicly. Must be a verified email address already on your GitHub account. Only relevant when the sponsorable is yourself. Defaults to your primary email address on file if omitted. */ + readonly contactEmail: InputMaybe; + /** The username of the supported fiscal host's GitHub organization, if you want to receive sponsorship payouts through a fiscal host rather than directly to a bank account. For example, 'Open-Source-Collective' for Open Source Collective or 'numfocus' for numFOCUS. Case insensitive. See https://docs.github.com/sponsors/receiving-sponsorships-through-github-sponsors/using-a-fiscal-host-to-receive-github-sponsors-payouts for more information. */ + readonly fiscalHostLogin: InputMaybe; + /** The URL for your profile page on the fiscal host's website, e.g., https://opencollective.com/babel or https://numfocus.org/project/bokeh. Required if fiscalHostLogin is specified. */ + readonly fiscallyHostedProjectProfileUrl: InputMaybe; + /** Provide an introduction to serve as the main focus that appears on your GitHub Sponsors profile. It's a great opportunity to help potential sponsors learn more about you, your work, and why their sponsorship is important to you. GitHub-flavored Markdown is supported. */ + readonly fullDescription: InputMaybe; + /** The country or region where the sponsorable resides. This is for tax purposes. Required if the sponsorable is yourself, ignored when sponsorableLogin specifies an organization. */ + readonly residenceCountryOrRegionCode: InputMaybe; + /** The username of the organization to create a GitHub Sponsors profile for, if desired. Defaults to creating a GitHub Sponsors profile for the authenticated user if omitted. */ + readonly sponsorableLogin: InputMaybe; +}; + /** Autogenerated input type of CreateSponsorsTier */ export type CreateSponsorsTierInput = { /** The value of the new tier in US dollars. Valid values: 1-12000. */ @@ -2364,6 +2398,21 @@ export type LockReason = /** The issue or pull request was locked because the conversation was too heated. */ | 'TOO_HEATED'; +/** Ordering options for mannequins. */ +export type MannequinOrder = { + /** The ordering direction. */ + readonly direction: OrderDirection; + /** The field to order mannequins by. */ + readonly field: MannequinOrderField; +}; + +/** Properties by which mannequins can be ordered. */ +export type MannequinOrderField = + /** Order mannequins why when they were created. */ + | 'CREATED_AT' + /** Order mannequins alphabetically by their source login. */ + | 'LOGIN'; + /** Autogenerated input type of MarkDiscussionCommentAsAnswer */ export type MarkDiscussionCommentAsAnswerInput = { /** A unique identifier for the client performing the mutation. */ @@ -2449,7 +2498,7 @@ export type MergeableState = /** The mergeability of the pull request is still being calculated. */ | 'UNKNOWN'; -/** Represents the different Octoshift migration sources. */ +/** Represents the different GitHub Enterprise Importer (GEI) migration sources. */ export type MigrationSourceType = /** An Azure DevOps migration source. */ | 'AZURE_DEVOPS' @@ -2458,21 +2507,21 @@ export type MigrationSourceType = /** A GitHub Migration API source. */ | 'GITHUB_ARCHIVE'; -/** The Octoshift migration state. */ +/** The GitHub Enterprise Importer (GEI) migration state. */ export type MigrationState = - /** The Octoshift migration has failed. */ + /** The migration has failed. */ | 'FAILED' - /** The Octoshift migration has invalid credentials. */ + /** The migration has invalid credentials. */ | 'FAILED_VALIDATION' - /** The Octoshift migration is in progress. */ + /** The migration is in progress. */ | 'IN_PROGRESS' - /** The Octoshift migration has not started. */ + /** The migration has not started. */ | 'NOT_STARTED' - /** The Octoshift migration needs to have its credentials validated. */ + /** The migration needs to have its credentials validated. */ | 'PENDING_VALIDATION' - /** The Octoshift migration has been queued. */ + /** The migration has been queued. */ | 'QUEUED' - /** The Octoshift migration has succeeded. */ + /** The migration has succeeded. */ | 'SUCCEEDED'; /** Ordering options for milestone connections. */ @@ -3153,6 +3202,14 @@ export type ProjectViewLayout = /** Table layout */ | 'TABLE_LAYOUT'; +/** Autogenerated input type of PublishSponsorsTier */ +export type PublishSponsorsTierInput = { + /** A unique identifier for the client performing the mutation. */ + readonly clientMutationId: InputMaybe; + /** The ID of the draft tier to publish. */ + readonly tierId: Scalars['ID']; +}; + /** Represents available types of methods to use when merging a pull request. */ export type PullRequestMergeMethod = /** Add all commits from the head branch to the base branch with a merge commit. */ @@ -4134,6 +4191,501 @@ export type SponsorsActivityPeriod = /** The previous seven days. */ | 'WEEK'; +/** Represents countries or regions for billing and residence for a GitHub Sponsors profile. */ +export type SponsorsCountryOrRegionCode = + /** Andorra */ + | 'AD' + /** United Arab Emirates */ + | 'AE' + /** Afghanistan */ + | 'AF' + /** Antigua and Barbuda */ + | 'AG' + /** Anguilla */ + | 'AI' + /** Albania */ + | 'AL' + /** Armenia */ + | 'AM' + /** Angola */ + | 'AO' + /** Antarctica */ + | 'AQ' + /** Argentina */ + | 'AR' + /** American Samoa */ + | 'AS' + /** Austria */ + | 'AT' + /** Australia */ + | 'AU' + /** Aruba */ + | 'AW' + /** Åland */ + | 'AX' + /** Azerbaijan */ + | 'AZ' + /** Bosnia and Herzegovina */ + | 'BA' + /** Barbados */ + | 'BB' + /** Bangladesh */ + | 'BD' + /** Belgium */ + | 'BE' + /** Burkina Faso */ + | 'BF' + /** Bulgaria */ + | 'BG' + /** Bahrain */ + | 'BH' + /** Burundi */ + | 'BI' + /** Benin */ + | 'BJ' + /** Saint Barthélemy */ + | 'BL' + /** Bermuda */ + | 'BM' + /** Brunei Darussalam */ + | 'BN' + /** Bolivia */ + | 'BO' + /** Bonaire, Sint Eustatius and Saba */ + | 'BQ' + /** Brazil */ + | 'BR' + /** Bahamas */ + | 'BS' + /** Bhutan */ + | 'BT' + /** Bouvet Island */ + | 'BV' + /** Botswana */ + | 'BW' + /** Belarus */ + | 'BY' + /** Belize */ + | 'BZ' + /** Canada */ + | 'CA' + /** Cocos (Keeling) Islands */ + | 'CC' + /** Congo (Kinshasa) */ + | 'CD' + /** Central African Republic */ + | 'CF' + /** Congo (Brazzaville) */ + | 'CG' + /** Switzerland */ + | 'CH' + /** Côte d'Ivoire */ + | 'CI' + /** Cook Islands */ + | 'CK' + /** Chile */ + | 'CL' + /** Cameroon */ + | 'CM' + /** China */ + | 'CN' + /** Colombia */ + | 'CO' + /** Costa Rica */ + | 'CR' + /** Cape Verde */ + | 'CV' + /** Curaçao */ + | 'CW' + /** Christmas Island */ + | 'CX' + /** Cyprus */ + | 'CY' + /** Czech Republic */ + | 'CZ' + /** Germany */ + | 'DE' + /** Djibouti */ + | 'DJ' + /** Denmark */ + | 'DK' + /** Dominica */ + | 'DM' + /** Dominican Republic */ + | 'DO' + /** Algeria */ + | 'DZ' + /** Ecuador */ + | 'EC' + /** Estonia */ + | 'EE' + /** Egypt */ + | 'EG' + /** Western Sahara */ + | 'EH' + /** Eritrea */ + | 'ER' + /** Spain */ + | 'ES' + /** Ethiopia */ + | 'ET' + /** Finland */ + | 'FI' + /** Fiji */ + | 'FJ' + /** Falkland Islands */ + | 'FK' + /** Micronesia */ + | 'FM' + /** Faroe Islands */ + | 'FO' + /** France */ + | 'FR' + /** Gabon */ + | 'GA' + /** United Kingdom */ + | 'GB' + /** Grenada */ + | 'GD' + /** Georgia */ + | 'GE' + /** French Guiana */ + | 'GF' + /** Guernsey */ + | 'GG' + /** Ghana */ + | 'GH' + /** Gibraltar */ + | 'GI' + /** Greenland */ + | 'GL' + /** Gambia */ + | 'GM' + /** Guinea */ + | 'GN' + /** Guadeloupe */ + | 'GP' + /** Equatorial Guinea */ + | 'GQ' + /** Greece */ + | 'GR' + /** South Georgia and South Sandwich Islands */ + | 'GS' + /** Guatemala */ + | 'GT' + /** Guam */ + | 'GU' + /** Guinea-Bissau */ + | 'GW' + /** Guyana */ + | 'GY' + /** Hong Kong */ + | 'HK' + /** Heard and McDonald Islands */ + | 'HM' + /** Honduras */ + | 'HN' + /** Croatia */ + | 'HR' + /** Haiti */ + | 'HT' + /** Hungary */ + | 'HU' + /** Indonesia */ + | 'ID' + /** Ireland */ + | 'IE' + /** Israel */ + | 'IL' + /** Isle of Man */ + | 'IM' + /** India */ + | 'IN' + /** British Indian Ocean Territory */ + | 'IO' + /** Iraq */ + | 'IQ' + /** Iran */ + | 'IR' + /** Iceland */ + | 'IS' + /** Italy */ + | 'IT' + /** Jersey */ + | 'JE' + /** Jamaica */ + | 'JM' + /** Jordan */ + | 'JO' + /** Japan */ + | 'JP' + /** Kenya */ + | 'KE' + /** Kyrgyzstan */ + | 'KG' + /** Cambodia */ + | 'KH' + /** Kiribati */ + | 'KI' + /** Comoros */ + | 'KM' + /** Saint Kitts and Nevis */ + | 'KN' + /** Korea, South */ + | 'KR' + /** Kuwait */ + | 'KW' + /** Cayman Islands */ + | 'KY' + /** Kazakhstan */ + | 'KZ' + /** Laos */ + | 'LA' + /** Lebanon */ + | 'LB' + /** Saint Lucia */ + | 'LC' + /** Liechtenstein */ + | 'LI' + /** Sri Lanka */ + | 'LK' + /** Liberia */ + | 'LR' + /** Lesotho */ + | 'LS' + /** Lithuania */ + | 'LT' + /** Luxembourg */ + | 'LU' + /** Latvia */ + | 'LV' + /** Libya */ + | 'LY' + /** Morocco */ + | 'MA' + /** Monaco */ + | 'MC' + /** Moldova */ + | 'MD' + /** Montenegro */ + | 'ME' + /** Saint Martin (French part) */ + | 'MF' + /** Madagascar */ + | 'MG' + /** Marshall Islands */ + | 'MH' + /** Macedonia */ + | 'MK' + /** Mali */ + | 'ML' + /** Myanmar */ + | 'MM' + /** Mongolia */ + | 'MN' + /** Macau */ + | 'MO' + /** Northern Mariana Islands */ + | 'MP' + /** Martinique */ + | 'MQ' + /** Mauritania */ + | 'MR' + /** Montserrat */ + | 'MS' + /** Malta */ + | 'MT' + /** Mauritius */ + | 'MU' + /** Maldives */ + | 'MV' + /** Malawi */ + | 'MW' + /** Mexico */ + | 'MX' + /** Malaysia */ + | 'MY' + /** Mozambique */ + | 'MZ' + /** Namibia */ + | 'NA' + /** New Caledonia */ + | 'NC' + /** Niger */ + | 'NE' + /** Norfolk Island */ + | 'NF' + /** Nigeria */ + | 'NG' + /** Nicaragua */ + | 'NI' + /** Netherlands */ + | 'NL' + /** Norway */ + | 'NO' + /** Nepal */ + | 'NP' + /** Nauru */ + | 'NR' + /** Niue */ + | 'NU' + /** New Zealand */ + | 'NZ' + /** Oman */ + | 'OM' + /** Panama */ + | 'PA' + /** Peru */ + | 'PE' + /** French Polynesia */ + | 'PF' + /** Papua New Guinea */ + | 'PG' + /** Philippines */ + | 'PH' + /** Pakistan */ + | 'PK' + /** Poland */ + | 'PL' + /** Saint Pierre and Miquelon */ + | 'PM' + /** Pitcairn */ + | 'PN' + /** Puerto Rico */ + | 'PR' + /** Palestine */ + | 'PS' + /** Portugal */ + | 'PT' + /** Palau */ + | 'PW' + /** Paraguay */ + | 'PY' + /** Qatar */ + | 'QA' + /** Reunion */ + | 'RE' + /** Romania */ + | 'RO' + /** Serbia */ + | 'RS' + /** Russian Federation */ + | 'RU' + /** Rwanda */ + | 'RW' + /** Saudi Arabia */ + | 'SA' + /** Solomon Islands */ + | 'SB' + /** Seychelles */ + | 'SC' + /** Sudan */ + | 'SD' + /** Sweden */ + | 'SE' + /** Singapore */ + | 'SG' + /** Saint Helena */ + | 'SH' + /** Slovenia */ + | 'SI' + /** Svalbard and Jan Mayen Islands */ + | 'SJ' + /** Slovakia */ + | 'SK' + /** Sierra Leone */ + | 'SL' + /** San Marino */ + | 'SM' + /** Senegal */ + | 'SN' + /** Somalia */ + | 'SO' + /** Suriname */ + | 'SR' + /** South Sudan */ + | 'SS' + /** Sao Tome and Principe */ + | 'ST' + /** El Salvador */ + | 'SV' + /** Sint Maarten (Dutch part) */ + | 'SX' + /** Swaziland */ + | 'SZ' + /** Turks and Caicos Islands */ + | 'TC' + /** Chad */ + | 'TD' + /** French Southern Lands */ + | 'TF' + /** Togo */ + | 'TG' + /** Thailand */ + | 'TH' + /** Tajikistan */ + | 'TJ' + /** Tokelau */ + | 'TK' + /** Timor-Leste */ + | 'TL' + /** Turkmenistan */ + | 'TM' + /** Tunisia */ + | 'TN' + /** Tonga */ + | 'TO' + /** Turkey */ + | 'TR' + /** Trinidad and Tobago */ + | 'TT' + /** Tuvalu */ + | 'TV' + /** Taiwan */ + | 'TW' + /** Tanzania */ + | 'TZ' + /** Ukraine */ + | 'UA' + /** Uganda */ + | 'UG' + /** United States Minor Outlying Islands */ + | 'UM' + /** United States of America */ + | 'US' + /** Uruguay */ + | 'UY' + /** Uzbekistan */ + | 'UZ' + /** Vatican City */ + | 'VA' + /** Saint Vincent and the Grenadines */ + | 'VC' + /** Venezuela */ + | 'VE' + /** Virgin Islands, British */ + | 'VG' + /** Virgin Islands, U.S. */ + | 'VI' + /** Vietnam */ + | 'VN' + /** Vanuatu */ + | 'VU' + /** Wallis and Futuna Islands */ + | 'WF' + /** Samoa */ + | 'WS' + /** Yemen */ + | 'YE' + /** Mayotte */ + | 'YT' + /** South Africa */ + | 'ZA' + /** Zambia */ + | 'ZM' + /** Zimbabwe */ + | 'ZW'; + /** The different kinds of goals a GitHub Sponsors member can have. */ export type SponsorsGoalKind = /** The goal is about getting a certain amount in USD from sponsorships each month. */ @@ -4227,19 +4779,19 @@ export type StarOrderField = /** Autogenerated input type of StartRepositoryMigration */ export type StartRepositoryMigrationInput = { - /** The Octoshift migration source access token. */ + /** The migration source access token. */ readonly accessToken: Scalars['String']; /** A unique identifier for the client performing the mutation. */ readonly clientMutationId: InputMaybe; - /** Whether to continue the migration on error */ + /** Whether to continue the migration on error. Defaults to `false`. */ readonly continueOnError: InputMaybe; - /** The signed URL to access the user-uploaded git archive */ + /** The signed URL to access the user-uploaded git archive. */ readonly gitArchiveUrl: InputMaybe; /** The GitHub personal access token of the user importing to the target repository. */ readonly githubPat: InputMaybe; /** Whether to lock the source repository. */ readonly lockSource: InputMaybe; - /** The signed URL to access the user-uploaded metadata archive */ + /** The signed URL to access the user-uploaded metadata archive. */ readonly metadataArchiveUrl: InputMaybe; /** The ID of the organization that will own the imported repository. */ readonly ownerId: Scalars['ID']; @@ -4247,9 +4799,9 @@ export type StartRepositoryMigrationInput = { readonly repositoryName: Scalars['String']; /** Whether to skip migrating releases for the repository. */ readonly skipReleases: InputMaybe; - /** The ID of the Octoshift migration source. */ + /** The ID of the migration source. */ readonly sourceId: Scalars['ID']; - /** The Octoshift migration source repository URL. */ + /** The URL of the source repository. */ readonly sourceRepositoryUrl: Scalars['URI']; /** The visibility of the imported repository. */ readonly targetRepoVisibility: InputMaybe; diff --git a/src/components/maps/Map.tsx b/src/components/maps/Map.tsx index 13becba5..cf757f25 100644 --- a/src/components/maps/Map.tsx +++ b/src/components/maps/Map.tsx @@ -47,6 +47,7 @@ function Wrapper({ isLoaded, children }: { isLoaded: boolean; children: React.Re sx={(theme) => ({ ...(!isLoaded && { visibility: 'hidden' }), position: 'relative', + pointerEvents: 'visible', height: '100%', width: '100%', '& .mapboxgl-map': { diff --git a/src/components/strava/ActivityTypeWithIcon.tsx b/src/components/strava/ActivityTypeWithIcon.tsx index d6d9e534..a77fa730 100644 --- a/src/components/strava/ActivityTypeWithIcon.tsx +++ b/src/components/strava/ActivityTypeWithIcon.tsx @@ -15,8 +15,13 @@ export function ActivityTypeWithIcon() { return null; } - const typeText = activity.type === 'Ride' ? 'Ride' : 'Run'; - const icon = ; + // Split on capital letters to split an enum-like value + const typeText = activity.type.includes('Ride') + ? activity.type.replace(/(?<=[a-z])(?=[A-Z])/, ' ') + : 'Run'; + const icon = ( + + ); return (