From d55a2f09c5424c6966604e85e3f4e74d1fc96035 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Wed, 17 Jan 2024 15:01:54 +0100 Subject: [PATCH] feat(core): Leverage `gql.tada` for typings (#119) * implement gql.tada * address issues * make the changes * make tada work * leverage tada * fixes * changesets * add basic docs aroudn types * add some alias * more doc additions * doc additions * Fix imports, remove duplicate imports * fixes for comment json --------- Co-authored-by: Max Stoiber --- .changeset/cyan-ligers-reflect.md | 5 + .changeset/perfect-glasses-kiss.md | 5 + examples/ecommerce/package.json | 2 +- examples/ecommerce/schema.graphql | 2 +- examples/spacex/fuse/graphql.ts | 18 +- examples/spacex/package.json | 2 +- examples/standalone/package.json | 3 +- examples/standalone/src/App.tsx | 27 +- .../src/components/LaunchDetails.tsx | 31 +- .../standalone/src/components/LaunchItem.tsx | 9 +- .../standalone/src/components/LaunchSite.tsx | 32 +- .../standalone/src/components/Location.tsx | 8 +- .../standalone/src/components/PageNumbers.tsx | 2 +- .../standalone/src/fuse/fragment-masking.ts | 85 --- examples/standalone/src/fuse/gql.ts | 86 --- examples/standalone/src/fuse/graphql.ts | 558 ---------------- examples/standalone/src/fuse/index.ts | 5 +- examples/standalone/src/fuse/introspection.ts | 621 ++++++++++++++++++ examples/standalone/src/fuse/tada.ts | 11 + examples/standalone/tsconfig.json | 4 +- packages/core/package.json | 2 +- packages/core/src/cli.ts | 39 +- packages/core/src/next/plugin.ts | 77 ++- packages/core/src/utils/gql-tada.ts | 67 ++ packages/create-fuse-app/package.json | 1 + packages/create-fuse-app/src/index.ts | 23 +- pnpm-lock.yaml | 396 +++++++---- website/src/pages/docs/client/_meta.json | 1 + .../src/pages/docs/client/best-practices.mdx | 21 +- website/src/pages/docs/client/index.mdx | 2 +- .../pages/docs/client/javascript/angular.mdx | 12 +- .../pages/docs/client/javascript/nextjs.mdx | 12 +- .../pages/docs/client/javascript/react.mdx | 15 +- .../src/pages/docs/client/javascript/vue.mdx | 12 +- website/src/pages/docs/client/types.mdx | 38 ++ 35 files changed, 1239 insertions(+), 995 deletions(-) create mode 100644 .changeset/cyan-ligers-reflect.md create mode 100644 .changeset/perfect-glasses-kiss.md delete mode 100644 examples/standalone/src/fuse/fragment-masking.ts delete mode 100644 examples/standalone/src/fuse/gql.ts delete mode 100644 examples/standalone/src/fuse/graphql.ts create mode 100644 examples/standalone/src/fuse/introspection.ts create mode 100644 examples/standalone/src/fuse/tada.ts create mode 100644 packages/core/src/utils/gql-tada.ts create mode 100644 website/src/pages/docs/client/types.mdx diff --git a/.changeset/cyan-ligers-reflect.md b/.changeset/cyan-ligers-reflect.md new file mode 100644 index 00000000..7738ed04 --- /dev/null +++ b/.changeset/cyan-ligers-reflect.md @@ -0,0 +1,5 @@ +--- +'fuse': minor +--- + +Use `gql.tada` when the user has no prior codegen process diff --git a/.changeset/perfect-glasses-kiss.md b/.changeset/perfect-glasses-kiss.md new file mode 100644 index 00000000..e0a0d6a5 --- /dev/null +++ b/.changeset/perfect-glasses-kiss.md @@ -0,0 +1,5 @@ +--- +'create-fuse-app': minor +--- + +Default to using `gql.tada` diff --git a/examples/ecommerce/package.json b/examples/ecommerce/package.json index 041ea97f..2abe5c1e 100644 --- a/examples/ecommerce/package.json +++ b/examples/ecommerce/package.json @@ -17,7 +17,7 @@ "react-dom": "^18" }, "devDependencies": { - "@0no-co/graphqlsp": "^0.11.0", + "@0no-co/graphqlsp": "^1.0.2", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/examples/ecommerce/schema.graphql b/examples/ecommerce/schema.graphql index ad546648..9d6c66e9 100644 --- a/examples/ecommerce/schema.graphql +++ b/examples/ecommerce/schema.graphql @@ -47,4 +47,4 @@ type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! product(id: ID!): Product -} +} \ No newline at end of file diff --git a/examples/spacex/fuse/graphql.ts b/examples/spacex/fuse/graphql.ts index 3fba0e13..158b805e 100644 --- a/examples/spacex/fuse/graphql.ts +++ b/examples/spacex/fuse/graphql.ts @@ -105,7 +105,7 @@ export type QuerySiteArgs = { export type QueryLaunchesList = { __typename: 'QueryLaunchesList' - nodes: Array + nodes: Array> totalCount?: Maybe } @@ -139,9 +139,10 @@ export type Launches_SsrQuery = { launches: { __typename: 'QueryLaunchesList' nodes: Array< - { __typename: 'Launch'; id: string } & { - ' $fragmentRefs'?: { LaunchFieldsFragment: LaunchFieldsFragment } - } + | ({ __typename: 'Launch'; id: string } & { + ' $fragmentRefs'?: { LaunchFieldsFragment: LaunchFieldsFragment } + }) + | null > } & { ' $fragmentRefs'?: { TotalCountFieldsFragment: TotalCountFieldsFragment } @@ -158,9 +159,10 @@ export type Launches_RscQuery = { launches: { __typename: 'QueryLaunchesList' nodes: Array< - { __typename: 'Launch'; id: string } & { - ' $fragmentRefs'?: { LaunchFieldsFragment: LaunchFieldsFragment } - } + | ({ __typename: 'Launch'; id: string } & { + ' $fragmentRefs'?: { LaunchFieldsFragment: LaunchFieldsFragment } + }) + | null > } & { ' $fragmentRefs'?: { TotalCountFieldsFragment: TotalCountFieldsFragment } @@ -251,7 +253,7 @@ export type PageLaunchesQuery = { launches: { __typename: 'QueryLaunchesList' totalCount?: number | null - nodes: Array<{ __typename: 'Launch'; id: string; name: string }> + nodes: Array<{ __typename: 'Launch'; id: string; name: string } | null> } } diff --git a/examples/spacex/package.json b/examples/spacex/package.json index aeeee5c9..b4e35e38 100644 --- a/examples/spacex/package.json +++ b/examples/spacex/package.json @@ -17,7 +17,7 @@ "react-dom": "^18" }, "devDependencies": { - "@0no-co/graphqlsp": "^0.11.0", + "@0no-co/graphqlsp": "^1.0.2", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/examples/standalone/package.json b/examples/standalone/package.json index 2a3f39f8..517ff0d8 100644 --- a/examples/standalone/package.json +++ b/examples/standalone/package.json @@ -8,11 +8,12 @@ "build": "vite build && fuse build" }, "dependencies": { + "gql.tada": "1.0.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { - "@0no-co/graphqlsp": "^0.11.0", + "@0no-co/graphqlsp": "^1.0.2", "@graphql-typed-document-node/core": "^3.2.0", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", diff --git a/examples/standalone/src/App.tsx b/examples/standalone/src/App.tsx index d856dca8..a5bd22d9 100644 --- a/examples/standalone/src/App.tsx +++ b/examples/standalone/src/App.tsx @@ -1,8 +1,8 @@ import * as React from 'react' import { graphql, useQuery } from './fuse' -import { LaunchItem } from './components/LaunchItem' -import { PageNumbers } from './components/PageNumbers' +import { LaunchItem, LaunchFields } from './components/LaunchItem' +import { PageNumbers, TotalCountFields } from './components/PageNumbers' import { LaunchDetails } from './components/LaunchDetails' export default function Page() { @@ -23,17 +23,20 @@ export default function Page() { ) } -const LaunchesQuery = graphql(` - query Launches_SSR($limit: Int, $offset: Int) { - launches(limit: $limit, offset: $offset) { - nodes { - id - ...LaunchFields +const LaunchesQuery = graphql( + ` + query Launches_SSR($limit: Int, $offset: Int) { + launches(limit: $limit, offset: $offset) { + nodes { + id + ...LaunchFields + } + ...TotalCountFields } - ...TotalCountFields } - } -`) + `, + [LaunchFields, TotalCountFields], +) function Launches() { const [selected, setSelected] = React.useState(null) @@ -51,7 +54,7 @@ function Launches() { (node) => node && ( setSelected(node.id)} + select={() => setSelected('' + node.id)} key={node.id} launch={node} /> diff --git a/examples/standalone/src/components/LaunchDetails.tsx b/examples/standalone/src/components/LaunchDetails.tsx index b72fd23d..3224ff2f 100644 --- a/examples/standalone/src/components/LaunchDetails.tsx +++ b/examples/standalone/src/components/LaunchDetails.tsx @@ -1,21 +1,26 @@ import { graphql, useQuery } from '../fuse' -import { LaunchSite } from './LaunchSite' +import { LaunchSite, LaunchSiteFields } from './LaunchSite' -const LaunchDetailsQuery = graphql(` - query LaunchDetails($id: ID!) { - node(id: $id) { - ... on Launch { - id - name - details - launchDate - site { - ...LaunchSiteFields +const LaunchDetailsQuery = graphql( + ` + query LaunchDetails($id: ID!) { + node(id: $id) { + __typename + ... on Launch { + id + name + details + launchDate + __typename + site { + ...LaunchSiteFields + } } } } - } -`) + `, + [LaunchSiteFields], +) export const LaunchDetails = (props: { id: string; deselect: () => void }) => { const [result] = useQuery({ diff --git a/examples/standalone/src/components/LaunchItem.tsx b/examples/standalone/src/components/LaunchItem.tsx index 7537ff90..feb99bfe 100644 --- a/examples/standalone/src/components/LaunchItem.tsx +++ b/examples/standalone/src/components/LaunchItem.tsx @@ -1,7 +1,7 @@ -import { FragmentType, graphql, useFragment } from '../fuse' +import { FragmentOf, graphql, readFragment } from '../fuse' import styles from './LaunchItem.module.css' -const LaunchFields = graphql(` +export const LaunchFields = graphql(` fragment LaunchFields on Launch { name launchDate @@ -10,11 +10,10 @@ const LaunchFields = graphql(` `) export const LaunchItem = (props: { - launch: FragmentType + launch: FragmentOf select: () => void }) => { - const node = useFragment(LaunchFields, props.launch) - + const node = readFragment(LaunchFields, props.launch) return (
  • {node.name} diff --git a/examples/standalone/src/components/LaunchSite.tsx b/examples/standalone/src/components/LaunchSite.tsx index b0b78954..2969b296 100644 --- a/examples/standalone/src/components/LaunchSite.tsx +++ b/examples/standalone/src/components/LaunchSite.tsx @@ -1,23 +1,25 @@ -import { FragmentType, graphql, useFragment } from '../fuse' -import { Location } from './Location' +import { FragmentOf, graphql, readFragment } from '../fuse' +import { Location, SiteLocationFields } from './Location' -const LaunchSiteFields = graphql(` - fragment LaunchSiteFields on Site { - id - name - details - status - location { - ...SiteLocationFields +export const LaunchSiteFields = graphql( + ` + fragment LaunchSiteFields on Site { + id + name + details + status + location { + ...SiteLocationFields + } } - } -`) + `, + [SiteLocationFields], +) -// TODO: make pretty export const LaunchSite = (props: { - site: FragmentType + site: FragmentOf }) => { - const result = useFragment(LaunchSiteFields, props.site) + const result = readFragment(LaunchSiteFields, props.site) return (
    diff --git a/examples/standalone/src/components/Location.tsx b/examples/standalone/src/components/Location.tsx index 51593f1f..dfa1f7db 100644 --- a/examples/standalone/src/components/Location.tsx +++ b/examples/standalone/src/components/Location.tsx @@ -1,6 +1,6 @@ -import { FragmentType, graphql, useFragment } from '../fuse' +import { FragmentOf, graphql, readFragment } from '../fuse' -const SiteLocationFields = graphql(` +export const SiteLocationFields = graphql(` fragment SiteLocationFields on Location { latitude longitude @@ -10,9 +10,9 @@ const SiteLocationFields = graphql(` `) export const Location = (props: { - location: FragmentType + location: FragmentOf }) => { - const result = useFragment(SiteLocationFields, props.location) + const result = readFragment(SiteLocationFields, props.location) return (
    diff --git a/examples/standalone/src/components/PageNumbers.tsx b/examples/standalone/src/components/PageNumbers.tsx index 1537fb90..a7907768 100644 --- a/examples/standalone/src/components/PageNumbers.tsx +++ b/examples/standalone/src/components/PageNumbers.tsx @@ -2,7 +2,7 @@ import { FragmentType, graphql, useFragment } from '../fuse' import styles from './PageNumbers.module.css' -const TotalCountFields = graphql(` +export const TotalCountFields = graphql(` fragment TotalCountFields on QueryLaunchesList { totalCount } diff --git a/examples/standalone/src/fuse/fragment-masking.ts b/examples/standalone/src/fuse/fragment-masking.ts deleted file mode 100644 index 355c9d1a..00000000 --- a/examples/standalone/src/fuse/fragment-masking.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { - ResultOf, - DocumentTypeDecoration, - TypedDocumentNode, -} from '@graphql-typed-document-node/core' -import { FragmentDefinitionNode } from 'graphql' -import { Incremental } from './graphql' - -export type FragmentType< - TDocumentType extends DocumentTypeDecoration, -> = TDocumentType extends DocumentTypeDecoration - ? [TType] extends [{ ' $fragmentName'?: infer TKey }] - ? TKey extends string - ? { ' $fragmentRefs'?: { [key in TKey]: TType } } - : never - : never - : never - -// return non-nullable if `fragmentType` is non-nullable -export function useFragment( - _documentNode: DocumentTypeDecoration, - fragmentType: FragmentType>, -): TType -// return nullable if `fragmentType` is nullable -export function useFragment( - _documentNode: DocumentTypeDecoration, - fragmentType: - | FragmentType> - | null - | undefined, -): TType | null | undefined -// return array of non-nullable if `fragmentType` is array of non-nullable -export function useFragment( - _documentNode: DocumentTypeDecoration, - fragmentType: ReadonlyArray>>, -): ReadonlyArray -// return array of nullable if `fragmentType` is array of nullable -export function useFragment( - _documentNode: DocumentTypeDecoration, - fragmentType: - | ReadonlyArray>> - | null - | undefined, -): ReadonlyArray | null | undefined -export function useFragment( - _documentNode: DocumentTypeDecoration, - fragmentType: - | FragmentType> - | ReadonlyArray>> - | null - | undefined, -): TType | ReadonlyArray | null | undefined { - return fragmentType as any -} - -export function makeFragmentData< - F extends DocumentTypeDecoration, - FT extends ResultOf, ->(data: FT, _fragment: F): FragmentType { - return data as FragmentType -} -export function isFragmentReady( - queryNode: DocumentTypeDecoration, - fragmentNode: TypedDocumentNode, - data: - | FragmentType, any>> - | null - | undefined, -): data is FragmentType { - const deferredFields = ( - queryNode as { - __meta__?: { deferredFields: Record } - } - ).__meta__?.deferredFields - - if (!deferredFields) return true - - const fragDef = fragmentNode.definitions[0] as - | FragmentDefinitionNode - | undefined - const fragName = fragDef?.name?.value - - const fields = (fragName && deferredFields[fragName]) || [] - return fields.length > 0 && fields.every((field) => data && field in data) -} diff --git a/examples/standalone/src/fuse/gql.ts b/examples/standalone/src/fuse/gql.ts deleted file mode 100644 index b7a59dc4..00000000 --- a/examples/standalone/src/fuse/gql.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* eslint-disable */ -import * as types from './graphql' -import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core' - -/** - * Map of all GraphQL operations in the project. - * - * This map has several performance disadvantages: - * 1. It is not tree-shakeable, so it will include all operations in the project. - * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. - * 3. It does not support dead code elimination, so it will add unused operations. - * - * Therefore it is highly recommended to use the babel or swc plugin for production. - */ -const documents = { - '\n query Launches_SSR($limit: Int, $offset: Int) {\n launches(limit: $limit, offset: $offset) {\n nodes {\n id\n ...LaunchFields\n }\n ...TotalCountFields\n }\n }\n': - types.Launches_SsrDocument, - '\n query LaunchDetails($id: ID!) {\n node(id: $id) {\n ... on Launch {\n id\n name\n details\n launchDate\n site {\n ...LaunchSiteFields\n }\n }\n }\n }\n': - types.LaunchDetailsDocument, - '\n fragment LaunchFields on Launch {\n name\n launchDate\n image\n }\n': - types.LaunchFieldsFragmentDoc, - '\n fragment LaunchSiteFields on Site {\n id\n name\n details\n status\n location {\n ...SiteLocationFields\n }\n }\n': - types.LaunchSiteFieldsFragmentDoc, - '\n fragment SiteLocationFields on Location {\n latitude\n longitude\n name\n region\n }\n': - types.SiteLocationFieldsFragmentDoc, - '\n fragment TotalCountFields on QueryLaunchesList {\n totalCount\n }\n': - types.TotalCountFieldsFragmentDoc, -} - -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - * - * - * @example - * ```ts - * const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`); - * ``` - * - * The query argument is unknown! - * Please regenerate the types. - */ -export function graphql(source: string): unknown - -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: '\n query Launches_SSR($limit: Int, $offset: Int) {\n launches(limit: $limit, offset: $offset) {\n nodes {\n id\n ...LaunchFields\n }\n ...TotalCountFields\n }\n }\n', -): (typeof documents)['\n query Launches_SSR($limit: Int, $offset: Int) {\n launches(limit: $limit, offset: $offset) {\n nodes {\n id\n ...LaunchFields\n }\n ...TotalCountFields\n }\n }\n'] -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: '\n query LaunchDetails($id: ID!) {\n node(id: $id) {\n ... on Launch {\n id\n name\n details\n launchDate\n site {\n ...LaunchSiteFields\n }\n }\n }\n }\n', -): (typeof documents)['\n query LaunchDetails($id: ID!) {\n node(id: $id) {\n ... on Launch {\n id\n name\n details\n launchDate\n site {\n ...LaunchSiteFields\n }\n }\n }\n }\n'] -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: '\n fragment LaunchFields on Launch {\n name\n launchDate\n image\n }\n', -): (typeof documents)['\n fragment LaunchFields on Launch {\n name\n launchDate\n image\n }\n'] -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: '\n fragment LaunchSiteFields on Site {\n id\n name\n details\n status\n location {\n ...SiteLocationFields\n }\n }\n', -): (typeof documents)['\n fragment LaunchSiteFields on Site {\n id\n name\n details\n status\n location {\n ...SiteLocationFields\n }\n }\n'] -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: '\n fragment SiteLocationFields on Location {\n latitude\n longitude\n name\n region\n }\n', -): (typeof documents)['\n fragment SiteLocationFields on Location {\n latitude\n longitude\n name\n region\n }\n'] -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: '\n fragment TotalCountFields on QueryLaunchesList {\n totalCount\n }\n', -): (typeof documents)['\n fragment TotalCountFields on QueryLaunchesList {\n totalCount\n }\n'] - -export function graphql(source: string) { - return (documents as any)[source] ?? {} -} - -export type DocumentType> = - TDocumentNode extends DocumentNode ? TType : never diff --git a/examples/standalone/src/fuse/graphql.ts b/examples/standalone/src/fuse/graphql.ts deleted file mode 100644 index bb2ea2c9..00000000 --- a/examples/standalone/src/fuse/graphql.ts +++ /dev/null @@ -1,558 +0,0 @@ -/* eslint-disable */ -import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core' -export type Maybe = T | null -export type InputMaybe = Maybe -export type Exact = { - [K in keyof T]: T[K] -} -export type MakeOptional = Omit & { - [SubKey in K]?: Maybe -} -export type MakeMaybe = Omit & { - [SubKey in K]: Maybe -} -export type MakeEmpty< - T extends { [key: string]: unknown }, - K extends keyof T, -> = { [_ in K]?: never } -export type Incremental = - | T - | { - [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never - } -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string } - String: { input: string; output: string } - Boolean: { input: boolean; output: boolean } - Int: { input: number; output: number } - Float: { input: number; output: number } - /** A date string, such as 2007-12-03, compliant with the `full-date` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ - Date: { input: any; output: any } - /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ - JSON: { input: any; output: any } -} - -export type Launch = Node & { - __typename: 'Launch' - details?: Maybe - id: Scalars['ID']['output'] - image: Scalars['String']['output'] - launchDate: Scalars['String']['output'] - name: Scalars['String']['output'] - rocket: Rocket - site: Site -} - -export type Location = { - __typename: 'Location' - coordinates?: Maybe> - latitude?: Maybe - longitude?: Maybe - name?: Maybe - region?: Maybe -} - -export type Mutation = { - __typename: 'Mutation' - _version: Scalars['String']['output'] - sayHello?: Maybe -} - -export type MutationSayHelloArgs = { - name?: InputMaybe -} - -export type Node = { - id: Scalars['ID']['output'] -} - -export type Query = { - __typename: 'Query' - _version: Scalars['String']['output'] - launch?: Maybe - launches: QueryLaunchesList - node?: Maybe - nodes: Array> - rocket?: Maybe - site?: Maybe -} - -export type QueryLaunchArgs = { - id: Scalars['ID']['input'] -} - -export type QueryLaunchesArgs = { - limit?: InputMaybe - offset?: InputMaybe -} - -export type QueryNodeArgs = { - id: Scalars['ID']['input'] -} - -export type QueryNodesArgs = { - ids: Array -} - -export type QueryRocketArgs = { - id: Scalars['ID']['input'] -} - -export type QuerySiteArgs = { - id: Scalars['ID']['input'] -} - -export type QueryLaunchesList = { - __typename: 'QueryLaunchesList' - nodes: Array> - totalCount?: Maybe -} - -export type Rocket = Node & { - __typename: 'Rocket' - company?: Maybe - cost?: Maybe - country?: Maybe - description?: Maybe - id: Scalars['ID']['output'] -} - -export type Site = Node & { - __typename: 'Site' - details?: Maybe - id: Scalars['ID']['output'] - location?: Maybe - name?: Maybe - status?: Maybe -} - -export type SiteStatus = 'ACTIVE' | 'INACTIVE' | 'UNKNOWN' - -export type Launches_SsrQueryVariables = Exact<{ - limit?: InputMaybe - offset?: InputMaybe -}> - -export type Launches_SsrQuery = { - __typename: 'Query' - launches: { - __typename: 'QueryLaunchesList' - nodes: Array< - | ({ __typename: 'Launch'; id: string } & { - ' $fragmentRefs'?: { LaunchFieldsFragment: LaunchFieldsFragment } - }) - | null - > - } & { - ' $fragmentRefs'?: { TotalCountFieldsFragment: TotalCountFieldsFragment } - } -} - -export type LaunchDetailsQueryVariables = Exact<{ - id: Scalars['ID']['input'] -}> - -export type LaunchDetailsQuery = { - __typename: 'Query' - node?: - | { - __typename: 'Launch' - id: string - name: string - details?: string | null - launchDate: string - site: { __typename: 'Site' } & { - ' $fragmentRefs'?: { - LaunchSiteFieldsFragment: LaunchSiteFieldsFragment - } - } - } - | { __typename: 'Rocket' } - | { __typename: 'Site' } - | null -} - -export type LaunchFieldsFragment = { - __typename: 'Launch' - name: string - launchDate: string - image: string -} & { ' $fragmentName'?: 'LaunchFieldsFragment' } - -export type LaunchSiteFieldsFragment = { - __typename: 'Site' - id: string - name?: string | null - details?: string | null - status?: SiteStatus | null - location?: - | ({ __typename: 'Location' } & { - ' $fragmentRefs'?: { - SiteLocationFieldsFragment: SiteLocationFieldsFragment - } - }) - | null -} & { ' $fragmentName'?: 'LaunchSiteFieldsFragment' } - -export type SiteLocationFieldsFragment = { - __typename: 'Location' - latitude?: number | null - longitude?: number | null - name?: string | null - region?: string | null -} & { ' $fragmentName'?: 'SiteLocationFieldsFragment' } - -export type TotalCountFieldsFragment = { - __typename: 'QueryLaunchesList' - totalCount?: number | null -} & { ' $fragmentName'?: 'TotalCountFieldsFragment' } - -export const LaunchFieldsFragmentDoc = { - kind: 'Document', - definitions: [ - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'LaunchFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Launch' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'launchDate' } }, - { kind: 'Field', name: { kind: 'Name', value: 'image' } }, - ], - }, - }, - ], -} as unknown as DocumentNode -export const SiteLocationFieldsFragmentDoc = { - kind: 'Document', - definitions: [ - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'SiteLocationFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Location' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'latitude' } }, - { kind: 'Field', name: { kind: 'Name', value: 'longitude' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'region' } }, - ], - }, - }, - ], -} as unknown as DocumentNode -export const LaunchSiteFieldsFragmentDoc = { - kind: 'Document', - definitions: [ - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'LaunchSiteFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Site' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'details' } }, - { kind: 'Field', name: { kind: 'Name', value: 'status' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'location' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'FragmentSpread', - name: { kind: 'Name', value: 'SiteLocationFields' }, - }, - ], - }, - }, - ], - }, - }, - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'SiteLocationFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Location' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'latitude' } }, - { kind: 'Field', name: { kind: 'Name', value: 'longitude' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'region' } }, - ], - }, - }, - ], -} as unknown as DocumentNode -export const TotalCountFieldsFragmentDoc = { - kind: 'Document', - definitions: [ - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'TotalCountFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'QueryLaunchesList' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'totalCount' } }, - ], - }, - }, - ], -} as unknown as DocumentNode -export const Launches_SsrDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'Launches_SSR' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'limit' }, - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } }, - }, - { - kind: 'VariableDefinition', - variable: { - kind: 'Variable', - name: { kind: 'Name', value: 'offset' }, - }, - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'launches' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'limit' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'limit' }, - }, - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'offset' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'offset' }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'nodes' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { - kind: 'FragmentSpread', - name: { kind: 'Name', value: 'LaunchFields' }, - }, - ], - }, - }, - { - kind: 'FragmentSpread', - name: { kind: 'Name', value: 'TotalCountFields' }, - }, - ], - }, - }, - ], - }, - }, - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'LaunchFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Launch' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'launchDate' } }, - { kind: 'Field', name: { kind: 'Name', value: 'image' } }, - ], - }, - }, - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'TotalCountFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'QueryLaunchesList' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'totalCount' } }, - ], - }, - }, - ], -} as unknown as DocumentNode -export const LaunchDetailsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'LaunchDetails' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'id' }, - value: { - kind: 'Variable', - name: { kind: 'Name', value: 'id' }, - }, - }, - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'InlineFragment', - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Launch' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'details' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'launchDate' }, - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'site' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'FragmentSpread', - name: { kind: 'Name', value: 'LaunchSiteFields' }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'SiteLocationFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Location' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'latitude' } }, - { kind: 'Field', name: { kind: 'Name', value: 'longitude' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'region' } }, - ], - }, - }, - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'LaunchSiteFields' }, - typeCondition: { - kind: 'NamedType', - name: { kind: 'Name', value: 'Site' }, - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'details' } }, - { kind: 'Field', name: { kind: 'Name', value: 'status' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'location' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'FragmentSpread', - name: { kind: 'Name', value: 'SiteLocationFields' }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode diff --git a/examples/standalone/src/fuse/index.ts b/examples/standalone/src/fuse/index.ts index 9f999c8a..b440a13e 100644 --- a/examples/standalone/src/fuse/index.ts +++ b/examples/standalone/src/fuse/index.ts @@ -1,3 +1,4 @@ -export * from './fragment-masking' -export * from './gql' +// This is a generated file! + +export * from './tada' export * from 'fuse/client' diff --git a/examples/standalone/src/fuse/introspection.ts b/examples/standalone/src/fuse/introspection.ts new file mode 100644 index 00000000..fa6213fa --- /dev/null +++ b/examples/standalone/src/fuse/introspection.ts @@ -0,0 +1,621 @@ +/** An IntrospectionQuery representation of your schema. + * + * @remarks + * This is an introspection of your schema saved as a file by GraphQLSP. + * You may import it to create a `graphql()` tag function with `gql.tada` + * by importing it and passing it to `initGraphQLTada<>()`. + * + * @example + * ``` + * import { initGraphQLTada } from 'gql.tada'; + * import type { introspection } from './introspection'; + * + * export const graphql = initGraphQLTada<{ + * introspection: typeof introspection; + * scalars: { + * DateTime: string; + * Json: any; + * }; + * }>(); + * ``` + */ +const introspection = { + __schema: { + queryType: { + name: 'Query', + }, + mutationType: { + name: 'Mutation', + }, + subscriptionType: null, + types: [ + { + kind: 'SCALAR', + name: 'Date', + }, + { + kind: 'SCALAR', + name: 'JSON', + }, + { + kind: 'OBJECT', + name: 'Launch', + fields: [ + { + name: 'details', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + args: [], + }, + { + name: 'image', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + }, + args: [], + }, + { + name: 'launchDate', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + }, + args: [], + }, + { + name: 'name', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + }, + args: [], + }, + { + name: 'rocket', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'OBJECT', + name: 'Rocket', + ofType: null, + }, + }, + args: [], + }, + { + name: 'site', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'OBJECT', + name: 'Site', + ofType: null, + }, + }, + args: [], + }, + ], + interfaces: [ + { + kind: 'INTERFACE', + name: 'Node', + }, + ], + }, + { + kind: 'SCALAR', + name: 'String', + }, + { + kind: 'SCALAR', + name: 'ID', + }, + { + kind: 'OBJECT', + name: 'Location', + fields: [ + { + name: 'coordinates', + type: { + kind: 'LIST', + ofType: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'Float', + ofType: null, + }, + }, + }, + args: [], + }, + { + name: 'latitude', + type: { + kind: 'SCALAR', + name: 'Float', + ofType: null, + }, + args: [], + }, + { + name: 'longitude', + type: { + kind: 'SCALAR', + name: 'Float', + ofType: null, + }, + args: [], + }, + { + name: 'name', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'region', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + ], + interfaces: [], + }, + { + kind: 'SCALAR', + name: 'Float', + }, + { + kind: 'OBJECT', + name: 'Mutation', + fields: [ + { + name: '_version', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + }, + args: [], + }, + { + name: 'sayHello', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [ + { + name: 'name', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + }, + ], + }, + ], + interfaces: [], + }, + { + kind: 'INTERFACE', + name: 'Node', + fields: [ + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + args: [], + }, + ], + interfaces: [], + possibleTypes: [ + { + kind: 'OBJECT', + name: 'Launch', + }, + { + kind: 'OBJECT', + name: 'Rocket', + }, + { + kind: 'OBJECT', + name: 'Site', + }, + ], + }, + { + kind: 'OBJECT', + name: 'Query', + fields: [ + { + name: '_version', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + }, + args: [], + }, + { + name: 'launch', + type: { + kind: 'OBJECT', + name: 'Launch', + ofType: null, + }, + args: [ + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + }, + ], + }, + { + name: 'launches', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'OBJECT', + name: 'QueryLaunchesList', + ofType: null, + }, + }, + args: [ + { + name: 'limit', + type: { + kind: 'SCALAR', + name: 'Int', + ofType: null, + }, + }, + { + name: 'offset', + type: { + kind: 'SCALAR', + name: 'Int', + ofType: null, + }, + }, + ], + }, + { + name: 'node', + type: { + kind: 'INTERFACE', + name: 'Node', + ofType: null, + }, + args: [ + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + }, + ], + }, + { + name: 'nodes', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'LIST', + ofType: { + kind: 'INTERFACE', + name: 'Node', + ofType: null, + }, + }, + }, + args: [ + { + name: 'ids', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'LIST', + ofType: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + }, + }, + }, + ], + }, + { + name: 'rocket', + type: { + kind: 'OBJECT', + name: 'Rocket', + ofType: null, + }, + args: [ + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + }, + ], + }, + { + name: 'site', + type: { + kind: 'OBJECT', + name: 'Site', + ofType: null, + }, + args: [ + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + }, + ], + }, + ], + interfaces: [], + }, + { + kind: 'SCALAR', + name: 'Int', + }, + { + kind: 'OBJECT', + name: 'QueryLaunchesList', + fields: [ + { + name: 'nodes', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'LIST', + ofType: { + kind: 'OBJECT', + name: 'Launch', + ofType: null, + }, + }, + }, + args: [], + }, + { + name: 'totalCount', + type: { + kind: 'SCALAR', + name: 'Int', + ofType: null, + }, + args: [], + }, + ], + interfaces: [], + }, + { + kind: 'OBJECT', + name: 'Rocket', + fields: [ + { + name: 'company', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'cost', + type: { + kind: 'SCALAR', + name: 'Int', + ofType: null, + }, + args: [], + }, + { + name: 'country', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'description', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + args: [], + }, + ], + interfaces: [ + { + kind: 'INTERFACE', + name: 'Node', + }, + ], + }, + { + kind: 'OBJECT', + name: 'Site', + fields: [ + { + name: 'details', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'id', + type: { + kind: 'NON_NULL', + ofType: { + kind: 'SCALAR', + name: 'ID', + ofType: null, + }, + }, + args: [], + }, + { + name: 'location', + type: { + kind: 'OBJECT', + name: 'Location', + ofType: null, + }, + args: [], + }, + { + name: 'name', + type: { + kind: 'SCALAR', + name: 'String', + ofType: null, + }, + args: [], + }, + { + name: 'status', + type: { + kind: 'ENUM', + name: 'SiteStatus', + ofType: null, + }, + args: [], + }, + ], + interfaces: [ + { + kind: 'INTERFACE', + name: 'Node', + }, + ], + }, + { + kind: 'ENUM', + name: 'SiteStatus', + enumValues: [ + { + name: 'ACTIVE', + }, + { + name: 'INACTIVE', + }, + { + name: 'UNKNOWN', + }, + ], + }, + { + kind: 'SCALAR', + name: 'Boolean', + }, + { + kind: 'SCALAR', + name: 'Any', + }, + ], + directives: [], + }, +} as const + +export { introspection } diff --git a/examples/standalone/src/fuse/tada.ts b/examples/standalone/src/fuse/tada.ts new file mode 100644 index 00000000..e0cbbac7 --- /dev/null +++ b/examples/standalone/src/fuse/tada.ts @@ -0,0 +1,11 @@ +import { initGraphQLTada } from 'gql.tada' +import type { introspection } from './introspection' + +export const graphql = initGraphQLTada<{ + introspection: typeof introspection +}>() + +export type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada' +export type { FragmentOf as FragmentType } from 'gql.tada' +export { readFragment } from 'gql.tada' +export { readFragment as useFragment } from 'gql.tada' diff --git a/examples/standalone/tsconfig.json b/examples/standalone/tsconfig.json index 76f6d763..68a8a17f 100644 --- a/examples/standalone/tsconfig.json +++ b/examples/standalone/tsconfig.json @@ -17,9 +17,7 @@ { "name": "@0no-co/graphqlsp", "schema": "./schema.graphql", - "disableTypegen": true, - "templateIsCallExpression": true, - "template": "graphql" + "tadaOutputLocation": "./src/fuse/introspection.ts" } ], "paths": { diff --git a/packages/core/package.json b/packages/core/package.json index 1cdc4ff1..25c528eb 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -82,7 +82,7 @@ "@graphql-typed-document-node/core": "^3.2.0", "@graphql-yoga/plugin-defer-stream": "^3.0.0", "@graphql-yoga/plugin-disable-introspection": "^2.0.0", - "@parcel/watcher": "^2.3.0", + "@parcel/watcher": "^2.4.0", "@pothos/core": "^3.38.0", "@pothos/plugin-dataloader": "^3.17.1", "@pothos/plugin-relay": "^3.44.0", diff --git a/packages/core/src/cli.ts b/packages/core/src/cli.ts index 8f3e841a..30c1e948 100644 --- a/packages/core/src/cli.ts +++ b/packages/core/src/cli.ts @@ -1,16 +1,18 @@ #!/usr/bin/env node import sade from 'sade' import path from 'path' +import { existsSync } from 'fs' import fs, { writeFile } from 'fs/promises' import { createServer, build } from 'vite' import { VitePluginNode } from 'vite-plugin-node' import { generate, CodegenContext } from '@graphql-codegen/cli' import { DateTimeResolver, JSONResolver } from 'graphql-scalars' -import { existsSync } from 'fs' + +import { isUsingGraphQLTada, tadaGqlContents } from './utils/gql-tada' const prog = sade('fuse') -prog.version('0.0.0') +prog.version(process.env.npm_package_version ?? '0.0.0') prog .command('build') @@ -89,9 +91,24 @@ prog console.log('Server build output created in ./build') } + const baseDirectory = process.cwd() if (opts.client) { - await boostrapCodegen(opts.schema, false) + if (!(await isUsingGraphQLTada(baseDirectory))) { + await boostrapCodegen(opts.schema, false) + } else { + const hasSrcDir = existsSync(path.resolve(baseDirectory, 'src')) + const base = hasSrcDir + ? path.resolve(baseDirectory, 'src') + : baseDirectory + await Promise.allSettled([ + fs.writeFile( + path.resolve(base, 'fuse/index.ts'), + `// This is a generated file!\n\nexport * from './tada';\nexport * from 'fuse/client';\n`, + ), + fs.writeFile(path.resolve(base, 'fuse/tada.ts'), tadaGqlContents), + ]) + } } }) .command('dev') @@ -163,7 +180,21 @@ prog } if (opts.client) { - await boostrapCodegen(opts.schema, true) + if (!(await isUsingGraphQLTada(baseDirectory))) { + await boostrapCodegen(opts.schema, true) + } else { + const hasSrcDir = existsSync(path.resolve(baseDirectory, 'src')) + const base = hasSrcDir + ? path.resolve(baseDirectory, 'src') + : baseDirectory + await Promise.allSettled([ + fs.writeFile( + path.resolve(base, 'fuse/index.ts'), + `// This is a generated file!\n\nexport * from './tada';\nexport * from 'fuse/client';\n`, + ), + fs.writeFile(path.resolve(base, 'fuse/tada.ts'), tadaGqlContents), + ]) + } } }) diff --git a/packages/core/src/next/plugin.ts b/packages/core/src/next/plugin.ts index 55290f7d..e5dcf658 100644 --- a/packages/core/src/next/plugin.ts +++ b/packages/core/src/next/plugin.ts @@ -1,9 +1,10 @@ +import path from 'path' import { generate, CodegenContext } from '@graphql-codegen/cli' import { existsSync, promises as fs } from 'fs' import { resolve } from 'path' import { DateTimeResolver, JSONResolver } from 'graphql-scalars' -// Add when enabling persisted operations -// import { addTypenameSelectionDocumentTransform } from '@graphql-codegen/client-preset'; + +import { isUsingGraphQLTada, tadaGqlContents } from '../utils/gql-tada' interface Options { port?: number @@ -14,15 +15,19 @@ let isRunningCodegen = false export function nextFusePlugin(options: Options = {}) { return (nextConfig: any = {}): any => { if (process.env.NODE_ENV === 'development' && !isRunningCodegen) { - boostrapFuse() - try { - isRunningCodegen = true - setTimeout(() => { - try { - boostrapCodegen(options.port || 3000, options.path || 'fuse') - } catch (e) {} - }, 1000) - } catch (e) {} + isRunningCodegen = true + isUsingGraphQLTada(process.cwd()).then((isUsing) => { + boostrapFuse(isUsing) + try { + setTimeout(() => { + try { + if (!isUsing) { + boostrapCodegen(options.port || 3000, options.path || 'fuse') + } + } catch (e) {} + }, 1000) + } catch (e) {} + }) } const newNextConfig = Object.assign({}, nextConfig, { @@ -51,31 +56,44 @@ export function nextFusePlugin(options: Options = {}) { } } -async function boostrapFuse() { +async function boostrapFuse(isUsingTada: boolean) { let baseDirectory = process.cwd() try { const hasSrcDir = existsSync(resolve(baseDirectory, 'src')) if (hasSrcDir) { baseDirectory = resolve(baseDirectory, 'src') } + if (!existsSync(baseDirectory + '/fuse')) { await fs.mkdir(baseDirectory + '/fuse') } - await Promise.allSettled([ - fs.writeFile( - baseDirectory + '/fuse/server.ts', - `// This is a generated file!\n\nexport * from 'fuse/next/server'\n`, - ), - fs.writeFile( - baseDirectory + '/fuse/client.ts', - `// This is a generated file!\n\nexport * from 'fuse/next/client'\n`, - ), - fs.writeFile( - baseDirectory + '/fuse/pages.ts', - `// This is a generated file!\n\nexport * from 'fuse/next/pages'\n`, - ), - ]) + await Promise.allSettled( + [ + fs.writeFile( + baseDirectory + '/fuse/server.ts', + `// This is a generated file!\n\nexport * from 'fuse/next/server'\n`, + ), + fs.writeFile( + baseDirectory + '/fuse/client.ts', + `// This is a generated file!\n\nexport * from 'fuse/next/client'\n`, + ), + fs.writeFile( + baseDirectory + '/fuse/pages.ts', + `// This is a generated file!\n\nexport * from 'fuse/next/pages'\n`, + ), + isUsingTada && + fs.writeFile( + path.resolve(baseDirectory, 'fuse/index.ts'), + `// This is a generated file!\n\nexport * from './tada'\n`, + ), + isUsingTada && + fs.writeFile( + path.resolve(baseDirectory, 'fuse/tada.ts'), + tadaGqlContents, + ), + ].filter(Boolean), + ) } catch (e) {} } @@ -95,15 +113,14 @@ async function boostrapCodegen(port: number, path: string) { watch: [ baseDirectory + '/**/*.{ts,tsx}', baseDirectory + '/types/**/*.ts', + '!./{node_modules,.next,.git}/**/*', ], + documents: ['./**/!(node_modules|.next|.git)/*.{ts,tsx}'], schema: `http://localhost:${port}/api/${path}`, + debug: true, generates: { [baseDirectory + '/fuse/']: { - documents: ['./**/*.{ts,tsx}', '!./{node_modules,.next,.git}/**/*'], preset: 'client', - // presetConfig: { - // persistedDocuments: true, - // }, config: { scalars: { ID: { diff --git a/packages/core/src/utils/gql-tada.ts b/packages/core/src/utils/gql-tada.ts new file mode 100644 index 00000000..16492bad --- /dev/null +++ b/packages/core/src/utils/gql-tada.ts @@ -0,0 +1,67 @@ +import { promises as fs } from 'fs' +import path from 'path' + +export async function isUsingGraphQLTada(cwd: string): Promise { + const [pkgJson, tsConfig] = await Promise.allSettled([ + fs.readFile(path.resolve(cwd, 'package.json'), 'utf-8'), + fs.readFile(path.resolve(cwd, 'tsconfig.json'), 'utf-8'), + ]) + + if (pkgJson.status === 'rejected' || tsConfig.status === 'rejected') { + return false + } + + try { + const parsed = JSON.parse(pkgJson.value as string) + if ( + !parsed.dependencies['gql.tada'] && + !parsed.devDependencies['gql.tada'] + ) { + return false + } + + if ( + !parsed.dependencies['@0no-co/graphqlsp'] && + !parsed.devDependencies['@0no-co/graphqlsp'] + ) { + return false + } + } catch (e) { + return false + } + + try { + const parsed = JSON.parse(tsConfig.value as string) + const lspPlugin = parsed.compilerOptions.plugins.find( + (plugin: any) => plugin.name === '@0no-co/graphqlsp', + ) + if (!lspPlugin) { + return false + } + + if (!lspPlugin.tadaOutputLocation) { + return false + } + } catch (e) { + // unparseable, this can happen due to comments in tsconfig + return ( + tsConfig.value.includes('@0no-co/graphqlsp') && + tsConfig.value.includes('tadaOutputLocation') + ) + } + + return true +} + +export const tadaGqlContents = `import { initGraphQLTada } from 'gql.tada'; +import type { introspection } from './introspection'; + +export const graphql = initGraphQLTada<{ + introspection: typeof introspection; +}>(); + +export type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada'; +export type { FragmentOf as FragmentType } from 'gql.tada'; +export { readFragment } from 'gql.tada'; +export { readFragment as useFragment } from 'gql.tada'; +` diff --git a/packages/create-fuse-app/package.json b/packages/create-fuse-app/package.json index 9ab31e02..0c26734b 100644 --- a/packages/create-fuse-app/package.json +++ b/packages/create-fuse-app/package.json @@ -27,6 +27,7 @@ "dependencies": { "@babel/core": "^7.23.5", "@clack/prompts": "^0.7.0", + "comment-json": "^4.2.3", "execa": "^8.0.1", "kolorist": "^1.8.0" }, diff --git a/packages/create-fuse-app/src/index.ts b/packages/create-fuse-app/src/index.ts index 5c98d708..b23efb7b 100644 --- a/packages/create-fuse-app/src/index.ts +++ b/packages/create-fuse-app/src/index.ts @@ -8,6 +8,7 @@ import { type PackageJson, TsConfigJson } from 'type-fest' import rewriteNext from './rewrite-next' import { getPkgManager } from './get-package-manager' import { install } from './install-package' +import { parse, stringify } from 'comment-json' const s = prompts.spinner() @@ -17,7 +18,7 @@ async function createFuseApp() { prompts.intro(kl.trueColor(219, 254, 1)('Fuse - Your new API')) s.start('Installing fuse...') - await install(packageManager, 'prod', ['fuse']) + await install(packageManager, 'prod', ['fuse', 'gql.tada', 'graphql']) await install(packageManager, 'dev', [ '@0no-co/graphqlsp', '@graphql-typed-document-node/core', @@ -60,7 +61,7 @@ async function createFuseApp() { initialTypeSnippet, ) await writeGraphQLSP(targetDir) - await updateTSConfig(targetDir) + await updateTSConfig(targetDir, existsSync(resolve(targetDir, 'src'))) s.stop('Created Base files!') prompts.outro( @@ -178,7 +179,7 @@ async function createFuseApp() { } await writeGraphQLSP(targetDir) - await updateTSConfig(targetDir) + await updateTSConfig(targetDir, existsSync(resolve(targetDir, 'src'))) s.stop(kl.green('Added Fuse plugin to next config!')) prompts.outro( @@ -219,13 +220,13 @@ const writeGraphQLSP = async (targetDir: string) => { } } -const updateTSConfig = async (targetDir: string) => { +const updateTSConfig = async (targetDir: string, hasSrcDir: boolean) => { if (existsSync(resolve(targetDir, 'tsconfig.json'))) { const tsConfigFile = await fs.readFile( resolve(targetDir, 'tsconfig.json'), 'utf-8', ) - const tsConfig = JSON.parse(tsConfigFile) as TsConfigJson + const tsConfig = parse(tsConfigFile) as TsConfigJson if ( !tsConfig.compilerOptions?.plugins?.find( (plugin) => plugin.name === '@0no-co/graphqlsp', @@ -233,6 +234,10 @@ const updateTSConfig = async (targetDir: string) => { ) { const updatedTsConfig = { ...tsConfig, + include: [ + ...(tsConfig.include || []), + hasSrcDir ? './src/fuse/introspection.ts' : './fuse/introspection.ts', + ], compilerOptions: { ...tsConfig.compilerOptions, plugins: [ @@ -240,16 +245,16 @@ const updateTSConfig = async (targetDir: string) => { { name: '@0no-co/graphqlsp', schema: './schema.graphql', - disableTypegen: true, - templateIsCallExpression: true, - template: 'graphql', + tadaOutputLocation: hasSrcDir + ? './src/fuse/introspection.ts' + : './fuse/introspection.ts', }, ], }, } await fs.writeFile( resolve(targetDir, 'tsconfig.json'), - JSON.stringify(updatedTsConfig, undefined, 2), + stringify(updatedTsConfig, undefined, 2), 'utf-8', ) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f455f037..e323523a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,7 +34,7 @@ importers: version: 16.8.1 next: specifier: 14.0.3 - version: 14.0.3(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0) + version: 14.0.3(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)(sass@1.69.5) react: specifier: ^18 version: 18.2.0 @@ -43,8 +43,8 @@ importers: version: 18.2.0(react@18.2.0) devDependencies: '@0no-co/graphqlsp': - specifier: ^0.11.0 - version: 0.11.0(graphql@16.8.1) + specifier: ^1.0.2 + version: 1.0.2 '@types/node': specifier: ^20 version: 20.8.10 @@ -74,7 +74,7 @@ importers: version: 16.8.1 next: specifier: 14.0.3 - version: 14.0.3(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0) + version: 14.0.3(@babel/core@7.23.3)(react-dom@18.2.0)(react@18.2.0)(sass@1.69.5) react: specifier: ^18 version: 18.2.0 @@ -83,8 +83,8 @@ importers: version: 18.2.0(react@18.2.0) devDependencies: '@0no-co/graphqlsp': - specifier: ^0.11.0 - version: 0.11.0(graphql@16.8.1) + specifier: ^1.0.2 + version: 1.0.2 '@types/node': specifier: ^20 version: 20.8.10 @@ -106,6 +106,9 @@ importers: examples/standalone: dependencies: + gql.tada: + specifier: 1.0.1 + version: 1.0.1(graphql@16.8.1) react: specifier: ^18.2.0 version: 18.2.0 @@ -114,8 +117,8 @@ importers: version: 18.2.0(react@18.2.0) devDependencies: '@0no-co/graphqlsp': - specifier: ^0.11.0 - version: 0.11.0(graphql@16.8.1) + specifier: ^1.0.2 + version: 1.0.2 '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.8.1) @@ -148,7 +151,7 @@ importers: version: 2.1.0 '@graphql-codegen/cli': specifier: ^5.0.0 - version: 5.0.0(@parcel/watcher@2.3.0)(@types/node@20.8.10)(graphql@16.8.1)(typescript@5.2.2) + version: 5.0.0(@parcel/watcher@2.4.0)(@types/node@20.8.10)(graphql@16.8.1)(typescript@5.2.2) '@graphql-codegen/client-preset': specifier: ^4.1.0 version: 4.1.0(graphql@16.8.1) @@ -162,8 +165,8 @@ importers: specifier: ^2.0.0 version: 2.0.0(graphql-yoga@5.0.0)(graphql@16.8.1) '@parcel/watcher': - specifier: ^2.3.0 - version: 2.3.0 + specifier: ^2.4.0 + version: 2.4.0 '@pothos/core': specifier: ^3.38.0 version: 3.38.0(graphql@16.8.1) @@ -258,6 +261,9 @@ importers: '@clack/prompts': specifier: ^0.7.0 version: 0.7.0 + comment-json: + specifier: ^4.2.3 + version: 4.2.3 execa: specifier: ^8.0.1 version: 8.0.1 @@ -379,23 +385,12 @@ packages: graphql: 16.8.1 dev: false - /@0no-co/graphqlsp@0.11.0(graphql@16.8.1): - resolution: {integrity: sha512-47e7CbHNUKLYf08Yg49Tw0cASRCfsZeTyCvvHr9i4C1waLnkMFOh34IWwoIn6uoVAFPm9+2dKeQB8/u4b+q92g==} + /@0no-co/graphqlsp@1.0.2: + resolution: {integrity: sha512-fUrhTBWiSCvpGERwJep498Ws+wWzo7XmsUg+OWE1EgtDazfAMcNMyzWi+13T5aEPyY7Khl1YRupINh7XWTjFNw==} dependencies: - '@graphql-codegen/add': 5.0.0(graphql@16.8.1) - '@graphql-codegen/core': 4.0.0(graphql@16.8.1) - '@graphql-codegen/typed-document-node': 5.0.1(graphql@16.8.1) - '@graphql-codegen/typescript': 4.0.1(graphql@16.8.1) - '@graphql-codegen/typescript-operations': 4.0.1(graphql@16.8.1) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) - '@sindresorhus/fnv1a': 2.0.1 - graphql-language-service: 5.2.0(graphql@16.8.1) - lru-cache: 10.0.1 node-fetch: 2.7.0 transitivePeerDependencies: - encoding - - graphql - - supports-color dev: true /@aashutoshrathi/word-wrap@1.2.6: @@ -437,6 +432,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: false /@ardatan/sync-fetch@0.0.1: resolution: {integrity: sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==} @@ -611,6 +607,7 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 semver: 6.3.1 + dev: false /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.3): resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} @@ -738,6 +735,7 @@ packages: '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-member-expression-to-functions': 7.23.0 '@babel/helper-optimise-call-expression': 7.22.5 + dev: false /@babel/helper-simple-access@7.22.5: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} @@ -880,6 +878,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.23.5): resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} @@ -894,6 +893,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.5) '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.5) + dev: false /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.3): resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} @@ -929,6 +929,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.3): resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} @@ -966,6 +967,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} @@ -1033,6 +1035,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.3): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} @@ -1077,6 +1080,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.3): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} @@ -1155,6 +1159,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-async-generator-functions@7.23.4(@babel/core@7.23.3): resolution: {integrity: sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==} @@ -1199,6 +1204,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.23.3): resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==} @@ -1218,6 +1224,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==} @@ -1276,6 +1283,7 @@ packages: '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5) '@babel/helper-split-export-declaration': 7.22.6 globals: 11.12.0 + dev: false /@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} @@ -1297,6 +1305,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/template': 7.22.15 + dev: false /@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} @@ -1316,6 +1325,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==} @@ -1380,6 +1390,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-flow': 7.23.3(@babel/core@7.23.5) + dev: false /@babel/plugin-transform-for-of@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==} @@ -1399,6 +1410,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-function-name@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} @@ -1422,6 +1434,7 @@ packages: '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-function-name': 7.23.0 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.23.3): resolution: {integrity: sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==} @@ -1452,6 +1465,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.23.3): resolution: {integrity: sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==} @@ -1482,6 +1496,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==} @@ -1516,6 +1531,7 @@ packages: '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 + dev: false /@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==} @@ -1618,6 +1634,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5) + dev: false /@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.23.3): resolution: {integrity: sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==} @@ -1660,6 +1677,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==} @@ -1703,6 +1721,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-react-constant-elements@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-zP0QKq/p6O42OL94udMgSfKXyse4RyJ0JqbQ34zDAONWjyrEsghYEyTSK5FIpmXmCpB55SHokL1cRRKHv8L2Qw==} @@ -1732,6 +1751,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.23.3): resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} @@ -1789,6 +1809,7 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5) '@babel/types': 7.23.3 + dev: false /@babel/plugin-transform-react-pure-annotations@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==} @@ -1840,6 +1861,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-spread@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} @@ -1861,6 +1883,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: false /@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==} @@ -1890,6 +1913,7 @@ packages: dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 + dev: false /@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==} @@ -3032,8 +3056,9 @@ packages: '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) graphql: 16.8.1 tslib: 2.5.3 + dev: false - /@graphql-codegen/cli@5.0.0(@parcel/watcher@2.3.0)(@types/node@20.8.10)(graphql@16.8.1)(typescript@5.2.2): + /@graphql-codegen/cli@5.0.0(@parcel/watcher@2.4.0)(@types/node@20.8.10)(graphql@16.8.1)(typescript@5.2.2): resolution: {integrity: sha512-A7J7+be/a6e+/ul2KI5sfJlpoqeqwX8EzktaKCeduyVKgOLA6W5t+NUGf6QumBDXU8PEOqXk3o3F+RAwCWOiqA==} hasBin: true peerDependencies: @@ -3058,7 +3083,7 @@ packages: '@graphql-tools/prisma-loader': 8.0.2(@types/node@20.8.10)(graphql@16.8.1) '@graphql-tools/url-loader': 8.0.0(@types/node@20.8.10)(graphql@16.8.1) '@graphql-tools/utils': 10.0.8(graphql@16.8.1) - '@parcel/watcher': 2.3.0 + '@parcel/watcher': 2.4.0 '@whatwg-node/fetch': 0.8.8 chalk: 4.1.2 cosmiconfig: 8.3.6(typescript@5.2.2) @@ -3124,6 +3149,7 @@ packages: '@graphql-tools/utils': 10.0.8(graphql@16.8.1) graphql: 16.8.1 tslib: 2.5.3 + dev: false /@graphql-codegen/gql-tag-operations@4.0.1(graphql@16.8.1): resolution: {integrity: sha512-qF6wIbBzW8BNT+wiVsBxrYOs2oYcsxQ7mRvCpfEI3HnNZMAST/uX76W8MqFEJvj4mw7NIDv7xYJAcAZIWM5LWw==} @@ -3153,6 +3179,7 @@ packages: import-from: 4.0.0 lodash: 4.17.21 tslib: 2.5.3 + dev: false /@graphql-codegen/schema-ast@4.0.0(graphql@16.8.1): resolution: {integrity: sha512-WIzkJFa9Gz28FITAPILbt+7A8+yzOyd1NxgwFh7ie+EmO9a5zQK6UQ3U/BviirguXCYnn+AR4dXsoDrSrtRA1g==} @@ -3163,6 +3190,7 @@ packages: '@graphql-tools/utils': 10.0.8(graphql@16.8.1) graphql: 16.8.1 tslib: 2.5.3 + dev: false /@graphql-codegen/typed-document-node@5.0.1(graphql@16.8.1): resolution: {integrity: sha512-VFkhCuJnkgtbbgzoCAwTdJe2G1H6sd3LfCrDqWUrQe53y2ukfSb5Ov1PhAIkCBStKCMQBUY9YgGz9GKR40qQ8g==} @@ -3178,6 +3206,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: false /@graphql-codegen/typescript-operations@4.0.1(graphql@16.8.1): resolution: {integrity: sha512-GpUWWdBVUec/Zqo23aFLBMrXYxN2irypHqDcKjN78JclDPdreasAEPcIpMfqf4MClvpmvDLy4ql+djVAwmkjbw==} @@ -3193,6 +3222,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: false /@graphql-codegen/typescript@4.0.1(graphql@16.8.1): resolution: {integrity: sha512-3YziQ21dCVdnHb+Us1uDb3pA6eG5Chjv0uTK+bt9dXeMlwYBU8MbtzvQTo4qvzWVC1AxSOKj0rgfNu1xCXqJyA==} @@ -3208,6 +3238,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: false /@graphql-codegen/visitor-plugin-common@4.0.1(graphql@16.8.1): resolution: {integrity: sha512-Bi/1z0nHg4QMsAqAJhds+ForyLtk7A3HQOlkrZNm3xEkY7lcBzPtiOTLBtvziwopBsXUxqeSwVjOOFPLS5Yw1Q==} @@ -3228,6 +3259,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: false /@graphql-tools/apollo-engine-loader@8.0.0(graphql@16.8.1): resolution: {integrity: sha512-axQTbN5+Yxs1rJ6cWQBOfw3AEeC+fvIuZSfJLPLLvFJLj4pUm9fhxey/g6oQZAAQJqKPfw+tLDUQvnfvRK8Kmg==} @@ -3482,6 +3514,7 @@ packages: '@graphql-tools/utils': 10.0.8(graphql@16.8.1) graphql: 16.8.1 tslib: 2.6.2 + dev: false /@graphql-tools/optimize@2.0.0(graphql@16.8.1): resolution: {integrity: sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==} @@ -3491,6 +3524,7 @@ packages: dependencies: graphql: 16.8.1 tslib: 2.6.2 + dev: false /@graphql-tools/prisma-loader@8.0.2(@types/node@20.8.10)(graphql@16.8.1): resolution: {integrity: sha512-8d28bIB0bZ9Bj0UOz9sHagVPW+6AHeqvGljjERtwCnWl8OCQw2c2pNboYXISLYUG5ub76r4lDciLLTU+Ks7Q0w==} @@ -3538,6 +3572,7 @@ packages: transitivePeerDependencies: - encoding - supports-color + dev: false /@graphql-tools/schema@10.0.0(graphql@16.8.1): resolution: {integrity: sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==} @@ -3550,6 +3585,7 @@ packages: graphql: 16.8.1 tslib: 2.6.2 value-or-promise: 1.0.12 + dev: false /@graphql-tools/url-loader@8.0.0(@types/node@20.8.10)(graphql@16.8.1): resolution: {integrity: sha512-rPc9oDzMnycvz+X+wrN3PLrhMBQkG4+sd8EzaFN6dypcssiefgWKToXtRKI8HHK68n2xEq1PyrOpkjHFJB+GwA==} @@ -3589,6 +3625,7 @@ packages: dset: 3.1.3 graphql: 16.8.1 tslib: 2.6.2 + dev: false /@graphql-tools/wrap@10.0.1(graphql@16.8.1): resolution: {integrity: sha512-Cw6hVrKGM2OKBXeuAGltgy4tzuqQE0Nt7t/uAqnuokSXZhMHXJUb124Bnvxc2gPZn5chfJSDafDe4Cp8ZAVJgg==} @@ -3768,7 +3805,7 @@ packages: react: '>=16' dependencies: '@types/mdx': 2.0.10 - '@types/react': 18.2.37 + '@types/react': 18.2.48 react: 18.2.0 dev: false @@ -3991,8 +4028,8 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@parcel/watcher-android-arm64@2.3.0: - resolution: {integrity: sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==} + /@parcel/watcher-android-arm64@2.4.0: + resolution: {integrity: sha512-+fPtO/GsbYX1LJnCYCaDVT3EOBjvSFdQN9Mrzh9zWAOOfvidPWyScTrHIZHHfJBvlHzNA0Gy0U3NXFA/M7PHUA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] @@ -4000,8 +4037,8 @@ packages: dev: false optional: true - /@parcel/watcher-darwin-arm64@2.3.0: - resolution: {integrity: sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==} + /@parcel/watcher-darwin-arm64@2.4.0: + resolution: {integrity: sha512-T/At5pansFuQ8VJLRx0C6C87cgfqIYhW2N/kBfLCUvDhCah0EnLLwaD/6MW3ux+rpgkpQAnMELOCTKlbwncwiA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] @@ -4009,8 +4046,8 @@ packages: dev: false optional: true - /@parcel/watcher-darwin-x64@2.3.0: - resolution: {integrity: sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==} + /@parcel/watcher-darwin-x64@2.4.0: + resolution: {integrity: sha512-vZMv9jl+szz5YLsSqEGCMSllBl1gU1snfbRL5ysJU03MEa6gkVy9OMcvXV1j4g0++jHEcvzhs3Z3LpeEbVmY6Q==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] @@ -4018,8 +4055,8 @@ packages: dev: false optional: true - /@parcel/watcher-freebsd-x64@2.3.0: - resolution: {integrity: sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==} + /@parcel/watcher-freebsd-x64@2.4.0: + resolution: {integrity: sha512-dHTRMIplPDT1M0+BkXjtMN+qLtqq24sLDUhmU+UxxLP2TEY2k8GIoqIJiVrGWGomdWsy5IO27aDV1vWyQ6gfHA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] @@ -4027,8 +4064,8 @@ packages: dev: false optional: true - /@parcel/watcher-linux-arm-glibc@2.3.0: - resolution: {integrity: sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==} + /@parcel/watcher-linux-arm-glibc@2.4.0: + resolution: {integrity: sha512-9NQXD+qk46RwATNC3/UB7HWurscY18CnAPMTFcI9Y8CTbtm63/eex1SNt+BHFinEQuLBjaZwR2Lp+n7pmEJPpQ==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] @@ -4036,8 +4073,8 @@ packages: dev: false optional: true - /@parcel/watcher-linux-arm64-glibc@2.3.0: - resolution: {integrity: sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==} + /@parcel/watcher-linux-arm64-glibc@2.4.0: + resolution: {integrity: sha512-QuJTAQdsd7PFW9jNGaV9Pw+ZMWV9wKThEzzlY3Lhnnwy7iW23qtQFPql8iEaSFMCVI5StNNmONUopk+MFKpiKg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] @@ -4045,8 +4082,8 @@ packages: dev: false optional: true - /@parcel/watcher-linux-arm64-musl@2.3.0: - resolution: {integrity: sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==} + /@parcel/watcher-linux-arm64-musl@2.4.0: + resolution: {integrity: sha512-oyN+uA9xcTDo/45bwsd6TFHa7Lc7hKujyMlvwrCLvSckvWogndCEoVYFNfZ6JJ2KNL/6fFiGPcbjp8jJmEh5Ng==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] @@ -4054,8 +4091,8 @@ packages: dev: false optional: true - /@parcel/watcher-linux-x64-glibc@2.3.0: - resolution: {integrity: sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==} + /@parcel/watcher-linux-x64-glibc@2.4.0: + resolution: {integrity: sha512-KphV8awJmxU3q52JQvJot0QMu07CIyEjV+2Tb2ZtbucEgqyRcxOBDMsqp1JNq5nuDXtcCC0uHQICeiEz38dPBQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] @@ -4063,8 +4100,8 @@ packages: dev: false optional: true - /@parcel/watcher-linux-x64-musl@2.3.0: - resolution: {integrity: sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==} + /@parcel/watcher-linux-x64-musl@2.4.0: + resolution: {integrity: sha512-7jzcOonpXNWcSijPpKD5IbC6xC7yTibjJw9jviVzZostYLGxbz8LDJLUnLzLzhASPlPGgpeKLtFUMjAAzM+gSA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] @@ -4072,8 +4109,8 @@ packages: dev: false optional: true - /@parcel/watcher-win32-arm64@2.3.0: - resolution: {integrity: sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==} + /@parcel/watcher-win32-arm64@2.4.0: + resolution: {integrity: sha512-NOej2lqlq8bQNYhUMnOD0nwvNql8ToQF+1Zhi9ULZoG+XTtJ9hNnCFfyICxoZLXor4bBPTOnzs/aVVoefYnjIg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] @@ -4081,8 +4118,8 @@ packages: dev: false optional: true - /@parcel/watcher-win32-ia32@2.3.0: - resolution: {integrity: sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==} + /@parcel/watcher-win32-ia32@2.4.0: + resolution: {integrity: sha512-IO/nM+K2YD/iwjWAfHFMBPz4Zqn6qBDqZxY4j2n9s+4+OuTSRM/y/irksnuqcspom5DjkSeF9d0YbO+qpys+JA==} engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] @@ -4090,8 +4127,8 @@ packages: dev: false optional: true - /@parcel/watcher-win32-x64@2.3.0: - resolution: {integrity: sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==} + /@parcel/watcher-win32-x64@2.4.0: + resolution: {integrity: sha512-pAUyUVjfFjWaf/pShmJpJmNxZhbMvJASUpdes9jL6bTEJ+gDxPRSpXTIemNyNsb9AtbiGXs9XduP1reThmd+dA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] @@ -4099,8 +4136,8 @@ packages: dev: false optional: true - /@parcel/watcher@2.3.0: - resolution: {integrity: sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==} + /@parcel/watcher@2.4.0: + resolution: {integrity: sha512-XJLGVL0DEclX5pcWa2N9SX1jCGTDd8l972biNooLFtjneuGqodupPQh6XseXIBBeVIMaaJ7bTcs3qGvXwsp4vg==} engines: {node: '>= 10.0.0'} dependencies: detect-libc: 1.0.3 @@ -4108,18 +4145,18 @@ packages: micromatch: 4.0.5 node-addon-api: 7.0.0 optionalDependencies: - '@parcel/watcher-android-arm64': 2.3.0 - '@parcel/watcher-darwin-arm64': 2.3.0 - '@parcel/watcher-darwin-x64': 2.3.0 - '@parcel/watcher-freebsd-x64': 2.3.0 - '@parcel/watcher-linux-arm-glibc': 2.3.0 - '@parcel/watcher-linux-arm64-glibc': 2.3.0 - '@parcel/watcher-linux-arm64-musl': 2.3.0 - '@parcel/watcher-linux-x64-glibc': 2.3.0 - '@parcel/watcher-linux-x64-musl': 2.3.0 - '@parcel/watcher-win32-arm64': 2.3.0 - '@parcel/watcher-win32-ia32': 2.3.0 - '@parcel/watcher-win32-x64': 2.3.0 + '@parcel/watcher-android-arm64': 2.4.0 + '@parcel/watcher-darwin-arm64': 2.4.0 + '@parcel/watcher-darwin-x64': 2.4.0 + '@parcel/watcher-freebsd-x64': 2.4.0 + '@parcel/watcher-linux-arm-glibc': 2.4.0 + '@parcel/watcher-linux-arm64-glibc': 2.4.0 + '@parcel/watcher-linux-arm64-musl': 2.4.0 + '@parcel/watcher-linux-x64-glibc': 2.4.0 + '@parcel/watcher-linux-x64-musl': 2.4.0 + '@parcel/watcher-win32-arm64': 2.4.0 + '@parcel/watcher-win32-ia32': 2.4.0 + '@parcel/watcher-win32-x64': 2.4.0 dev: false /@peculiar/asn1-schema@2.3.8: @@ -4647,11 +4684,6 @@ packages: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true - /@sindresorhus/fnv1a@2.0.1: - resolution: {integrity: sha512-suq9tRQ6bkpMukTG5K5z0sPWB7t0zExMzZCdmYm6xTSSIm/yCKNm7VCL36wVeyTsFr597/UhU1OAYdHGMDiHrw==} - engines: {node: '>=10'} - dev: true - /@sindresorhus/slugify@1.1.2: resolution: {integrity: sha512-V9nR/W0Xd9TSGXpZ4iFUcFGhuOJtZX82Fzxj1YISlbSgKvIiNa7eLEZrT0vAraPOt++KHauIVNYgGRgjc13dXA==} engines: {node: '>=10'} @@ -5048,7 +5080,7 @@ packages: /@types/react-dom@18.0.0: resolution: {integrity: sha512-49897Y0UiCGmxZqpC8Blrf6meL8QUla6eb+BBhn69dTXlmuOlzkfr7HHY/O8J25e1lTUMs+YYxSlVDAaGHCOLg==} dependencies: - '@types/react': 18.2.37 + '@types/react': 18.2.48 /@types/react-dom@18.2.15: resolution: {integrity: sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==} @@ -5063,6 +5095,13 @@ packages: '@types/scheduler': 0.16.7 csstype: 3.1.2 + /@types/react@18.2.48: + resolution: {integrity: sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==} + dependencies: + '@types/prop-types': 15.7.11 + '@types/scheduler': 0.16.7 + csstype: 3.1.2 + /@types/scheduler@0.16.7: resolution: {integrity: sha512-8g25Nl3AuB1KulTlSUsUhUo/oBgBU6XIXQ+XURpeioEbEJvkO7qI4vDfREv3vJYHHzqXjcAHvoJy4pTtSQNZtA==} @@ -5087,8 +5126,8 @@ packages: dependencies: '@types/node': 20.10.3 - /@typescript-eslint/parser@6.13.1(eslint@8.0.0)(typescript@5.2.2): - resolution: {integrity: sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==} + /@typescript-eslint/parser@6.19.0(eslint@8.0.0)(typescript@5.2.2): + resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -5097,10 +5136,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.13.1 - '@typescript-eslint/types': 6.13.1 - '@typescript-eslint/typescript-estree': 6.13.1(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.13.1 + '@typescript-eslint/scope-manager': 6.19.0 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 eslint: 8.0.0 typescript: 5.2.2 @@ -5108,21 +5147,21 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.13.1: - resolution: {integrity: sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==} + /@typescript-eslint/scope-manager@6.19.0: + resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.13.1 - '@typescript-eslint/visitor-keys': 6.13.1 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 dev: true - /@typescript-eslint/types@6.13.1: - resolution: {integrity: sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==} + /@typescript-eslint/types@6.19.0: + resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.13.1(typescript@5.2.2): - resolution: {integrity: sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==} + /@typescript-eslint/typescript-estree@6.19.0(typescript@5.2.2): + resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -5130,11 +5169,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.13.1 - '@typescript-eslint/visitor-keys': 6.13.1 + '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/visitor-keys': 6.19.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 + minimatch: 9.0.3 semver: 7.5.4 ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 @@ -5142,11 +5182,11 @@ packages: - supports-color dev: true - /@typescript-eslint/visitor-keys@6.13.1: - resolution: {integrity: sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==} + /@typescript-eslint/visitor-keys@6.19.0: + resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.13.1 + '@typescript-eslint/types': 6.19.0 eslint-visitor-keys: 3.4.3 dev: true @@ -5455,6 +5495,10 @@ packages: is-string: 1.0.7 dev: true + /array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + dev: false + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -5520,6 +5564,7 @@ packages: /asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: false /asn1js@3.0.5: resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} @@ -5557,6 +5602,7 @@ packages: /auto-bind@4.0.0: resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} engines: {node: '>=8'} + dev: false /autoprefixer@10.0.1(postcss@8.4.31): resolution: {integrity: sha512-aQo2BDIsoOdemXUAOBpFv4ZQa2DrOtEufarYhtFsK1088Ca0TUwu/aQWf0M3mrILXZ3mTIVn1lR3hPW8acacsw==} @@ -5653,6 +5699,7 @@ packages: /babel-plugin-syntax-trailing-function-commas@7.0.0-beta.0: resolution: {integrity: sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==} + dev: false /babel-preset-fbjs@3.4.0(@babel/core@7.23.5): resolution: {integrity: sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==} @@ -5687,6 +5734,7 @@ packages: '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.23.5) '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.23.5) babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0 + dev: false /bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -5780,6 +5828,7 @@ packages: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} dependencies: node-int64: 0.4.0 + dev: false /buffer@4.9.2: resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} @@ -5846,6 +5895,7 @@ packages: dependencies: pascal-case: 3.1.2 tslib: 2.6.2 + dev: false /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} @@ -5879,6 +5929,7 @@ packages: no-case: 3.0.4 tslib: 2.6.2 upper-case-first: 2.0.2 + dev: false /ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -5939,6 +5990,7 @@ packages: title-case: 3.0.3 upper-case: 2.0.2 upper-case-first: 2.0.2 + dev: false /change-case@4.1.2: resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} @@ -5955,6 +6007,7 @@ packages: sentence-case: 3.0.4 snake-case: 3.0.4 tslib: 2.6.2 + dev: false /character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -6135,9 +6188,21 @@ packages: engines: {node: ^12.20.0 || >=14} dev: true + /comment-json@4.2.3: + resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + engines: {node: '>= 6'} + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + dev: false + /common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} + dev: false /compute-scroll-into-view@3.1.0: resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} @@ -6168,6 +6233,7 @@ packages: no-case: 3.0.4 tslib: 2.6.2 upper-case: 2.0.2 + dev: false /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} @@ -6199,6 +6265,10 @@ packages: browserslist: 4.22.1 dev: true + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + /cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} dependencies: @@ -6236,12 +6306,14 @@ packages: node-fetch: 2.7.0 transitivePeerDependencies: - encoding + dev: false /cross-inspect@1.0.0: resolution: {integrity: sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==} engines: {node: '>=16.0.0'} dependencies: tslib: 2.6.2 + dev: false /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -6761,6 +6833,7 @@ packages: /dependency-graph@0.11.0: resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} engines: {node: '>= 0.6.0'} + dev: false /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} @@ -6870,6 +6943,7 @@ packages: /dset@3.1.3: resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} engines: {node: '>=4'} + dev: false /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -7137,11 +7211,11 @@ packages: dependencies: '@next/eslint-plugin-next': 14.0.3 '@rushstack/eslint-patch': 1.6.0 - '@typescript-eslint/parser': 6.13.1(eslint@8.0.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.19.0(eslint@8.0.0)(typescript@5.2.2) eslint: 8.0.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.0.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.0.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.0.0) eslint-plugin-react: 7.33.2(eslint@8.0.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.0.0) @@ -7161,7 +7235,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.0.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.0.0): resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -7171,8 +7245,8 @@ packages: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.0.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) fast-glob: 3.3.1 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -7184,7 +7258,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -7205,16 +7279,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.13.1(eslint@8.0.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.19.0(eslint@8.0.0)(typescript@5.2.2) debug: 3.2.7 eslint: 8.0.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.0.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.0.0) transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0): + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0): resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: @@ -7224,7 +7298,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.13.1(eslint@8.0.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.19.0(eslint@8.0.0)(typescript@5.2.2) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -7233,7 +7307,7 @@ packages: doctrine: 2.1.0 eslint: 8.0.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.13.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.0.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -7649,9 +7723,11 @@ packages: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} dependencies: bser: 2.1.1 + dev: false /fbjs-css-vars@1.0.2: resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + dev: false /fbjs@3.0.5: resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} @@ -7665,6 +7741,7 @@ packages: ua-parser-js: 1.0.37 transitivePeerDependencies: - encoding + dev: false /figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} @@ -7973,6 +8050,14 @@ packages: dependencies: get-intrinsic: 1.2.2 + /gql.tada@1.0.1(graphql@16.8.1): + resolution: {integrity: sha512-OZ6+O3eIOwGG4xXpoVKK1TWMEitFWK5QLd4sUMrPZMlLJdd7zGD6hE3YkM6AatriJYX45wE0QD4SYHOVn9ySXA==} + dependencies: + '@0no-co/graphql.web': 1.0.4(graphql@16.8.1) + transitivePeerDependencies: + - graphql + dev: false + /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -8010,17 +8095,6 @@ packages: - utf-8-validate dev: false - /graphql-language-service@5.2.0(graphql@16.8.1): - resolution: {integrity: sha512-o/ZgTS0pBxWm3hSF4+6GwiV1//DxzoLWEbS38+jqpzzy1d/QXBidwQuVYTOksclbtOJZ3KR/tZ8fi/tI6VpVMg==} - hasBin: true - peerDependencies: - graphql: ^15.5.0 || ^16.0.0 - dependencies: - graphql: 16.8.1 - nullthrows: 1.1.1 - vscode-languageserver-types: 3.17.5 - dev: true - /graphql-request@6.1.0(graphql@16.8.1): resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} peerDependencies: @@ -8051,6 +8125,7 @@ packages: dependencies: graphql: 16.8.1 tslib: 2.6.2 + dev: false /graphql-ws@5.14.2(graphql@16.8.1): resolution: {integrity: sha512-LycmCwhZ+Op2GlHz4BZDsUYHKRiiUz+3r9wbhBATMETNlORQJAaFlAgTFoeRh6xQoQegwYwIylVD1Qns9/DA3w==} @@ -8117,6 +8192,11 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + /has-own-prop@2.0.0: + resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} + engines: {node: '>=8'} + dev: false + /has-property-descriptors@1.0.1: resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} dependencies: @@ -8284,6 +8364,7 @@ packages: dependencies: capital-case: 1.0.4 tslib: 2.6.2 + dev: false /heap@0.2.7: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} @@ -8405,6 +8486,7 @@ packages: /immutable@3.7.6: resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} engines: {node: '>=0.8.0'} + dev: false /immutable@4.3.4: resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} @@ -8420,6 +8502,7 @@ packages: /import-from@4.0.0: resolution: {integrity: sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==} engines: {node: '>=12.2'} + dev: false /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -8490,6 +8573,7 @@ packages: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} dependencies: loose-envify: 1.4.0 + dev: false /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -8502,6 +8586,7 @@ packages: dependencies: is-relative: 1.0.0 is-windows: 1.0.2 + dev: false /is-alphabetical@2.0.1: resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} @@ -8642,6 +8727,7 @@ packages: resolution: {integrity: sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==} dependencies: tslib: 2.6.2 + dev: false /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} @@ -8702,6 +8788,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-unc-path: 1.0.0 + dev: false /is-set@2.0.2: resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} @@ -8765,6 +8852,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: unc-path-regex: 0.1.2 + dev: false /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} @@ -8775,6 +8863,7 @@ packages: resolution: {integrity: sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==} dependencies: tslib: 2.6.2 + dev: false /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} @@ -9166,6 +9255,7 @@ packages: resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} dependencies: tslib: 2.6.2 + dev: false /lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -9175,6 +9265,7 @@ packages: /lru-cache@10.0.1: resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} engines: {node: 14 || >=16.14} + dev: false /lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -9209,6 +9300,7 @@ packages: /map-cache@0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} engines: {node: '>=0.10.0'} + dev: false /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} @@ -9958,6 +10050,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -10254,6 +10353,7 @@ packages: /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: false /node-releases@2.0.13: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} @@ -10320,6 +10420,7 @@ packages: /nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + dev: false /num2fraction@1.2.2: resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==} @@ -10518,6 +10619,7 @@ packages: dependencies: dot-case: 3.0.4 tslib: 2.6.2 + dev: false /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -10545,6 +10647,7 @@ packages: is-absolute: 1.0.0 map-cache: 0.2.2 path-root: 0.1.1 + dev: false /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} @@ -10587,12 +10690,14 @@ packages: dependencies: no-case: 3.0.4 tslib: 2.6.2 + dev: false /path-case@3.0.4: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} dependencies: dot-case: 3.0.4 tslib: 2.6.2 + dev: false /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -10622,12 +10727,14 @@ packages: /path-root-regex@0.1.2: resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} engines: {node: '>=0.10.0'} + dev: false /path-root@0.1.1: resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} engines: {node: '>=0.10.0'} dependencies: path-root-regex: 0.1.2 + dev: false /path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -10889,6 +10996,7 @@ packages: resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} dependencies: asap: 2.0.6 + dev: false /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -11216,6 +11324,7 @@ packages: invariant: 2.2.4 transitivePeerDependencies: - encoding + dev: false /remark-gfm@3.0.1: resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} @@ -11290,6 +11399,11 @@ packages: resolution: {integrity: sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==} dev: false + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: false + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -11528,6 +11642,7 @@ packages: no-case: 3.0.4 tslib: 2.6.2 upper-case-first: 2.0.2 + dev: false /serve-static@1.15.0: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} @@ -11568,6 +11683,7 @@ packages: /setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: false /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -11625,6 +11741,7 @@ packages: /signedsource@1.0.0: resolution: {integrity: sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==} + dev: false /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -11743,6 +11860,7 @@ packages: resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} dependencies: tslib: 2.6.2 + dev: false /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -12035,6 +12153,7 @@ packages: resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} dependencies: tslib: 2.6.2 + dev: false /swr@2.2.4(react@18.2.0): resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} @@ -12136,6 +12255,7 @@ packages: resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} dependencies: tslib: 2.6.2 + dev: false /title@3.5.3: resolution: {integrity: sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==} @@ -12233,6 +12353,7 @@ packages: /tslib@2.5.3: resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} + dev: false /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -12428,6 +12549,7 @@ packages: /ua-parser-js@1.0.37: resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + dev: false /ufo@1.3.2: resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} @@ -12445,6 +12567,7 @@ packages: /unc-path-regex@0.1.2: resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} engines: {node: '>=0.10.0'} + dev: false /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -12635,11 +12758,13 @@ packages: resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} dependencies: tslib: 2.6.2 + dev: false /upper-case@2.0.2: resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} dependencies: tslib: 2.6.2 + dev: false /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -12735,6 +12860,7 @@ packages: /value-or-promise@1.0.12: resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} engines: {node: '>=12'} + dev: false /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} @@ -12796,7 +12922,7 @@ packages: debug: 4.3.4 pathe: 1.1.1 picocolors: 1.0.0 - vite: 5.0.6(@types/node@20.8.10) + vite: 5.0.11(@types/node@20.8.10) transitivePeerDependencies: - '@types/node' - less @@ -12825,6 +12951,42 @@ packages: - supports-color dev: false + /vite@5.0.11(@types/node@20.8.10): + resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.8.10 + esbuild: 0.19.8 + postcss: 8.4.32 + rollup: 4.6.1 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vite@5.0.6(@types/node@20.8.10): resolution: {integrity: sha512-MD3joyAEBtV7QZPl2JVVUai6zHms3YOmLR+BpMzLlX2Yzjfcc4gTgNi09d/Rua3F4EtC8zdwPU8eQYyib4vVMQ==} engines: {node: ^18.0.0 || >=20.0.0} @@ -12904,7 +13066,7 @@ packages: strip-literal: 1.3.0 tinybench: 2.5.1 tinypool: 0.8.1 - vite: 5.0.6(@types/node@20.8.10) + vite: 5.0.11(@types/node@20.8.10) vite-node: 1.0.4(@types/node@20.8.10) why-is-node-running: 2.2.2 transitivePeerDependencies: @@ -12917,10 +13079,6 @@ packages: - terser dev: true - /vscode-languageserver-types@3.17.5: - resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} - dev: true - /vscode-oniguruma@1.7.0: resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} dev: false diff --git a/website/src/pages/docs/client/_meta.json b/website/src/pages/docs/client/_meta.json index 6eca25e0..cb3d53be 100644 --- a/website/src/pages/docs/client/_meta.json +++ b/website/src/pages/docs/client/_meta.json @@ -1,6 +1,7 @@ { "index": "Overview", "best-practices": "Best practices", + "types": "Types", "javascript": "JavaScript frameworks", "other": "Other languages" } diff --git a/website/src/pages/docs/client/best-practices.mdx b/website/src/pages/docs/client/best-practices.mdx index af2074da..18011bf3 100644 --- a/website/src/pages/docs/client/best-practices.mdx +++ b/website/src/pages/docs/client/best-practices.mdx @@ -17,9 +17,9 @@ this way when you need more data for your component you know exactly where to ad you don't have to go up your component-tree to find the `query` responsible for adding the data. ```tsx -import { FragmentType, graphql, useFragment } from '@/fuse' +import { FragmentType, graphql, readFragment } from '@/fuse' -const UserFields = graphql(` +export const UserFields = graphql(` fragment Avatar_UserFields on User { firstName avatarUrl @@ -27,9 +27,9 @@ const UserFields = graphql(` `) export const Avatar = (props: { - user: FragmentType + user: FragmentOf }) => { - const user = useFragment(UserFields, props.user) + const user = readFragment(UserFields, props.user) return (
    @@ -44,6 +44,7 @@ The above defined fragment is now globally available and we can add it to our qu ```tsx import { graphql } from '@/fuse' +import { UserFields } from './Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -51,7 +52,7 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [UserFields]) ``` From now on out, every time we need a new field in the `Avatar` component we can just add it there @@ -123,18 +124,14 @@ Now when we spread it in our `Blog` page we can easily see that it relates to th inspect the GraphQL document being sent to the server we can also derive that this is meant for that component. -### `useFragment` and `FragmentType` +### `readFragment` and `FragmentOf` -You'll see that we use this `useFragment` function in our components that have a fragment describing their +You'll see that we use this `readFragment` function in our components that have a fragment describing their data-requirements, this helper ensures that we remove any extraneous fields and type the output correctly. -Another thing worth noting is how we type the `props`, we use this `FragmentType` helper which ensures that +Another thing worth noting is how we type the `props`, we use this `FragmentOf` helper which ensures that the parent-component uses the fragment and passes that into props, this means that if the parent-component would define all the fields of the fragment manually and not spread it that we would show a warning. - - Note that even though this function is called `useFragment`, it is **not a React hook and you need to use it in server components too**. - - ## Top-level queries One of the benefits that comes with describing the data you need is that you perform 1 request and get 1 response, diff --git a/website/src/pages/docs/client/index.mdx b/website/src/pages/docs/client/index.mdx index e76dbb41..188e4f4e 100644 --- a/website/src/pages/docs/client/index.mdx +++ b/website/src/pages/docs/client/index.mdx @@ -33,7 +33,7 @@ Let's go over each file: client components to talk to your API. - [`fuse/server.ts`](/docs/basics/client/server-components): This is the main entry-point for React server components and server actions. It exports an `execute` function which takes a `Document` and `variables` and will execute the operation in-process without an extra HTTP request to the API. -- [`fuse/fragment-masking.ts`](/docs/basics/client/best-practices): The `useFragment` and `FragmentType` helpers are exported from here, +- [`fuse/fragment-masking.ts`](/docs/basics/client/best-practices): The `readFragment` and `FragmentOf` helpers are exported from here, these helpers basically ensure that the props you pass in will be reduced to the selection of fields of your fragment. - `fuse/gql.ts`: The `graphql()` function is exported from here, this helper ensures that both the `Result` diff --git a/website/src/pages/docs/client/javascript/angular.mdx b/website/src/pages/docs/client/javascript/angular.mdx index 4bfae779..ca7cff67 100644 --- a/website/src/pages/docs/client/javascript/angular.mdx +++ b/website/src/pages/docs/client/javascript/angular.mdx @@ -7,7 +7,7 @@ Constructing a typed-document-node for a query: ```tsx import { graphql } from '../fuse' -import { Avatar } from './components/Avatar' +import { Avatar, AvatarFragment } from './components/Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -16,21 +16,21 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) ``` and for a fragment: ```tsx -import { graphql, useFragment, FragmentType } from '../../fuse' +import { graphql, readFragment, FragmentOf } from '../../fuse' -const AvatarFragment = graphql(` +export const AvatarFragment = graphql(` fragment Avatar_UserFields on User { name avatarUrl } `) -// Derive the input-type: FragmentType -// Apply fragment-masking: useFragment(AvatarFragment, user); +// Derive the input-type: FragmentOf +// Apply fragment-masking: readFragment(AvatarFragment, user); ``` diff --git a/website/src/pages/docs/client/javascript/nextjs.mdx b/website/src/pages/docs/client/javascript/nextjs.mdx index 5048d02c..563c37ce 100644 --- a/website/src/pages/docs/client/javascript/nextjs.mdx +++ b/website/src/pages/docs/client/javascript/nextjs.mdx @@ -49,6 +49,7 @@ Querying data cna be done by using the `useQuery` hook from your generated fuse ```tsx import { useQuery } from '@/fuse/client' import { graphql } from '@/fuse' +import { AvatarFragment } from './Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -56,7 +57,7 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) function User() { const [result] = useQuery({ @@ -71,6 +72,7 @@ When you need to reach into your mutatation entry points we supply `useMutation` ```tsx import { graphql } from '@/fuse' import { useMutation } from '@/fuse/client' +import { AvatarFragment } from './Avatar' const UpdateUser = graphql(` mutation UpdateUser ($id: ID!, firstName: $String!) { @@ -78,7 +80,7 @@ const UpdateUser = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) const UpdateUser = () => { const [result, update] = useMutation(UpdateUser) @@ -106,6 +108,7 @@ that is available on the data. import { useMemo } from 'react' import { graphql } from '@/fuse' import { useQuery } from '@/fuse/client' +import { AvatarFragment } from './Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -113,7 +116,7 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) const User = () => { const [result] = useQuery({ @@ -238,6 +241,7 @@ import { fetchExchange, } from '@/fuse/pages' import { graphql } from '@/fuse' +import { AvatarFragment } from './Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -245,7 +249,7 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) function User() { const [result] = useQuery({ diff --git a/website/src/pages/docs/client/javascript/react.mdx b/website/src/pages/docs/client/javascript/react.mdx index 549990ce..4562af3f 100644 --- a/website/src/pages/docs/client/javascript/react.mdx +++ b/website/src/pages/docs/client/javascript/react.mdx @@ -37,7 +37,7 @@ coming from the `Avatar` component. import * as React from 'react' import { graphql, useQuery } from '../fuse' -import { Avatar } from './components/Avatar' +import { Avatar, AvatarFragment } from './components/Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -46,7 +46,7 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) const App = () => { const [result] = useQuery({ query: UserQuery, variables: { id: '1' } }) @@ -66,9 +66,9 @@ In the `Avatar` component we can now use the fragment to render what we need. ```tsx import * as React from 'react' -import { graphql, useFragment, FragmentType } from '../../fuse' +import { graphql, readFragment, FragmentOf } from '../../fuse' -const AvatarFragment = graphql(` +export const AvatarFragment = graphql(` fragment Avatar_UserFields on User { name avatarUrl @@ -76,9 +76,9 @@ const AvatarFragment = graphql(` `) export const Avatar = (props: { - user: FragmentType + user: FragmentOf }) => { - const user = useFragment(AvatarFragment, props.user) + const user = readFragment(AvatarFragment, props.user) return ( {user.name} @@ -93,6 +93,7 @@ Mutations work in a similar way, we can use the `useMutation` hook to execute a ```tsx import * as React from 'react' import { graphql, useMutation } from '../fuse' +import { AvatarFragment } from './components/Avatar' const UpdateUser = graphql(` mutation UpdateUser ($id: ID!, firstName: $String!) { @@ -100,7 +101,7 @@ const UpdateUser = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) const UpdateUser = () => { const [result, update] = useMutation(UpdateUser) diff --git a/website/src/pages/docs/client/javascript/vue.mdx b/website/src/pages/docs/client/javascript/vue.mdx index 27759363..2ecb47d7 100644 --- a/website/src/pages/docs/client/javascript/vue.mdx +++ b/website/src/pages/docs/client/javascript/vue.mdx @@ -8,7 +8,7 @@ Constructing a typed-document-node for a query: ```tsx import { graphql } from '../fuse' -import { Avatar } from './components/Avatar' +import { Avatar, AvatarFragment } from './components/Avatar' const UserQuery = graphql(` query User ($id: ID!) { @@ -17,21 +17,21 @@ const UserQuery = graphql(` ...Avatar_UserFields } } -`) +`, [AvatarFragment]) ``` and for a fragment: ```tsx -import { graphql, useFragment, FragmentType } from '../../fuse' +import { graphql, readFragment, FragmentOf } from '../../fuse' -const AvatarFragment = graphql(` +export const AvatarFragment = graphql(` fragment Avatar_UserFields on User { name avatarUrl } `) -// Derive the input-type: FragmentType -// Apply fragment-masking: useFragment(AvatarFragment, user); +// Derive the input-type: FragmentOf +// Apply fragment-masking: readFragment(AvatarFragment, user); ``` diff --git a/website/src/pages/docs/client/types.mdx b/website/src/pages/docs/client/types.mdx new file mode 100644 index 00000000..b9b0149d --- /dev/null +++ b/website/src/pages/docs/client/types.mdx @@ -0,0 +1,38 @@ +# Type generation + +By default fuse will use [`gql.tada`](https://gql-tada.0no.co/) to type your GraphQL documents. + +Folks who have been with fuse longer might still be on the GraphQL Code Generator default, +we still support this! We'll check whether `tadaOutputLocation` is set in the `tsconfig` and +whether you have `gql.tada` intalled. If not, we'll fall back to the GraphQL Code Generator. + +The biggest difference between the two in terms of writing code is that fragments in `gql.tada` +aren't global which means you'll have to explicitly add them in the second argument of the `graphql` +function. + +```ts +const UserQuery = graphql(` + query User { + user(id: "1") { + id + ...UserFields + } + } +`, [UserFragment]) // needed in tada but not codegen. +``` + +The other difference is that `gql.tada` will calculate everything at runtime while with codegen +there will always be a background process running to calculate the types. + +## Migrating to gql.tada + +To migrate to `gql.tada` we'll need to ensure that the LSP is working correctly and is upgraded to v1, +when that is working we can install `gql.tada` and add `tadaOutputLocation: '{src}/fuse/introspection.ts'` to +the graphqlsp config in the `tsconfig` file. + +After that you can delete the `fragment-masking`, `gql` and `graphql` typescript files which are present in +the `fuse` folder. + +## Opting out of gql.tada + +You can opt out of `gql.tada by` uninstalling the package and removing `tadaOutputLocation` from the `tsconfig`.