diff --git a/next.config.js b/next.config.js index 02a40b6..50a1f01 100644 --- a/next.config.js +++ b/next.config.js @@ -2,9 +2,7 @@ const nextConfig = { reactStrictMode: true, images: { - domains: [ - 'images.pexels.com', - ], + domains: ['images.cdn.unbody.io'], }, } diff --git a/package.json b/package.json index ab995d8..81eb900 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,11 @@ "@types/node": "18.15.11", "@types/react": "18.0.35", "@types/react-dom": "18.0.11", + "axios": "^1.4.0", "eslint": "8.38.0", "eslint-config-next": "13.3.0", + "graphql": "^16.6.0", + "graphql-request": "^6.0.0", "next": "13.3.0", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/src/components/Post/Post.tsx b/src/components/Post/Post.tsx index 7ad990a..08e53b5 100644 --- a/src/components/Post/Post.tsx +++ b/src/components/Post/Post.tsx @@ -4,55 +4,82 @@ import styled from '@emotion/styled' import Image from 'next/image' import { LogosCircleIcon } from '../Icons/LogosCircleIcon' import { useMemo } from 'react' +import { UnbodyImageBlock } from '@/lib/unbody/unbody.types' + +export enum PostImageRatio { + PORTRAIT = 'portrait', + LANDSCAPE = 'landscape', + SQUARE = 'square', +} + +export enum PostClassType { + ARTICLE = 'article', + PODCAST = 'podcast', +} + +export enum PostStyleType { + LSD = 'lsd', + DEFAULT = 'default', +} + +export enum PostSize { + SMALL = 'small', + LARGE = 'large', +} + +export enum PostType { + BODY = 'body', + HEADER = 'header', +} + +export type PostAppearanceProps = { + size?: PostSize + classType?: PostClassType + postType?: PostType + styleType?: PostStyleType + aspectRatio?: PostImageRatio + showImage?: boolean +} + +export type PostDataProps = { + date: string + title: string + description?: string + author?: string + tags?: string[] + coverImage?: UnbodyImageBlock +} + +export const PostImageRatioOptions = { + [PostImageRatio.PORTRAIT]: '9 / 16', + [PostImageRatio.LANDSCAPE]: '16 / 9', + [PostImageRatio.SQUARE]: '1 / 1', +} export type PostProps = CommonProps & React.HTMLAttributes & { - size?: 'small' | 'large' - classType?: 'article' | 'podcast' - postType?: 'body' | 'header' - styleType?: 'lsd' | 'default' - aspectRatio?: 'portrait' | 'landscape' | 'square' - showImage?: boolean - imageUrl?: string - date: Date - title: string - description?: string - author?: string - tags?: string[] + appearance?: PostAppearanceProps + data: PostDataProps } -const getAspectRatio = (aspectRatio: PostProps['aspectRatio']) => { - switch (aspectRatio) { - case 'portrait': - return '9 / 16' - case 'landscape': - return '16 / 9' - case 'square': - return '1 / 1' - default: - return '16 / 9' - } -} - export default function Post({ - size = 'small', - classType = 'article', - postType = 'body', - styleType = 'lsd', - aspectRatio = 'landscape', - showImage = true, - imageUrl, - date, - title, - description, - author, - tags = [], + appearance: { + size = PostSize.SMALL, + classType = PostClassType.ARTICLE, + postType = PostType.BODY, + styleType = PostStyleType.LSD, + aspectRatio = PostImageRatio.LANDSCAPE, + showImage = true, + } = {}, + data: { coverImage, date: dateStr, title, description, author, tags = [] }, ...props }: PostProps) { + const date = new Date(dateStr) + const _title = useMemo( () => ( {title} @@ -63,7 +90,7 @@ export default function Post({ const _description = useMemo( () => - classType == 'article' && ( + classType == PostClassType.ARTICLE && ( {description} @@ -72,24 +99,24 @@ export default function Post({ ) const _thumbnail = useMemo(() => { - if (!showImage || !imageUrl) return null + if (!showImage || !coverImage) return null if (postType === 'body') { return ( - + ) } else { // TBD return ( - + {_title} {_description} ) } - }, [showImage, imageUrl, aspectRatio, postType, _title, _description]) + }, [showImage, coverImage, aspectRatio, postType, _title, _description]) const _header = useMemo(() => { if (postType === 'body') @@ -153,10 +180,12 @@ const Container = styled.div` ` const ThumbnailContainer = styled.div<{ - aspectRatio: PostProps['aspectRatio'] + aspectRatio: PostImageRatio }>` aspect-ratio: ${(p) => - p.aspectRatio ? getAspectRatio(p.aspectRatio) : '16 / 9'}; + p.aspectRatio + ? PostImageRatioOptions[p.aspectRatio] + : PostImageRatioOptions[PostImageRatio.PORTRAIT]}; position: relative; width: 100%; height: 100%; diff --git a/src/components/Post/PostsDemo.tsx b/src/components/Post/PostsDemo.tsx index 042fc0a..2e07130 100644 --- a/src/components/Post/PostsDemo.tsx +++ b/src/components/Post/PostsDemo.tsx @@ -1,123 +1,41 @@ +import { useState } from 'react' import { PostContainer } from '../PostContainer' -import { PostProps } from './Post' +import { PostDataProps, PostProps } from './Post' -const postsData: PostProps[] = [ - { - size: 'small', // 'small' | 'large' - classType: 'article', // 'article' | 'podcast' - postType: 'body', // 'body' | 'header' => TBD - styleType: 'lsd', // 'lsd' | 'default' => WIP - aspectRatio: 'landscape', // 'portrait' | 'landscape' | 'square' - showImage: true, // true | false - imageUrl: - 'https://images.pexels.com/photos/4429335/pexels-photo-4429335.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', - date: new Date(), - title: 'Preventing an Orwellian Future with Privacy-Enhancing Technology', - description: - 'We built a pedal-powered generator and controller, which is practical to use as an energy source and exercise machine in a household -- and which you can integrate into a solar PV ', - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, - { - aspectRatio: 'portrait', // different aspect ratio - portrait - imageUrl: - 'https://images.pexels.com/photos/4992820/pexels-photo-4992820.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', - date: new Date(), - title: 'How to Build a Practical Household Bike Generator', - description: - 'We built a pedal-powered generator and controller, which is practical to use as an energy source and exercise machine in a household -- and which you can integrate into a solar PV', - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, - { - classType: 'podcast', // podcast - imageUrl: - 'https://images.pexels.com/photos/6039256/pexels-photo-6039256.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', - date: new Date(), - title: 'How to Build a Practical Household Bike Generator', - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, - { - showImage: false, // without image - classType: 'article', - date: new Date(), - title: 'How to Build a Practical Household Bike Generator', - description: - 'We built a pedal-powered generator and controller, which is practical to use as an energy source and exercise machine in a household -- and which you can integrate into a solar PV', - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, - { - postType: 'header', // header? TBD - imageUrl: - 'https://images.pexels.com/photos/6039256/pexels-photo-6039256.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', - date: new Date(), - title: 'How to Build a Practical Household Bike Generator', - description: - 'We built a pedal-powered generator and controller, which is practical to use as an energy source and exercise machine in a household -- and which you can integrate into a solar PV', - }, - { - showImage: false, // without image - classType: 'article', - date: new Date(), - title: 'Satoshi breaks their silence: Inside the mind of the OG anon', - description: - "Bitcoin's creator reveals their feelings on privacy, CBDCs and their favorite NFT collection in an unprecedented interview with Acid.info", - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, - { - aspectRatio: 'square', // square - imageUrl: - 'https://images.pexels.com/photos/6477673/pexels-photo-6477673.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', - date: new Date(), - title: 'How to Build a Practical Household Bike Generator', - description: - 'We built a pedal-powered generator and controller, which is practical to use as an energy source and exercise machine in a household -- and which you can integrate into a solar PV', - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, - { - // featured - imageUrl: - 'https://images.pexels.com/photos/6227715/pexels-photo-6227715.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2', - date: new Date(), - title: 'How to Build a Practical Household Bike Generator', - description: - 'We built a pedal-powered generator and controller, which is practical to use as an energy source and exercise machine in a household -- and which you can integrate into a solar PV', - author: 'Jason Freeman', - tags: ['Privacy', 'Security', 'Liberty'], - }, -] +type Props = { + posts: PostDataProps[] + featuredPost: PostDataProps +} + +const PostsDemo = (props: Props) => { + const [posts, setPosts] = useState(props.posts) -const PostsDemo = () => { return (
{/* For Demo purposes only. Use inline CSS and styled components temporarily */} - + {/*@TODO @jinho, wht PostContainer should recive an array of postData instead of only One?*/} - - - - + {posts.length > 0 ? ( + ({ + appearance: {}, + data: post, + }))} + /> + ) : ( +
+

No Posts found!

+
+ )}
) } diff --git a/src/lib/.placeholder b/src/lib/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/src/lib/unbody/client.class.ts b/src/lib/unbody/client.class.ts new file mode 100644 index 0000000..6b5c3d4 --- /dev/null +++ b/src/lib/unbody/client.class.ts @@ -0,0 +1,26 @@ +import axios, { Axios } from 'axios' +import { UnbodyExploreArgs } from './unbody.types' + +export class UnbodyClient { + public client: Axios + static UNBODY_GRAPHQL_ENDPOINT = 'https://graphql.unbody.io' + + constructor(apiKey: string | undefined, projectId: string | undefined) { + if (!apiKey) throw new Error('Unbody client: apiKey is required') + if (!projectId) throw new Error('Unbody client: projectId is required') + + this.client = axios.create({ + baseURL: UnbodyClient.UNBODY_GRAPHQL_ENDPOINT, + headers: { + Authorization: apiKey, + 'X-Project-id': projectId, + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + }) + } + async request(query: string): Promise { + const { data } = await this.client.post('', { query }) + return data + } +} diff --git a/src/lib/unbody/unbody-content.types.ts b/src/lib/unbody/unbody-content.types.ts new file mode 100644 index 0000000..56b71ea --- /dev/null +++ b/src/lib/unbody/unbody-content.types.ts @@ -0,0 +1,237 @@ +export namespace UnbodyGraphQl { + export interface Get { + Get: T + } + + export namespace Additional { + interface AdditionalAnswer { + endPosition: number + hasAnswer: boolean + property: string + result: string + startPosition: number + } + interface AdditionalnumbererpretationSource { + concept: string + occurrence: number + weight: number + } + + interface Additionalnumbererpretation { + source: [AdditionalnumbererpretationSource] + } + + interface AdditionalFeatureProjection { + vector: [number] + } + + interface AdditionalNearestNeighborsNeighbor { + concept: string + distance: number + } + + interface AdditionalNearestNeighbors { + neighbors: [AdditionalNearestNeighborsNeighbor] + } + + interface AdditionalSemanticPath { + concept: string + distanceToNext: number + distanceToPrevious: number + distanceToQuery: number + distanceToResult: number + } + + interface AdditionalClassification { + basedOn: [string] + classifiedFields: [string] + completed: string + id: string + scope: [string] + } + + export interface AdditionalProps { + certainty: number + creationTimeUnix: string + distance: number + explainScore: string + id: string + lastUpdateTimeUnix: string + score: string + vector: [number] + + interpretation: Additionalnumbererpretation + nearestNeighbors: AdditionalNearestNeighbors + semanticPath: AdditionalSemanticPath + answer: AdditionalAnswer + classification: AdditionalClassification + featureProjection: AdditionalFeatureProjection + } + } + + export interface BaseObject { + _additional: Additional.AdditionalProps + } + + export interface BaseObjectWithRef extends BaseObject { + document: Array + } + + export interface Beacon { + beacon: string + } + + export namespace Fragments { + export interface TocItem {} + export interface FootnoteItem {} + } + + export interface ImageBlock + extends BaseObjectWithRef { + alt: string + createdAt: string + ext: string + height: number + mimeType: string + modifiedAt: string + order: number + originalName: string + path: string[] + pathstring: string + remoteId: string + size: number + sourceId: string + url: string + width: number + } + + export interface TextBlock extends BaseObjectWithRef { + footnotes: string | Array + html: string + order: number + remoteId: string + sourceId: string + tagName: string + text: string + } + + export interface AudioFile + extends BaseObjectWithRef { + duration: number + ext: string + mimeType: string + order: number + originalName: string + remoteId: string + size: number + sourceId: string + url: string + } + + export interface GoogleDoc extends BaseObject { + blocks: Array + createdAt: string + html: string + mimeType: string + modifiedAt: string + originalName: string + path: string[] + pathstring: string + remoteId: string + size: number + sourceId: string + subtitle: string + summary: string + tags: string[] + text: string + title: string + toc: string | Array + } + + export interface GoogleCalendarEvent extends BaseObject { + createdAt: string + creatorDisplayName: string + creatorEmail: string + creatorId: string + creatorSelf: boolean + descriptionHtml: string + descriptionText: string + end: string + htmlLink: string + location: string + organizerDisplayName: string + organizerEmail: string + organizerId: string + organizerSelf: boolean + recurrence: [string] + remoteId: string + sequence: number + sourceId: string + start: string + status: string + summary: string + title: string + updatedAt: string + + attachments: Array + } + + export namespace Explore { + interface ExploreNearObjectInpObj { + beacon?: string + certainty?: number + distance?: number + id?: string + } + + interface Txt2VecC11yExploreMoveToMovementObjectsInpObj { + id?: string + beacon?: string + } + + interface Txt2VecC11yExploreMoveTo { + concepts?: string[] + objects?: Txt2VecC11yExploreMoveToMovementObjectsInpObj[] + force?: number + } + + interface Txt2VecC11yExploreMoveAwayFromMovementObjectsInpObj { + id?: string + beacon?: string + } + + interface Txt2VecC11yExploreMoveAwayFrom { + concepts?: string[] + objects?: Txt2VecC11yExploreMoveAwayFromMovementObjectsInpObj[] + force?: number + } + + interface Txt2VecC11yExploreNearTextInpObj { + moveTo?: Txt2VecC11yExploreMoveTo + certainty?: number + distance?: number + moveAwayFrom?: Txt2VecC11yExploreMoveAwayFrom + concepts?: string[] + } + + interface ExploreNearVectorInpObj { + distance?: number + vector?: number[] + certainty?: number + } + + interface QnATransformersExploreAskInpObj { + question: string + properties?: string[] + } + + export interface ExploreArgs { + nearObject?: ExploreNearObjectInpObj + nearText?: Txt2VecC11yExploreNearTextInpObj + ask?: QnATransformersExploreAskInpObj + offset?: number + limit?: number + nearVector?: ExploreNearVectorInpObj + } + } +} diff --git a/src/lib/unbody/unbody.types.ts b/src/lib/unbody/unbody.types.ts new file mode 100644 index 0000000..a741596 --- /dev/null +++ b/src/lib/unbody/unbody.types.ts @@ -0,0 +1,30 @@ +import { UnbodyGraphQl } from './unbody-content.types' + +export type UnbodyGoogleDoc = UnbodyGraphQl.GoogleDoc +export type UnbodyGoogleCalendarEvent = UnbodyGraphQl.GoogleCalendarEvent +export type UnbodyTextBlock = UnbodyGraphQl.TextBlock +export type UnbodyImageBlock = UnbodyGraphQl.ImageBlock +export type UnbodyAudio = UnbodyGraphQl.AudioFile +export type UnbodyExploreArgs = UnbodyGraphQl.Explore.ExploreArgs + +export type UnbodyGraphQlResponse = { + data: { + Get: T + } +} + +export type UnbodyGraphQlResponseGoogleDoc = UnbodyGraphQlResponse<{ + GoogleDoc: UnbodyGoogleDoc[] +}> + +export type UnbodyGraphQlResponseGoogleCalendarEvent = UnbodyGraphQlResponse<{ + GoogleCalendarEvent: UnbodyGoogleCalendarEvent[] +}> + +export type UnbodyGraphQlResponseTextBlock = UnbodyGraphQlResponse<{ + TextBlock: UnbodyTextBlock[] +}> + +export type UnbodyGraphQlResponseImageBlock = UnbodyGraphQlResponse<{ + ImageBlock: UnbodyImageBlock[] +}> diff --git a/src/lib/unbody/unbody.utils.ts b/src/lib/unbody/unbody.utils.ts new file mode 100644 index 0000000..9a7ef71 --- /dev/null +++ b/src/lib/unbody/unbody.utils.ts @@ -0,0 +1,27 @@ +import { UnbodyExploreArgs } from './unbody.types' + +export const pareseExploreArgs = (args: UnbodyExploreArgs = {}): string => { + const parse = (obj: any): string | number => { + if (typeof obj === 'number') { + return obj + } + + if (Array.isArray(obj)) { + const props = obj.map((value) => `${parse(value)}`).join(',') + return `[${props}]` + } + + if (typeof obj === 'object') { + const props = Object.keys(obj) + .map((key) => `${key}:${parse(obj[key])}`) + .join(',') + return `{${props}}` + } + + return JSON.stringify(obj) + } + + const p = parse(args) + //remove the first and last curly braces + return typeof p === 'string' ? p.substring(1, p.length - 1) : p + '' +} diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts index f8bcc7e..7fff2c3 100644 --- a/src/pages/api/hello.ts +++ b/src/pages/api/hello.ts @@ -1,13 +1,15 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import unbody, { getHomepagePosts } from '@/services/unbody.service' import type { NextApiRequest, NextApiResponse } from 'next' -type Data = { - name: string -} - -export default function handler( +export default async function handler( req: NextApiRequest, - res: NextApiResponse + res: NextApiResponse, ) { - res.status(200).json({ name: 'John Doe' }) + try { + const data = await getHomepagePosts() + res.status(200).json(data) + } catch (e: any) { + console.log(e) + res.status(e.response.statusCode || 500).send(e.message) + } } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 0a3fb38..e70673d 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,9 +1,45 @@ +import { PostDataProps } from '@/components/Post/Post' import PostsDemo from '@/components/Post/PostsDemo' +import { UnbodyGoogleDoc, UnbodyImageBlock } from '@/lib/unbody/unbody.types' +import { getHomepagePosts } from '@/services/unbody.service' +import { GetStaticProps } from 'next' -export default function Home() { +type Props = { + posts: PostDataProps[] + error: string | null +} + +export default function Home({ posts }: Props) { return ( <> - + ) } + +export const getStaticProps = async () => { + let posts: Partial[] = [] + let error = null + + try { + posts = await getHomepagePosts() + } catch (e) { + error = JSON.stringify(e) + } + + return { + props: { + posts: posts.map((post) => ({ + date: post.modifiedAt, + title: post.title, + description: post.summary, + author: 'Jinho', + tags: post.tags, + ...(post.blocks && post.blocks!.length > 0 + ? { coverImage: post.blocks![0] as UnbodyImageBlock } + : {}), + })), + error, + }, + } +} diff --git a/src/queries/getPosts.ts b/src/queries/getPosts.ts new file mode 100644 index 0000000..33cc161 --- /dev/null +++ b/src/queries/getPosts.ts @@ -0,0 +1,25 @@ +import { gql } from 'graphql-request' + +import { GetGoogleDocQuery, GetQuery } from '.' +import { pareseExploreArgs } from '@/lib/unbody/unbody.utils' +import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types' + +const defaultArgs: UnbodyExploreArgs = { + limit: 10, + nearText: { concepts: ['home'] }, +} + +export const getHomePagePostsQuery = (args: UnbodyExploreArgs = defaultArgs) => + GetGoogleDocQuery(args)(` + title + summary + tags + createdAt + modifiedAt + blocks{ + ...on ImageBlock{ + url + alt + } + } + `) diff --git a/src/queries/index.ts b/src/queries/index.ts new file mode 100644 index 0000000..bd22e31 --- /dev/null +++ b/src/queries/index.ts @@ -0,0 +1,7 @@ +import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types' +import { pareseExploreArgs } from '@/lib/unbody/unbody.utils' + +export const GetQuery = (q: string) => `query { Get{ ${q} } }` + +export const GetGoogleDocQuery = (args: UnbodyExploreArgs) => (q: string) => + GetQuery(`GoogleDoc(${pareseExploreArgs(args)}){ ${q} }`) diff --git a/src/services/unbody.service.ts b/src/services/unbody.service.ts new file mode 100644 index 0000000..bd7938f --- /dev/null +++ b/src/services/unbody.service.ts @@ -0,0 +1,26 @@ +import { UnbodyClient } from '@/lib/unbody/client.class' +import { + UnbodyGoogleDoc, + UnbodyGraphQlResponseGoogleDoc, +} from '@/lib/unbody/unbody.types' +import { getHomePagePostsQuery } from '@/queries/getPosts' + +const { UNBODY_API_KEY, UNBODY_LPE_PROJECT_ID } = process.env + +const unbody = new UnbodyClient( + UNBODY_API_KEY as string, + UNBODY_LPE_PROJECT_ID as string, +) + +type HomepagePost = Pick< + UnbodyGoogleDoc, + 'title' | 'summary' | 'tags' | 'modifiedAt' | 'subtitle' | 'blocks' +> + +export const getHomepagePosts = (): Promise => { + return unbody + .request(getHomePagePostsQuery()) + .then(({ data }) => data.Get.GoogleDoc) +} + +export default unbody diff --git a/yarn.lock b/yarn.lock index f8fe374..286355c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -203,6 +203,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.38.0.tgz#73a8a0d8aa8a8e6fe270431c5e72ae91b5337892" integrity sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g== +"@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@hookstate/core@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@hookstate/core/-/core-4.0.1.tgz#6744380e96ce13fe3488c926c1cbae93bbea0ff6" @@ -578,6 +583,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -588,6 +598,15 @@ axe-core@^4.6.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.6.3.tgz#fc0db6fdb65cc7a80ccf85286d91d64ababa3ece" integrity sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg== +axios@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axobject-query@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -645,9 +664,9 @@ callsites@^3.0.0: integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== caniuse-lite@^1.0.30001406: - version "1.0.30001478" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz#0ef8a1cf8b16be47a0f9fc4ecfc952232724b32a" - integrity sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw== + version "1.0.30001482" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001482.tgz#8b3fad73dc35b2674a5c96df2d4f9f1c561435de" + integrity sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ== chalk@5.2.0: version "5.2.0" @@ -738,6 +757,13 @@ colorette@^2.0.19: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" @@ -771,6 +797,13 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -860,6 +893,11 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1317,6 +1355,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -1324,6 +1367,15 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1478,6 +1530,19 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphql-request@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.0.0.tgz#9c8b6a0c341f289e049936d03cc9205300faae1c" + integrity sha512-2BmHTuglonjZvmNVw6ZzCfFlW/qkIPds0f+Qdi/Lvjsl3whJg2uvHmSvHnLWhUTEw6zcxPYAHiZoPvSVKOZ7Jw== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + cross-fetch "^3.1.5" + +graphql@^16.6.0: + version "16.6.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" + integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -1975,6 +2040,18 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -2053,6 +2130,13 @@ next@13.3.0: "@next/swc-win32-ia32-msvc" "13.3.0" "@next/swc-win32-x64-msvc" "13.3.0" +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -2286,6 +2370,11 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" @@ -2781,6 +2870,11 @@ toggle-selection@^1.0.6: resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-easing@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" @@ -2866,6 +2960,19 @@ use-sync-external-store@^1.2.0: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"